diff --git a/pkg/index/indextest/tests.go b/pkg/index/indextest/tests.go index a8b672bdb..2448a6138 100644 --- a/pkg/index/indextest/tests.go +++ b/pkg/index/indextest/tests.go @@ -20,7 +20,10 @@ import ( "fmt" "log" "os" + "path/filepath" "reflect" + "runtime" + "strings" "testing" "time" @@ -137,10 +140,34 @@ func (id *IndexDeps) UploadFile(fileName string, contents string) (fileRef, whol return } +func osSplitChar() string { + switch runtime.GOOS { + case "windows": + return ";" + case "plan9": + panic("unsupported") + } + return ":" +} + +func findGoPathPackage(pkg string) string { + gp := os.Getenv("GOPATH") + if gp == "" { + panic("no GOPATH set") + } + for _, p := range strings.Split(gp, osSplitChar()) { + dir := filepath.Join(p, "src", pkg) + if fi, err := os.Stat(dir); err == nil && fi.IsDir() { + return dir + } + } + panic(fmt.Sprintf("package %q not found in GOPATH(s) of %q", pkg, gp)) +} + func NewIndexDeps(index *index.Index) *IndexDeps { // TODO(mpl): do better than the quick hack with the testdata symlink when things // have settled regarding the organization of the packages. - secretRingFile := "testdata/test-secring.gpg" + secretRingFile := filepath.Join(findGoPathPackage("camlistore.org"), "pkg", "jsonsign", "testdata", "test-secring.gpg") pubKey := &test.Blob{Contents: `-----BEGIN PGP PUBLIC KEY BLOCK----- xsBNBEzgoVsBCAC/56aEJ9BNIGV9FVP+WzenTAkg12k86YqlwJVAB/VwdMlyXxvi @@ -269,7 +296,7 @@ func Index(t *testing.T, initIdx func() *index.Index) { } _, _, err = id.Index.GetBlobMimeType(blobref.Parse("abc-123")) if err != os.ErrNotExist { - t.Errorf("GetBlobMimeType(dummy blobref) = %v; want os.ENOENT", err) + t.Errorf("GetBlobMimeType(dummy blobref) = %v; want os.ErrNotExist", err) } } diff --git a/pkg/index/mongo/testdata b/pkg/index/mongo/testdata deleted file mode 120000 index 4f7c11684..000000000 --- a/pkg/index/mongo/testdata +++ /dev/null @@ -1 +0,0 @@ -../testdata \ No newline at end of file diff --git a/pkg/index/mysql/mysql_test.go b/pkg/index/mysql/mysql_test.go index fa102b01d..7e84c5ee4 100644 --- a/pkg/index/mysql/mysql_test.go +++ b/pkg/index/mysql/mysql_test.go @@ -19,12 +19,14 @@ package mysql_test import ( "database/sql" "errors" + "fmt" "sync" "testing" + "os" "camlistore.org/pkg/index" "camlistore.org/pkg/index/indextest" - _ "camlistore.org/pkg/index/mysql" // TODO: use + "camlistore.org/pkg/index/mysql" _ "camlistore.org/third_party/github.com/ziutek/mymysql/godrv" ) @@ -38,28 +40,52 @@ var ( func checkDB() { var err error if rootdb, err = sql.Open("mymysql", "mysql/root/root"); err == nil { - dbAvailable = true - return - } - if rootdb, err = sql.Open("mymysql", "mysql/root/"); err == nil { - dbAvailable = true - return + var n int + err := rootdb.QueryRow("SELECT COUNT(*) FROM user").Scan(&n) + if err == nil { + dbAvailable = true + } } } func makeIndex() *index.Index { - panic("TODO") + dbname := "camlitest_" + os.Getenv("USER") + do(rootdb, "DROP DATABASE IF EXISTS " + dbname) + do(rootdb, "CREATE DATABASE " + dbname) + + db, err := sql.Open("mymysql", dbname + "/root/root"); + if err != nil { + panic("opening test database: " + err.Error()) + } + for _, tableSql := range mysql.SQLCreateTables() { + do(db, tableSql) + } + + do(db, fmt.Sprintf(`REPLACE INTO meta VALUES ('version', '%d')`, mysql.SchemaVersion())) + s, err := mysql.NewStorage("localhost", "root", "root", dbname) + if err != nil { + panic(err) + } + return index.New(s) +} + +func do(db *sql.DB, sql string) { + _, err := db.Exec(sql) + if err == nil { + return + } + panic(fmt.Sprintf("Error %v running SQL: %s", err, sql)) } type mysqlTester struct{} func (mysqlTester) test(t *testing.T, tfn func(*testing.T, func() *index.Index)) { - t.Logf("TODO: implement") - return - once.Do(checkDB) if !dbAvailable { - err := errors.New("Not running; start a MySQL daemon on the standard port (3306) with root password 'root' or '' (empty).") + // TODO(bradfitz): accept somehow other passwords than + // 'root', and/or try localhost unix socket + // connections rather than using TCP localhost? + err := errors.New("Not running; start a MySQL daemon on the standard port (3306) with root password 'root'") t.Fatalf("MySQL not available locally for testing: %v", err) } tfn(t, makeIndex) diff --git a/pkg/index/mysql/mysqlindexer.go b/pkg/index/mysql/mysqlindexer.go index 493ae6bd7..c04c3f3a2 100644 --- a/pkg/index/mysql/mysqlindexer.go +++ b/pkg/index/mysql/mysqlindexer.go @@ -79,6 +79,9 @@ func (ms *myIndexStorage) CommitBatch(b index.BatchMutation) error { func (ms *myIndexStorage) Get(key string) (value string, err error) { err = ms.db.QueryRow("SELECT v FROM rows WHERE k=?", key).Scan(&value) + if err == sql.ErrNoRows { + err = index.ErrNotFound + } return } @@ -164,6 +167,20 @@ func (t *iter) Next() bool { return true } +// NewStorage returns an IndexStorage implementation of the described MySQL database. +// This exists mostly for testing and does not initialize the schema. +func NewStorage(host, user, password, dbname string) (index.IndexStorage, error) { + is := &myIndexStorage{ + host: host, + user: user, + password: password, + database: dbname, + } + db, err := sql.Open("mymysql", is.database+"/"+is.user+"/"+is.password) + is.db = db + return is, err +} + func newFromConfig(ld blobserver.Loader, config jsonconfig.Obj) (blobserver.Storage, error) { blobPrefix := config.RequiredString("blobSource") is := &myIndexStorage{ diff --git a/pkg/index/testdata b/pkg/index/testdata deleted file mode 120000 index 4684d1d03..000000000 --- a/pkg/index/testdata +++ /dev/null @@ -1 +0,0 @@ -../jsonsign/testdata \ No newline at end of file