144 lines
3.6 KiB
Go
144 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"strings"
|
|
|
|
"zombiezen.com/go/sqlite"
|
|
"zombiezen.com/go/sqlite/sqlitex"
|
|
)
|
|
|
|
type Result struct{ Expected, Actual fs.FileMode }
|
|
|
|
type SQLiteEmitter struct {
|
|
conn *sqlite.Conn
|
|
}
|
|
|
|
func (s *SQLiteEmitter) Close() error {
|
|
return s.conn.Close()
|
|
}
|
|
|
|
func sqlViewColSpec() string {
|
|
var cols []string
|
|
var whos = []rune{'o', 'g', 'u'}
|
|
var whats = []rune{'x', 'w', 'r'}
|
|
for _, fieldName := range []string{"expected", "actual"} {
|
|
cols = append(cols, fmt.Sprintf("%s", fieldName))
|
|
for iwho, who := range whos {
|
|
cols = append(cols, fmt.Sprintf("%[1]s & (7 << %[3]d * 3) >> (%[3]d * 3) AS %[1]s_%[2]c", fieldName, who, iwho))
|
|
for iwhat, what := range whats {
|
|
cols = append(cols, fmt.Sprintf("%[1]s & (1 << %[3]d * 3 + %[5]d) >> (%[3]d * 3 + %[5]d) AS %[1]s_%[2]c%[4]c", fieldName, who, iwho, what, iwhat))
|
|
}
|
|
}
|
|
}
|
|
return strings.Join(cols, ",\n")
|
|
}
|
|
|
|
const createTableFile = `CREATE TABLE file_result_raw (
|
|
expected INT NOT NULL,
|
|
actual INT NOT NULL
|
|
);`
|
|
|
|
var createViewFile string = `CREATE VIEW file_result AS
|
|
SELECT
|
|
` + sqlViewColSpec() + `
|
|
FROM file_result_raw;`
|
|
|
|
var createTableDir = strings.ReplaceAll(createTableFile, "file_result", "dir_result")
|
|
var createViewDir = strings.ReplaceAll(createViewFile, "file_result", "dir_result")
|
|
|
|
func NewSQLite(path string) (*SQLiteEmitter, error) {
|
|
conn, err := sqlite.OpenConn(path, sqlite.OpenCreate|sqlite.OpenReadWrite|sqlite.OpenWAL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
script := strings.Join([]string{createTableFile, createTableDir, createViewFile, createViewDir}, "\n")
|
|
fmt.Println(script)
|
|
err = sqlitex.ExecuteScript(conn, script, &sqlitex.ExecOptions{})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("NewSQLite: cannot create schema: %w", err)
|
|
}
|
|
// err = sqlitex.Execute(conn, createTableFile, &sqlitex.ExecOptions{})
|
|
// if err != nil {
|
|
// return nil, fmt.Errorf("NewSQLite: cannot create table: %w", err)
|
|
// }
|
|
// err = sqlitex.Execute(conn, createViewFile, &sqlitex.ExecOptions{})
|
|
// if err != nil {
|
|
// return nil, fmt.Errorf("NewSQLite: cannot create view: %w", err)
|
|
// }
|
|
return &SQLiteEmitter{
|
|
conn: conn,
|
|
}, nil
|
|
}
|
|
|
|
func (s *SQLiteEmitter) Emit(tablePrefix string) func(r Result) error {
|
|
query := fmt.Sprintf("INSERT INTO %sresult_raw(expected, actual) VALUES (?, ?)", tablePrefix)
|
|
return func(r Result) error {
|
|
return sqlitex.Execute(s.conn, query, &sqlitex.ExecOptions{
|
|
Args: []any{r.Expected, r.Actual},
|
|
})
|
|
}
|
|
}
|
|
|
|
func createFile(dir, pattern string) (path string, err error) {
|
|
f, err := os.CreateTemp(dir, pattern)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
f.Close()
|
|
return f.Name(), nil
|
|
}
|
|
|
|
func getData(create func(string, string) (string, error), emit func(Result) error) (err error) {
|
|
path, err := create("", "go-perm-test-*")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for mode := fs.FileMode(0); mode <= os.ModePerm; mode++ {
|
|
err := os.Chmod(path, mode)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot set mode 0%03o on %s: %w", mode, path, err)
|
|
}
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot stat %s: %w", path, err)
|
|
}
|
|
result := Result{
|
|
Expected: mode,
|
|
Actual: info.Mode(),
|
|
}
|
|
err = emit(result)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func run() error {
|
|
if len(os.Args) < 2 {
|
|
fmt.Fprintf(os.Stderr, "usage: %s <filename>", os.Args[0])
|
|
}
|
|
|
|
dbPath := os.Args[1]
|
|
db, err := NewSQLite(dbPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer db.Close()
|
|
|
|
return errors.Join(getData(createFile, db.Emit("file_")), getData(os.MkdirTemp, db.Emit("dir_")))
|
|
}
|
|
|
|
func main() {
|
|
err := run()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err)
|
|
os.Exit(1)
|
|
}
|
|
}
|