Copyright 2019 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package postgres

import (
	
	
	
	
	
	
	
	
	
	

	
	
	
	
	
	
	
imported to register the postgres migration driver
imported to register the file source migration driver
imported to register the postgres database driver
	_ 
)
recreateDB drops and recreates the database named dbName.
func ( string) error {
	 := dbtest.DropDB()
	if  != nil {
		return 
	}

	return dbtest.CreateDB()
}
migrationsSource returns a uri pointing to the migrations directory. It returns an error if unable to determine this path.
func () string {
	 := testhelper.TestDataPath("../../migrations")
	return "file://" + filepath.ToSlash()
}
tryToMigrate attempts to migrate the database named dbName to the latest migration. If this operation fails in the migration step, it returns isMigrationError=true to signal that the database should be recreated.
func ( string) ( bool,  error) {
	 := dbtest.DBConnURI()
	 := migrationsSource()
	,  := migrate.New(, )
	if  != nil {
		return false, fmt.Errorf("migrate.New(): %v", )
	}
	defer func() {
		if ,  := .Close();  != nil ||  != nil {
			 = dbtest.MultiErr{, , }
		}
	}()
	if  := .Up();  != nil &&  != migrate.ErrNoChange {
		return true, fmt.Errorf("m.Up(): %v", )
	}
	return false, nil
}
SetupTestDB creates a test database named dbName if it does not already exist, and migrates it to the latest schema from the migrations directory.
func ( string) ( *DB,  error) {
	defer derrors.Wrap(&, "SetupTestDB(%q)", )

	if  := dbtest.CreateDBIfNotExists();  != nil {
		return nil, fmt.Errorf("CreateDBIfNotExists(%q): %w", , )
	}
	if ,  := tryToMigrate();  != nil {
failed during migration stage, recreate and try again
			log.Printf("Migration failed for %s: %v, recreating database.", , )
			if  := recreateDB();  != nil {
				return nil, fmt.Errorf("recreateDB(%q): %v", , )
			}
			_,  = tryToMigrate()
		}
		if  != nil {
			return nil, fmt.Errorf("unfixable error migrating database: %v.\nConsider running ./devtools/drop_test_dbs.sh", )
		}
	}
	 := os.Getenv("GO_DISCOVERY_DATABASE_DRIVER")
	if  == "" {
		 = "pgx"
	}
	,  := database.Open(, dbtest.DBConnURI(), "test")
	if  != nil {
		return nil, 
	}
	return New(), nil
}
ResetTestDB truncates all data from the given test DB. It should be called after every test that mutates the database.
func ( *DB,  *testing.T) {
	 := context.Background()
	.Helper()
	if  := .db.Transact(, sql.LevelDefault, func( *database.DB) error {
		if ,  := .Exec(, `
			TRUNCATE modules CASCADE;
			TRUNCATE search_documents;
			TRUNCATE version_map;
			TRUNCATE paths CASCADE;
			TRUNCATE symbol_names CASCADE;
			TRUNCATE imports_unique;
			TRUNCATE latest_module_versions;`);  != nil {
			return 
		}
		if ,  := .Exec(, `TRUNCATE module_version_states CASCADE;`);  != nil {
			return 
		}
		if ,  := .Exec(, `TRUNCATE excluded_prefixes;`);  != nil {
			return 
		}
		return nil
	});  != nil {
		.Fatalf("error resetting test DB: %v", )
	}
	.expoller.Poll() // clear excluded prefixes
}
RunDBTests is a wrapper that runs the given testing suite in a test database named dbName. The given *DB reference will be set to the instantiated test database.
func ( string,  *testing.M,  **DB) {
	database.QueryLoggingDisabled = true
	,  := SetupTestDB()
	if  != nil {
		if errors.Is(, derrors.NotFound) && os.Getenv("GO_DISCOVERY_TESTDB") != "true" {
			log.Printf("SKIPPING: could not connect to DB (see doc/postgres.md to set up): %v", )
			return
		}
		log.Fatal()
	}
	* = 
	 := .Run()
	if  := .Close();  != nil {
		log.Fatal()
	}
	os.Exit()
}
RunDBTestsInParallel sets up numDBs databases, then runs the tests. Before it runs them, it sets acquirep to a function that tests should use to acquire a database. The second return value of the function should be called in a defer statement to release the database. For example: func Test(t *testing.T) { db, release := acquire(t) defer release()
func ( string,  int,  *testing.M,  *func(*testing.T) (*DB, func())) {
	 := time.Now()
	database.QueryLoggingDisabled = true
	 := make(chan *DB, )
	for  := 0;  < ; ++ {
		,  := SetupTestDB(fmt.Sprintf("%s-%d", , ))
		if  != nil {
			if errors.Is(, derrors.NotFound) && os.Getenv("GO_DISCOVERY_TESTDB") != "true" {
				log.Printf("SKIPPING: could not connect to DB (see doc/postgres.md to set up): %v", )
				return
			}
			log.Fatal()
		}
		 <- 
	}

	* = func( *testing.T) (*DB, func()) {
		 := <-
		 := func() {
			ResetTestDB(, )
			 <- 
		}
		return , 
	}

	log.Printf("parallel test setup for %d DBs took %s", , time.Since())
	 := .Run()
	if len() != cap() {
		log.Fatal("not all DBs were released")
	}
	for  := 0;  < ; ++ {
		 := <-
		if  := .Close();  != nil {
			log.Fatal()
		}
	}
	os.Exit()
}
MustInsertModule inserts m into db, calling t.Fatal on error. It also updates the latest-version information for m.
func ( context.Context,  *testing.T,  *DB,  *internal.Module) {
	mustInsertModule(, , , , "", true)
}

func ( context.Context,  *testing.T,  *DB,  *internal.Module,  string) {
	mustInsertModule(, , , , , true)
}

func ( context.Context,  *testing.T,  *DB,  *internal.Module) {
	mustInsertModule(, , , , "", false)
}

func ( context.Context,  *testing.T,  *DB,  *internal.Module,  string,  bool) {
	.Helper()
	var  *internal.LatestModuleVersions
	if  == "-" {
		if  := .UpdateLatestModuleVersionsStatus(, .ModulePath, 404);  != nil {
			.Fatal()
		}
	} else if  {
		 = addLatest(, , , .ModulePath, .Version, )
	}
	if ,  := .InsertModule(, , );  != nil {
		.Fatal()
	}
}

func ( context.Context,  *testing.T,  *DB, , ,  string) *internal.LatestModuleVersions {
	if !strings.HasPrefix(strings.TrimSpace(), "module") {
		 = "module " +  + "\n" + 
	}
	,  := internal.NewLatestModuleVersions(, , , "", []byte())
	if  != nil {
		.Fatal()
	}
	,  := .UpdateLatestModuleVersions(, )
	if  != nil {
		.Fatal()
	}
	return 
}
InsertSampleDirectory tree inserts a set of packages for testing GetUnit and frontend.FetchDirectoryDetails.
func ( context.Context,  *testing.T,  *DB) {
	.Helper()

	for ,  := range []struct {
		,  string
		            []string
	}{
		{
			"std",
			"v1.13.4",
			[]string{
				"archive/tar",
				"archive/zip",
				"cmd/go",
				"cmd/internal/obj",
				"cmd/internal/obj/arm",
				"cmd/internal/obj/arm64",
			},
		},
		{
			"std",
			"v1.13.0",
			[]string{
				"archive/tar",
				"archive/zip",
				"cmd/go",
				"cmd/internal/obj",
				"cmd/internal/obj/arm",
				"cmd/internal/obj/arm64",
			},
		},
		{
			"github.com/hashicorp/vault/api",
			"v1.1.2",
			[]string{""},
		},
		{
			"github.com/hashicorp/vault",
			"v1.1.2",
			[]string{
				"api",
				"builtin/audit/file",
				"builtin/audit/socket",
				"vault/replication",
				"vault/seal/transit",
			},
		},
		{
			"github.com/hashicorp/vault",
			"v1.2.3",
			[]string{
				"builtin/audit/file",
				"builtin/audit/socket",
				"internal/foo",
				"vault/replication",
				"vault/seal/transit",
			},
		},
		{
			"github.com/hashicorp/vault",
			"v1.0.3",
			[]string{
				"api",
				"builtin/audit/file",
				"builtin/audit/socket",
			},
		},
	} {
		 := sample.Module(., ., ....)
		MustInsertModule(, , , )
	}

}
GetFromSearchDocuments retrieves the module path and version for the given package path from the search_documents table. If the path is not in the table, the third return value is false.
func ( context.Context,  *testing.T,  *DB,  string) (,  string,  bool) {
	 := .db.QueryRow(, `
			SELECT module_path, version
			FROM search_documents
			WHERE package_path = $1`,
		)
	 := .Scan(&, &)
	switch  {
	case sql.ErrNoRows:
		return "", "", false
	case nil:
		return , , true
	default:
		.Fatal()
	}
	return