aboutsummaryrefslogtreecommitdiff
path: root/generator.go
diff options
context:
space:
mode:
authorJan Mercl <0xjnml@gmail.com>2017-07-01 23:04:53 +0200
committerJan Mercl <0xjnml@gmail.com>2017-07-01 23:04:53 +0200
commit5e8a085cfb2f6df373a2a68436b1c1acacba592b (patch)
tree6cd0e355f252b4e45331b7e476904c9b588ddce5 /generator.go
parent8370d1a12ed5bbad6630675316ee3985d8372a7b (diff)
Add a couple of tests. Build only on linux, do not pass.
modified: Makefile modified: all_test.go modified: generator.go modified: internal/bin/bin_linux_386.go modified: internal/bin/bin_linux_amd64.go new file: internal/mptest/mptest_linux_386.go new file: internal/mptest/mptest_linux_amd64.go new file: internal/threadtest1/threadtest1_linux_386.go new file: internal/threadtest1/threadtest1_linux_amd64.go new file: internal/threadtest2/threadtest2_linux_386.go new file: internal/threadtest2/threadtest2_linux_amd64.go new file: internal/threadtest4/threadtest4_linux_386.go new file: internal/threadtest4/threadtest4_linux_amd64.go modified: main.c new file: sqlite.h new file: testdata/mptest/config01.test new file: testdata/mptest/config02.test new file: testdata/mptest/crash01.test new file: testdata/mptest/crash02.subtest new file: testdata/mptest/multiwrite01.test
Diffstat (limited to 'generator.go')
-rw-r--r--generator.go336
1 files changed, 288 insertions, 48 deletions
diff --git a/generator.go b/generator.go
index adcf212..f813ce4 100644
--- a/generator.go
+++ b/generator.go
@@ -12,6 +12,7 @@ import (
"fmt"
"go/format"
"go/scanner"
+ "go/token"
"io"
"io/ioutil"
"os"
@@ -45,12 +46,17 @@ var (
)
const (
- prologue = `/*
+ sqliteRepo = "sqlite.org"
+ version = "3190300"
+
+ prologueSqlite = `// Code generated by ccgo. DO NOT EDIT.
+
+/*
%s
*/
-// Code generated by ccgo DO NOT EDIT.
+%s
package bin
@@ -71,6 +77,43 @@ func ftrace(s string, args ...interface{}) {
os.Stderr.Sync()
}
`
+
+ prologueTest = `// Code generated by ccgo. DO NOT EDIT.
+
+%s
+
+package main
+
+import (
+ "math"
+ "os"
+ "unsafe"
+
+ "github.com/cznic/crt"
+ "github.com/cznic/sqlite/internal/bin"
+)
+
+var argv []*int8
+
+func main() {
+ for _, v := range os.Args {
+ argv = append(argv, (*int8)(crt.CString(v)))
+ }
+ argv = append(argv, nil)
+ X_start(crt.NewTLS(), int32(len(os.Args)), &argv[0])
+}
+
+`
+
+ defines = `
+ #define HAVE_MALLOC_H 1
+ #define HAVE_MALLOC_USABLE_SIZE 1
+ #define HAVE_USLEEP 1
+ #define SQLITE_DEBUG 1
+ #define SQLITE_ENABLE_API_ARMOR 1
+ #define SQLITE_USE_URI 1
+ #define SQLITE_WITHOUT_MSIZE 1
+ `
)
func findRepo(s string) string {
@@ -121,32 +164,29 @@ func errStr(err error) string {
}
}
-func unconvert(pth string) {
- wd, err := os.Getwd()
- if err != nil {
- log.Fatal(err)
- }
-
- defer func() {
- if err := os.Chdir(wd); err != nil {
- log.Fatal(err)
- }
- }()
-
- if err := os.Chdir(filepath.Dir(pth)); err != nil {
- log.Fatal(err)
- }
-
- if out, err := exec.Command(unconvertBin, "-apply").CombinedOutput(); err != nil {
- log.Fatalf("unconvert: %s\n%s", err, out)
- }
-}
-
-func build(predef string, tus [][]string, opts ...cc.Opt) ([]*cc.TranslationUnit, []byte) {
+func build(predef string, tus [][]string, qualifiers []string, opts ...cc.Opt) ([]*cc.TranslationUnit, []byte) {
ndbg := ""
if *ndebug {
ndbg = "#define NDEBUG 1"
}
+
+ var lpos token.Position
+ if *cpp {
+ opts = append(opts, cc.Cpp(func(toks []xc.Token) {
+ if len(toks) != 0 {
+ p := toks[0].Position()
+ if p.Filename != lpos.Filename {
+ fmt.Fprintf(os.Stderr, "# %d %q\n", p.Line, p.Filename)
+ }
+ lpos = p
+ }
+ for _, v := range toks {
+ os.Stderr.WriteString(cc.TokSrc(v))
+ }
+ os.Stderr.WriteString("\n")
+ }))
+ }
+
var build []*cc.TranslationUnit
tus = append(tus, []string{ccir.CRT0Path})
for _, src := range tus {
@@ -173,6 +213,7 @@ func build(predef string, tus [][]string, opts ...cc.Opt) ([]*cc.TranslationUnit
cc.EnableNonConstStaticInitExpressions(),
cc.EnableWideBitFieldTypes(),
cc.ErrLimit(*errLimit),
+ cc.KeepComments(),
cc.SysIncludePaths([]string{ccir.LibcIncludePath}),
}, opts...)...,
)
@@ -184,7 +225,7 @@ func build(predef string, tus [][]string, opts ...cc.Opt) ([]*cc.TranslationUnit
}
var out buffer.Bytes
- if err := ccgo.New(build, &out); err != nil {
+ if err := ccgo.New(build, &out, ccgo.Packages(qualifiers)); err != nil {
log.Fatal(err)
}
@@ -255,36 +296,125 @@ func macros(buf io.Writer, ast *cc.TranslationUnit) {
fmt.Fprintf(buf, ")\n")
}
-func main() {
- const repo = "sqlite.org/sqlite-amalgamation-3190300/"
+func unconvert(pth string) {
+ wd, err := os.Getwd()
+ if err != nil {
+ log.Fatal(err)
+ }
- log.SetFlags(log.Lshortfile | log.Lmicroseconds)
- var err error
- if unconvertBin, err = exec.LookPath("unconvert"); err != nil {
- log.Fatal("Please install the unconvert tool (go get -u github.com/mdempsky/unconvert)")
+ defer func() {
+ if err := os.Chdir(wd); err != nil {
+ log.Fatal(err)
+ }
+ }()
+
+ if err := os.Chdir(filepath.Dir(pth)); err != nil {
+ log.Fatal(err)
}
- flag.Parse()
- pth := findRepo(repo)
- if pth == "" {
- log.Fatalf("repository not found: %v", repo)
+ if out, err := exec.Command(unconvertBin, "-apply").CombinedOutput(); err != nil {
+ log.Fatalf("unconvert: %s\n%s", err, out)
+ }
+}
+
+func cp(dst, src, glob string) {
+ pat := filepath.Join(filepath.FromSlash(src), glob)
+ m, err := filepath.Glob(pat)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if len(m) == 0 {
+ log.Fatalf("cp(%q, %q, %q): no files for %q", dst, src, glob, pat)
+ }
+
+ dst = filepath.FromSlash(dst)
+ for _, v := range m {
+ f, err := ioutil.ReadFile(v)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ _, nm := filepath.Split(v)
+ if err := ioutil.WriteFile(filepath.Join(dst, nm), f, 0664); err != nil {
+ log.Fatal(err)
+ }
+ }
+}
+
+func header(f string) []byte {
+ b, err := ioutil.ReadFile(f)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ var s scanner.Scanner
+ s.Init(token.NewFileSet().AddFile(f, -1, len(b)), b, nil, scanner.ScanComments)
+ var buf buffer.Bytes
+ fmt.Fprintf(&buf, "/* %s */", filepath.Base(f))
+ for {
+ _, tok, lit := s.Scan()
+ switch tok {
+ case token.COMMENT:
+ buf.WriteString(lit)
+ buf.WriteByte('\n')
+ default:
+ return buf.Bytes()
+ }
+ }
+}
+
+func tidyComment(s string) string {
+ if strings.HasPrefix(s, "/*") {
+ s = s[len("/*") : len(s)-len("*/")]
+ }
+ a := strings.Split(strings.TrimSpace(s), "\n")
+ for i, v := range a {
+ if strings.HasPrefix(v, "** ") {
+ a[i] = a[i][len("** "):]
+ continue
+ }
+
+ if v == "**" {
+ a[i] = ""
+ }
+ }
+ for i, v := range a {
+ a[i] = strings.TrimSpace(v)
+ }
+ return "// " + strings.Join(a, "\n// ") + "\n"
+}
+
+func tidyComments(b []byte) string {
+ var s scanner.Scanner
+ s.Init(token.NewFileSet().AddFile("", -1, len(b)), b, nil, scanner.ScanComments)
+ var a []string
+ for {
+ _, tok, lit := s.Scan()
+ if tok == token.EOF {
+ return strings.Join(a, "\n")
+ }
+
+ a = append(a, tidyComment(lit))
+ }
+}
+
+func sqlite() {
+ repo := findRepo(sqliteRepo)
+ if repo == "" {
+ log.Fatalf("repository not found: %v", sqliteRepo)
return
}
+ pth := filepath.Join(repo, "sqlite-amalgamation-"+version)
+ sqlite3 := filepath.Join(pth, "sqlite3.c")
asta, src := build(
- `
- #define HAVE_MALLOC_H 1
- #define HAVE_MALLOC_USABLE_SIZE 1
- #define HAVE_USLEEP 1
- #define SQLITE_DEBUG 1
- #define SQLITE_ENABLE_API_ARMOR 1
- #define SQLITE_USE_URI 1
- #define SQLITE_WITHOUT_MSIZE 1
- `,
+ defines,
[][]string{
{"main.c"},
- {filepath.Join(pth, "sqlite3.c")},
+ {sqlite3},
},
+ nil,
cc.EnableAnonymousStructFields(),
cc.IncludePaths([]string{pth}),
)
@@ -295,20 +425,130 @@ func main() {
log.Fatal(err)
}
- fmt.Fprintf(&b, prologue, lic)
+ fmt.Fprintf(&b, prologueSqlite, lic, tidyComments(header(sqlite3)))
macros(&b, asta[0])
b.Write(src)
b2, err := format.Source(b.Bytes())
if err != nil {
b2 = b.Bytes()
}
- if err := os.MkdirAll("internal/bin", 0775); err != nil {
+ if err := os.MkdirAll(filepath.Join("internal", "bin"), 0775); err != nil {
log.Fatal(err)
}
- dst := fmt.Sprintf("internal/bin/bin_%s_%s.go", runtime.GOOS, runtime.GOARCH)
+ dst := fmt.Sprintf(filepath.Join("internal", "bin", "bin_%s_%s.go"), runtime.GOOS, runtime.GOARCH)
if err := ioutil.WriteFile(dst, b2, 0664); err != nil {
log.Fatal(err)
}
+
unconvert(dst)
}
+
+func mpTest() {
+ repo := findRepo(sqliteRepo)
+ if repo == "" {
+ log.Fatalf("repository not found: %v", sqliteRepo)
+ return
+ }
+
+ sqlitePth := filepath.Join(repo, "sqlite-amalgamation-"+version)
+ pth := filepath.Join(repo, "sqlite-src-"+version, "mptest")
+ tag := "mptest"
+ test := filepath.Join(pth, tag+".c")
+ _, src := build(
+ defines,
+ [][]string{
+ {filepath.Join(sqlitePth, "sqlite3.c")},
+ {test},
+ },
+ []string{"bin"},
+ cc.EnableAnonymousStructFields(),
+ cc.IncludePaths([]string{sqlitePth}),
+ )
+
+ var b bytes.Buffer
+ fmt.Fprintf(&b, prologueTest, tidyComments(header(test)))
+ b.Write(src)
+ b2, err := format.Source(b.Bytes())
+ if err != nil {
+ b2 = b.Bytes()
+ }
+ if err := os.MkdirAll(filepath.Join("internal", tag), 0775); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := os.MkdirAll(filepath.Join("testdata", tag), 0775); err != nil {
+ log.Fatal(err)
+ }
+
+ dst := fmt.Sprintf(filepath.Join("internal", tag, tag+"_%s_%s.go"), runtime.GOOS, runtime.GOARCH)
+ if err := ioutil.WriteFile(dst, b2, 0664); err != nil {
+ log.Fatal(err)
+ }
+
+ unconvert(dst)
+ cp(filepath.Join("testdata", tag), pth, "*.test")
+ cp(filepath.Join("testdata", tag), pth, "*.subtest")
+}
+
+func threadTest(n int) {
+ repo := findRepo(sqliteRepo)
+ if repo == "" {
+ log.Fatalf("repository not found: %v", sqliteRepo)
+ return
+ }
+
+ sqlitePth := filepath.Join(repo, "sqlite-amalgamation-"+version)
+ pth := filepath.Join(repo, "sqlite-src-"+version, "test")
+ tag := fmt.Sprintf("threadtest%v", n)
+ test := filepath.Join(pth, tag+".c")
+ _, src := build(
+ defines,
+ [][]string{
+ {filepath.Join(sqlitePth, "sqlite3.c")},
+ {test},
+ },
+ []string{"bin"},
+ cc.EnableAnonymousStructFields(),
+ cc.IncludePaths([]string{".", sqlitePth, filepath.Join(repo, "sqlite-src-"+version, "src")}),
+ )
+
+ var b bytes.Buffer
+ fmt.Fprintf(&b, prologueTest, tidyComments(header(test)))
+ b.Write(src)
+ b2, err := format.Source(b.Bytes())
+ if err != nil {
+ b2 = b.Bytes()
+ }
+ if err := os.MkdirAll(filepath.Join("internal", tag), 0775); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := os.MkdirAll(filepath.Join("testdata", tag), 0775); err != nil {
+ log.Fatal(err)
+ }
+
+ dst := fmt.Sprintf(filepath.Join("internal", tag, tag+"_%s_%s.go"), runtime.GOOS, runtime.GOARCH)
+ if err := ioutil.WriteFile(dst, b2, 0664); err != nil {
+ log.Fatal(err)
+ }
+
+ unconvert(dst)
+}
+
+func main() {
+ log.SetFlags(log.Lshortfile | log.Lmicroseconds)
+ var err error
+ if unconvertBin, err = exec.LookPath("unconvert"); err != nil {
+ log.Fatal("Please install the unconvert tool (go get -u github.com/mdempsky/unconvert)")
+ }
+
+ flag.Parse()
+
+ sqlite()
+ mpTest()
+ threadTest(1)
+ threadTest(2)
+ // threadTest(3) depends on unexported function.
+ threadTest(4)
+}