diff --git a/actions/v2/internal/integrationtests/spend_external_funds_internally_test.go b/actions/v2/internal/integrationtests/spend_external_funds_internally_test.go index 4351b83d0..e3d86fb95 100644 --- a/actions/v2/internal/integrationtests/spend_external_funds_internally_test.go +++ b/actions/v2/internal/integrationtests/spend_external_funds_internally_test.go @@ -3,44 +3,45 @@ package integrationtests import ( "testing" - "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testabilities" + "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testsuite" ) func TestSpendExternalFundsInternally(t *testing.T) { - // given: - given, when, then := testabilities.New(t) - cleanup := given.StartedSPVWalletV2() - defer cleanup() - - // when: - receiveTxID := when.Alice().ReceivesFromExternal(10) - - // then: - then.Alice().Balance().IsEqualTo(10) - then.Alice().Operations().Last(). - WithTxID(receiveTxID). - WithTxStatus("BROADCASTED"). - WithValue(10). - WithType("incoming") - - // when: - internalTxID := when.Alice().SendsFundsTo(given.Bob(), 5) - - // then: - then.Alice().Balance().IsEqualTo(4) - then.Bob().Balance().IsEqualTo(5) - - then.Alice().Operations().Last(). - WithTxID(internalTxID). - WithTxStatus("BROADCASTED"). - WithValue(-6). - WithType("outgoing"). - WithCounterparty(given.Bob().DefaultPaymail().Address()) - - then.Bob().Operations().Last(). - WithTxID(internalTxID). - WithTxStatus("BROADCASTED"). - WithValue(5). - WithType("incoming"). - WithCounterparty(given.Alice().DefaultPaymail().Address()) + testsuite.RunOnAllDBMS(t, func(t *testing.T, dbms string) { + // given: + given, when, then, cleanup := testsuite.SetupDBMSTest(t, dbms) + defer cleanup() + + // when: + receiveTxID := when.Alice().ReceivesFromExternal(10) + + // then: + then.Alice().Balance().IsEqualTo(10) + then.Alice().Operations().Last(). + WithTxID(receiveTxID). + WithTxStatus("BROADCASTED"). + WithValue(10). + WithType("incoming") + + // when: + internalTxID := when.Alice().SendsFundsTo(given.Bob(), 5) + + // then: + then.Alice().Balance().IsEqualTo(4) + then.Bob().Balance().IsEqualTo(5) + + then.Alice().Operations().Last(). + WithTxID(internalTxID). + WithTxStatus("BROADCASTED"). + WithValue(-6). + WithType("outgoing"). + WithCounterparty(given.Bob().DefaultPaymail().Address()) + + then.Bob().Operations().Last(). + WithTxID(internalTxID). + WithTxStatus("BROADCASTED"). + WithValue(5). + WithType("incoming"). + WithCounterparty(given.Alice().DefaultPaymail().Address()) + }) } diff --git a/actions/v2/internal/integrationtests/spend_external_funds_op_return_test.go b/actions/v2/internal/integrationtests/spend_external_funds_op_return_test.go index d6a8d31af..fa98abcbe 100644 --- a/actions/v2/internal/integrationtests/spend_external_funds_op_return_test.go +++ b/actions/v2/internal/integrationtests/spend_external_funds_op_return_test.go @@ -3,35 +3,36 @@ package integrationtests import ( "testing" - "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testabilities" + "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testsuite" ) func TestSpendExternalFundsOpReturn(t *testing.T) { - // given: - given, when, then := testabilities.New(t) - cleanup := given.StartedSPVWalletV2() - defer cleanup() - - // and: - receiveTxID := when.Alice().ReceivesFromExternal(2) - - // then: - then.Alice().Balance().IsEqualTo(2) - then.Alice().Operations().Last(). - WithTxID(receiveTxID). - WithTxStatus("BROADCASTED"). - WithValue(2). - WithType("incoming") - - // when: - internalTxID := when.Alice().SendsData([]string{"Hello", "Bob!"}) - - // then: - then.Alice().Balance().IsEqualTo(1) - - then.Alice().Operations().Last(). - WithTxID(internalTxID). - WithTxStatus("BROADCASTED"). - WithValue(-1). - WithType("outgoing") + testsuite.RunOnAllDBMS(t, func(t *testing.T, dbms string) { + // given: + _, when, then, cleanup := testsuite.SetupDBMSTest(t, dbms) + defer cleanup() + + // and: + receiveTxID := when.Alice().ReceivesFromExternal(2) + + // then: + then.Alice().Balance().IsEqualTo(2) + then.Alice().Operations().Last(). + WithTxID(receiveTxID). + WithTxStatus("BROADCASTED"). + WithValue(2). + WithType("incoming") + + // when: + internalTxID := when.Alice().SendsData([]string{"Hello", "Bob!"}) + + // then: + then.Alice().Balance().IsEqualTo(1) + + then.Alice().Operations().Last(). + WithTxID(internalTxID). + WithTxStatus("BROADCASTED"). + WithValue(-1). + WithType("outgoing") + }) } diff --git a/actions/v2/internal/integrationtests/spend_external_funds_with_multiple_outputs_test.go b/actions/v2/internal/integrationtests/spend_external_funds_with_multiple_outputs_test.go index b8baa550b..c93e9a9fd 100644 --- a/actions/v2/internal/integrationtests/spend_external_funds_with_multiple_outputs_test.go +++ b/actions/v2/internal/integrationtests/spend_external_funds_with_multiple_outputs_test.go @@ -3,47 +3,48 @@ package integrationtests import ( "testing" - "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testabilities" + "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testsuite" ) func TestSpendExternalFundsWithMultipleOutputs(t *testing.T) { - // given: - given, when, then := testabilities.New(t) - cleanup := given.StartedSPVWalletV2() - defer cleanup() - - // and: - receiveTxID := when.Alice().ReceivesFromExternal(2) - - // then: - then.Alice().Balance().IsEqualTo(2) - then.Alice().Operations().Last(). - WithTxID(receiveTxID). - WithTxStatus("BROADCASTED"). - WithValue(2). - WithType("incoming") - - // when: - internalTxID := when.Alice().CreatesOutline(). - WithPaymailOutput(given.Bob(), 1). - WithOpReturnOutput([]string{"Hello", "Bob!"}). - SignsAndRecord() - - // then: - then.Alice().Balance().IsEqualTo(0) - then.Bob().Balance().IsEqualTo(1) - - then.Alice().Operations().Last(). - WithTxID(internalTxID). - WithTxStatus("BROADCASTED"). - WithValue(-2). - WithType("outgoing"). - WithCounterparty(given.Bob().DefaultPaymail().Address()) - - then.Bob().Operations().Last(). - WithTxID(internalTxID). - WithTxStatus("BROADCASTED"). - WithValue(1). - WithType("incoming"). - WithCounterparty(given.Alice().DefaultPaymail().Address()) + testsuite.RunOnAllDBMS(t, func(t *testing.T, dbms string) { + // given: + given, when, then, cleanup := testsuite.SetupDBMSTest(t, dbms) + defer cleanup() + + // and: + receiveTxID := when.Alice().ReceivesFromExternal(2) + + // then: + then.Alice().Balance().IsEqualTo(2) + then.Alice().Operations().Last(). + WithTxID(receiveTxID). + WithTxStatus("BROADCASTED"). + WithValue(2). + WithType("incoming") + + // when: + internalTxID := when.Alice().CreatesOutline(). + WithPaymailOutput(given.Bob(), 1). + WithOpReturnOutput([]string{"Hello", "Bob!"}). + SignsAndRecord() + + // then: + then.Alice().Balance().IsEqualTo(0) + then.Bob().Balance().IsEqualTo(1) + + then.Alice().Operations().Last(). + WithTxID(internalTxID). + WithTxStatus("BROADCASTED"). + WithValue(-2). + WithType("outgoing"). + WithCounterparty(given.Bob().DefaultPaymail().Address()) + + then.Bob().Operations().Last(). + WithTxID(internalTxID). + WithTxStatus("BROADCASTED"). + WithValue(1). + WithType("incoming"). + WithCounterparty(given.Alice().DefaultPaymail().Address()) + }) } diff --git a/actions/v2/internal/integrationtests/spend_external_funds_with_multiple_transfers_test.go b/actions/v2/internal/integrationtests/spend_external_funds_with_multiple_transfers_test.go index e93f60f71..53851c30d 100644 --- a/actions/v2/internal/integrationtests/spend_external_funds_with_multiple_transfers_test.go +++ b/actions/v2/internal/integrationtests/spend_external_funds_with_multiple_transfers_test.go @@ -3,56 +3,56 @@ package integrationtests import ( "testing" - "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testabilities" + "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testsuite" ) func TestSpendInternalFundsWithMultipleTransfers(t *testing.T) { - // given: - given, when, then := testabilities.New(t) - cleanup := given.StartedSPVWalletV2() - defer cleanup() - - // and: - when.Alice().ReceivesFromExternal(50) - - // then: - then.Alice().Balance().IsEqualTo(50) - - // when: - firstTxID := when.Alice().SendsFundsTo(given.Bob(), 30) - - // then: - then.Alice().Balance().IsEqualTo(19) - then.Bob().Balance().IsEqualTo(30) - - // and: - then.Alice().Operations().Last(). - WithTxID(firstTxID). - WithTxStatus("BROADCASTED"). - WithValue(-31). - WithType("outgoing"). - WithCounterparty(given.Bob().DefaultPaymail().Address()) - - // and: - then.Bob().Operations().Last(). - WithTxID(firstTxID). - WithTxStatus("BROADCASTED"). - WithValue(30). - WithType("incoming"). - WithCounterparty(given.Alice().DefaultPaymail().Address()) - - // when: - secondTxID := when.Bob().SendsFundsTo(given.Charlie(), 20) - - // then: - then.Bob().Balance().IsEqualTo(9) - - // and: - then.Bob().Operations().Last(). - WithTxID(secondTxID). - WithTxStatus("BROADCASTED"). - WithValue(-21). - WithType("outgoing"). - WithCounterparty(given.Charlie().DefaultPaymail().Address()) - + testsuite.RunOnAllDBMS(t, func(t *testing.T, dbms string) { + // given: + given, when, then, cleanup := testsuite.SetupDBMSTest(t, dbms) + defer cleanup() + + // and: + when.Alice().ReceivesFromExternal(50) + + // then: + then.Alice().Balance().IsEqualTo(50) + + // when: + firstTxID := when.Alice().SendsFundsTo(given.Bob(), 30) + + // then: + then.Alice().Balance().IsEqualTo(19) + then.Bob().Balance().IsEqualTo(30) + + // and: + then.Alice().Operations().Last(). + WithTxID(firstTxID). + WithTxStatus("BROADCASTED"). + WithValue(-31). + WithType("outgoing"). + WithCounterparty(given.Bob().DefaultPaymail().Address()) + + // and: + then.Bob().Operations().Last(). + WithTxID(firstTxID). + WithTxStatus("BROADCASTED"). + WithValue(30). + WithType("incoming"). + WithCounterparty(given.Alice().DefaultPaymail().Address()) + + // when: + secondTxID := when.Bob().SendsFundsTo(given.Charlie(), 20) + + // then: + then.Bob().Balance().IsEqualTo(9) + + // and: + then.Bob().Operations().Last(). + WithTxID(secondTxID). + WithTxStatus("BROADCASTED"). + WithValue(-21). + WithType("outgoing"). + WithCounterparty(given.Charlie().DefaultPaymail().Address()) + }) } diff --git a/actions/v2/internal/integrationtests/spend_funds_from_different_outputs_test.go b/actions/v2/internal/integrationtests/spend_funds_from_different_outputs_test.go index 7274d1cf8..67bd76a83 100644 --- a/actions/v2/internal/integrationtests/spend_funds_from_different_outputs_test.go +++ b/actions/v2/internal/integrationtests/spend_funds_from_different_outputs_test.go @@ -3,50 +3,51 @@ package integrationtests import ( "testing" - "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testabilities" + "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testsuite" ) func TestSpendingFromMultipleSourceOutputs(t *testing.T) { - // given - given, when, then := testabilities.New(t) - cleanup := given.StartedSPVWalletV2() - defer cleanup() - - // and: - _ = when.Alice().ReceivesFromExternal(15) - _ = when.Alice().ReceivesFromExternal(25) - thirdTx := when.Alice().ReceivesFromExternal(10) - - // then: - then.Alice().Balance().IsEqualTo(50) // 15 + 25 + 10 - - // and: - then.Alice().Operations().Last(). - WithTxID(thirdTx). - WithTxStatus("BROADCASTED"). - WithValue(10). - WithType("incoming") - - // when: - txID4 := when.Alice().SendsFundsTo(given.Bob(), 41) - - // then: - then.Alice().Balance().IsEqualTo(8) - then.Bob().Balance().IsEqualTo(41) - - // and: - then.Alice().Operations().Last(). - WithTxID(txID4). - WithTxStatus("BROADCASTED"). - WithValue(-42). - WithType("outgoing"). - WithCounterparty(given.Bob().DefaultPaymail().Address()) - - // and: - then.Bob().Operations().Last(). - WithTxID(txID4). - WithTxStatus("BROADCASTED"). - WithValue(41). - WithType("incoming"). - WithCounterparty(given.Alice().DefaultPaymail().Address()) + testsuite.RunOnAllDBMS(t, func(t *testing.T, dbms string) { + // given + given, when, then, cleanup := testsuite.SetupDBMSTest(t, dbms) + defer cleanup() + + // and: + _ = when.Alice().ReceivesFromExternal(15) + _ = when.Alice().ReceivesFromExternal(25) + thirdTx := when.Alice().ReceivesFromExternal(10) + + // then: + then.Alice().Balance().IsEqualTo(50) // 15 + 25 + 10 + + // and: + then.Alice().Operations().Last(). + WithTxID(thirdTx). + WithTxStatus("BROADCASTED"). + WithValue(10). + WithType("incoming") + + // when: + txID4 := when.Alice().SendsFundsTo(given.Bob(), 41) + + // then: + then.Alice().Balance().IsEqualTo(8) + then.Bob().Balance().IsEqualTo(41) + + // and: + then.Alice().Operations().Last(). + WithTxID(txID4). + WithTxStatus("BROADCASTED"). + WithValue(-42). + WithType("outgoing"). + WithCounterparty(given.Bob().DefaultPaymail().Address()) + + // and: + then.Bob().Operations().Last(). + WithTxID(txID4). + WithTxStatus("BROADCASTED"). + WithValue(41). + WithType("incoming"). + WithCounterparty(given.Alice().DefaultPaymail().Address()) + }) } diff --git a/actions/v2/internal/integrationtests/testsuite/suite.go b/actions/v2/internal/integrationtests/testsuite/suite.go new file mode 100644 index 000000000..5762436b3 --- /dev/null +++ b/actions/v2/internal/integrationtests/testsuite/suite.go @@ -0,0 +1,74 @@ +package testsuite + +import ( + "os" + "testing" + + "github.com/bitcoin-sv/spv-wallet/actions/v2/internal/integrationtests/testabilities" + testengine "github.com/bitcoin-sv/spv-wallet/engine/testabilities" + "github.com/bitcoin-sv/spv-wallet/engine/testabilities/testmode" +) + +const ( + // DbmsPostgres is the PostgreSQL database management system + DbmsPostgres = "postgres" + // DbmsSqlite is the SQLite database management system + DbmsSqlite = "sqlite" + + // EnvSQLiteDBPath is the environment variable to specify the SQLite database file path + EnvSQLiteDBPath = "TEST_SQLITE_DB_PATH" +) + +// RunOnAllDBMS runs the given test function on all database management systems +func RunOnAllDBMS(t *testing.T, testFunc func(t *testing.T, dbms string)) { + t.Run("PostgreSQL", func(t *testing.T) { + testFunc(t, DbmsPostgres) + }) + + t.Run("SQLite", func(t *testing.T) { + cleanupSQLiteFile(t) + testFunc(t, DbmsSqlite) + }) +} + +// SetupDBMSTest is a helper function to set up a test with the specified database system +func SetupDBMSTest(t *testing.T, dbms string) ( + given testabilities.IntegrationTestFixtures, + when testabilities.IntegrationTestAction, + then testabilities.IntegrationTestAssertion, + cleanup func(), +) { + t.Helper() + + given, when, then = testabilities.New(t) + + if dbms == DbmsPostgres { + t.Setenv(testmode.EnvDBMode, testmode.PostgresContainerMode) + + container := given.(testengine.EngineFixture).GetPostgresContainer() + testmode.CleanDatabaseSchema(t, container) + + cleanup = given.StartedSPVWalletV2() + } else { + var sqliteOpts []testengine.ConfigOpts + if dbPath := os.Getenv(EnvSQLiteDBPath); dbPath != "" { + sqliteOpts = append(sqliteOpts, testengine.WithSQLiteFilePath(dbPath)) + } + cleanup = given.StartedSPVWalletV2(sqliteOpts...) + } + + return given, when, then, cleanup +} + +// cleanupSQLiteFile removes any SQLite file used for testing if configured +func cleanupSQLiteFile(t *testing.T) { + t.Helper() + + if dbPath := os.Getenv(EnvSQLiteDBPath); dbPath != "" { + if _, err := os.Stat(dbPath); err == nil { + if err := os.Remove(dbPath); err != nil { + t.Logf("Warning: Failed to remove SQLite file %s: %s", dbPath, err) + } + } + } +} diff --git a/engine/testabilities/fixture_configopts.go b/engine/testabilities/fixture_configopts.go index ab6a67736..3998a30b3 100644 --- a/engine/testabilities/fixture_configopts.go +++ b/engine/testabilities/fixture_configopts.go @@ -21,3 +21,24 @@ func WithNotificationsEnabled() ConfigOpts { c.Notifications.Enabled = true } } + +func WithPostgresConfig(host, port, user, password, dbName string) ConfigOpts { + return func(c *config.AppConfig) { + c.Db.Datastore.Engine = "postgresql" + c.Db.SQL.User = user + c.Db.SQL.Password = password + c.Db.SQL.Name = dbName + c.Db.SQL.Host = host + c.Db.SQL.Port = port + } +} + +func WithSQLiteFilePath(dbPath string) ConfigOpts { + return func(c *config.AppConfig) { + c.Db.Datastore.Engine = "sqlite" + c.Db.SQLite.DatabasePath = dbPath + c.Db.SQLite.Shared = false + c.Db.SQLite.MaxIdleConnections = 1 + c.Db.SQLite.MaxOpenConnections = 1 + } +} diff --git a/engine/testabilities/fixture_engine.go b/engine/testabilities/fixture_engine.go index ccb53f4ba..950ca7d43 100644 --- a/engine/testabilities/fixture_engine.go +++ b/engine/testabilities/fixture_engine.go @@ -3,6 +3,7 @@ package testabilities import ( "context" "errors" + "os" "testing" "github.com/bitcoin-sv/spv-wallet/config" @@ -30,6 +31,9 @@ const fileDbConnectionString = "file:spv-wallet-test.db" const CallbackTestToken = "arc-test-token" +// singleton container for the shared PostgreSQL container +var sharedContainer *testmode.TestContainer + type EngineFixture interface { Engine() (walletEngine EngineWithConfig, cleanup func()) EngineWithConfiguration(opts ...ConfigOpts) (walletEngine EngineWithConfig, cleanup func()) @@ -53,6 +57,9 @@ type EngineFixture interface { // Tx creates a new mocked transaction builder Tx() txtestability.TransactionSpec + + // GetPostgresContainer returns the shared PostgreSQL container instance + GetPostgresContainer() *testmode.TestContainer } // FaucetFixture is a test fixture for the faucet service @@ -71,7 +78,6 @@ type engineFixture struct { engine engine.ClientInterface t testing.TB logger zerolog.Logger - dbConnectionString string externalTransport *httpmock.MockTransport paymailClient *paymailmock.PaymailClientMock txFixture txtestability.TransactionsFixtures @@ -108,8 +114,31 @@ func (f *engineFixture) Engine() (walletEngine EngineWithConfig, cleanup func()) return f.EngineWithConfiguration() } +func (f *engineFixture) GetPostgresContainer() *testmode.TestContainer { + if sharedContainer == nil { + sharedContainer = testmode.StartPostgresContainer(f.t) + + f.t.Cleanup(func() { + if sharedContainer != nil { + ctx := context.Background() + if err := sharedContainer.Container.Terminate(ctx); err != nil { + f.t.Logf("Failed to terminate container: %s", err) + } + sharedContainer = nil + } + }) + } + + return sharedContainer +} + func (f *engineFixture) EngineWithConfiguration(opts ...ConfigOpts) (walletEngine EngineWithConfig, cleanup func()) { f.config = f.ConfigForTests(opts...) + + for _, opt := range opts { + opt(f.config) + } + f.prepareDBConfigForTests() options, err := initializer.ToEngineOptions(f.config, f.logger) @@ -161,30 +190,89 @@ func (f *engineFixture) Tx() txtestability.TransactionSpec { return f.txFixture.Tx() } -// prepareDBConfigForTests creates a new connection that will be used as connection for engine func (f *engineFixture) prepareDBConfigForTests() { - require.Equal(f.t, datastore.SQLite, f.config.Db.Datastore.Engine, "Other datastore engines are not supported in tests (yet)") - - // It is a workaround for development purpose to check the code with postgres instance. - if ok, dbName := testmode.CheckPostgresMode(); ok { - f.config.Db.Datastore.Engine = datastore.PostgreSQL - f.config.Db.SQL.User = "postgres" - f.config.Db.SQL.Password = "postgres" - f.config.Db.SQL.Name = dbName - f.config.Db.SQL.Host = "localhost" + if f.tryPostgresContainer() { return } - // It is a workaround for development purpose to check what is the db state after running a tests. - if testmode.CheckFileSQLiteMode() { - f.dbConnectionString = fileDbConnectionString + if f.tryDevelopmentPostgres() { + return + } + + if f.tryDevelopmentSQLite() { + return + } + + f.useSQLite() +} + +func (f *engineFixture) tryPostgresContainer() bool { + if !testmode.CheckPostgresContainerMode() { + return false + } + + container := f.GetPostgresContainer() + + f.config.Db.Datastore.Engine = datastore.PostgreSQL + f.config.Db.SQL.User = testmode.DefaultPostgresUser + f.config.Db.SQL.Password = testmode.DefaultPostgresPass + f.config.Db.SQL.Name = testmode.DefaultPostgresName + + f.config.Db.SQL.Host = getConfigValueOrDefault(os.Getenv(testmode.EnvDBHost), container.Host) + f.config.Db.SQL.Port = getConfigValueOrDefault(os.Getenv(testmode.EnvDBPort), container.Port) + + f.t.Logf("Using PostgreSQL container at %s:%s", f.config.Db.SQL.Host, f.config.Db.SQL.Port) + + return true +} + +func (f *engineFixture) tryDevelopmentPostgres() bool { + ok, dbName := testmode.CheckPostgresMode() + if !ok { + return false + } + + f.config.Db.Datastore.Engine = datastore.PostgreSQL + f.config.Db.SQL.User = testmode.DefaultPostgresUser + f.config.Db.SQL.Password = testmode.DefaultPostgresPass + f.config.Db.SQL.Name = dbName + + host := os.Getenv(testmode.EnvDBHost) + port := os.Getenv(testmode.EnvDBPort) + + if host != "" { + f.config.Db.SQL.Host = host } else { - f.dbConnectionString = inMemoryDbConnectionString + f.config.Db.SQL.Host = "localhost" + } + + if port != "" { + f.config.Db.SQL.Port = port + } + + return true +} + +func (f *engineFixture) tryDevelopmentSQLite() bool { + if !testmode.CheckFileSQLiteMode() { + return false } + + f.config.Db.Datastore.Engine = datastore.SQLite + f.config.Db.SQLite.Shared = false + f.config.Db.SQLite.MaxIdleConnections = 1 + f.config.Db.SQLite.MaxOpenConnections = 1 + f.config.Db.SQLite.DatabasePath = fileDbConnectionString + + return true +} + +func (f *engineFixture) useSQLite() { + f.config.Db.Datastore.Engine = datastore.SQLite f.config.Db.SQLite.Shared = false f.config.Db.SQLite.MaxIdleConnections = 1 f.config.Db.SQLite.MaxOpenConnections = 1 - f.config.Db.SQLite.DatabasePath = f.dbConnectionString + f.config.Db.SQLite.DatabasePath = inMemoryDbConnectionString } func (f *engineFixture) initialiseFixtures() { @@ -281,3 +369,10 @@ func getConfigForTests() *config.AppConfig { return cfg } + +func getConfigValueOrDefault(value, defaultValue string) string { + if value != "" { + return value + } + return defaultValue +} diff --git a/engine/testabilities/testmode/db_mode.go b/engine/testabilities/testmode/db_mode.go index f20138cdf..b2034959c 100644 --- a/engine/testabilities/testmode/db_mode.go +++ b/engine/testabilities/testmode/db_mode.go @@ -7,46 +7,150 @@ Calls of SetPostgresMode and SetFileSQLiteMode should not be committed. package testmode import ( + "context" + "database/sql" + "fmt" "os" "testing" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/postgres" ) const ( - modeEnvVar = "TEST_DB_MODE" - nameEnvVar = "TEST_DB_NAME" + // EnvDBMode is the environment variable to set the test database mode + EnvDBMode = "TEST_DB_MODE" + // EnvDBName is the environment variable to set the test database name + EnvDBName = "TEST_DB_NAME" + // EnvDBHost is the environment variable to set the test database host + EnvDBHost = "TEST_DB_HOST" + // EnvDBPort is the environment variable to set the test database port + EnvDBPort = "TEST_DB_PORT" + + // PostgresContainerMode is the mode to use a PostgreSQL testcontainer for testing + PostgresContainerMode = "postgres-container" + // PostgresMode is the mode to use actual Postgres for testing + PostgresMode = "postgres" + // SQLiteFileMode is the mode to use SQLite file for testing + SQLiteFileMode = "file" - defaultPostgresDBName = "postgres" + // DefaultPostgresName is the default database name for PostgreSQL + DefaultPostgresName = "postgres" + // DefaultPostgresUser is the default database user for PostgreSQL + DefaultPostgresUser = "postgres" + // DefaultPostgresPass is the default database password for PostgreSQL + DefaultPostgresPass = "postgres" ) -// DevelopmentOnly_SetPostgresMode sets the test mode to use actual Postgres and sets the database name. +// TestContainer represents a running test container +type TestContainer struct { + Container testcontainers.Container + Host string + Port string +} + +// StartPostgresContainer starts a PostgreSQL container and returns connection details +func StartPostgresContainer(t testing.TB) *TestContainer { + t.Helper() + + ctx := context.Background() + + postgresContainer, err := postgres.Run(ctx, + "postgres:latest", + postgres.WithDatabase(DefaultPostgresName), + postgres.WithUsername(DefaultPostgresUser), + postgres.WithPassword(DefaultPostgresPass), + postgres.BasicWaitStrategies(), + ) + if err != nil { + t.Fatalf("failed to start postgres container: %s", err) + } + + host, err := postgresContainer.Host(ctx) + if err != nil { + t.Fatalf("failed to get container host: %s", err) + } + + port, err := postgresContainer.MappedPort(ctx, "5432") + if err != nil { + t.Fatalf("failed to get mapped port: %s", err) + } + + t.Logf("Started PostgreSQL container at %s:%s", host, port.Port()) + + return &TestContainer{ + Container: postgresContainer, + Host: host, + Port: port.Port(), + } +} + +// CleanDatabaseSchema resets the database schema for a fresh test +func CleanDatabaseSchema(t testing.TB, container *TestContainer) { + t.Helper() + + connStr := fmt.Sprintf( + "host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", + container.Host, container.Port, DefaultPostgresUser, DefaultPostgresPass, DefaultPostgresName, + ) + + db, err := sql.Open("postgres", connStr) + if err != nil { + t.Fatalf("Failed to connect to database: %s", err) + } + defer func(db *sql.DB) { + err := db.Close() + if err != nil { + t.Fatalf("Failed to close database connection: %s", err) + } + }(db) + + _, err = db.Exec(`DROP SCHEMA IF EXISTS public CASCADE; CREATE SCHEMA public;`) + + if err != nil { + t.Fatalf("Failed to clean database: %s", err) + } + + t.Log("Database schema cleaned successfully") +} + +// DevelopmentOnly_SetPostgresMode sets the test mode to use actual Postgres func DevelopmentOnly_SetPostgresMode(t testing.TB) { - t.Setenv(modeEnvVar, "postgres") + t.Helper() + t.Setenv(EnvDBMode, PostgresMode) } -// DevelopmentOnly_SetPostgresModeWithName sets the test mode to use actual Postgres and sets the database name. +// DevelopmentOnly_SetPostgresModeWithName sets the test mode to use actual Postgres and sets the database name func DevelopmentOnly_SetPostgresModeWithName(t testing.TB, dbName string) { - DevelopmentOnly_SetPostgresMode(t) - t.Setenv(nameEnvVar, dbName) + t.Helper() + t.Setenv(EnvDBMode, PostgresMode) + t.Setenv(EnvDBName, dbName) } // DevelopmentOnly_SetFileSQLiteMode sets the test mode to use SQLite file func DevelopmentOnly_SetFileSQLiteMode(t testing.TB) { - t.Setenv(modeEnvVar, "file") + t.Helper() + t.Setenv(EnvDBMode, SQLiteFileMode) } -// CheckPostgresMode checks if the test mode is set to use actual Postgres and returns the database name. +// CheckPostgresMode checks if the test mode is set to use actual Postgres and returns the database name func CheckPostgresMode() (ok bool, dbName string) { - if os.Getenv(modeEnvVar) != "postgres" { + if os.Getenv(EnvDBMode) != PostgresMode { return false, "" } - dbName = os.Getenv(nameEnvVar) + dbName = os.Getenv(EnvDBName) if dbName == "" { - dbName = defaultPostgresDBName + dbName = DefaultPostgresName } return true, dbName } // CheckFileSQLiteMode checks if the test mode is set to use SQLite file func CheckFileSQLiteMode() bool { - return os.Getenv(modeEnvVar) == "file" + return os.Getenv(EnvDBMode) == SQLiteFileMode +} + +// CheckPostgresContainerMode checks if the test mode is set to use PostgreSQL container +func CheckPostgresContainerMode() bool { + return os.Getenv(EnvDBMode) == PostgresContainerMode } diff --git a/go.mod b/go.mod index 616b12a82..d3dcd3d5b 100644 --- a/go.mod +++ b/go.mod @@ -54,24 +54,63 @@ require ( ) require ( + dario.cat/mergo v1.0.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/aws/aws-sdk-go v1.55.5 // indirect github.com/bytedance/sonic/loader v0.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect + github.com/containerd/containerd v1.7.18 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v27.1.1+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/lib/pq v1.10.9 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/newrelic/go-agent/v3 v3.36.0 // indirect github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 // indirect github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/speakeasy-api/openapi-overlay v0.9.0 // indirect + github.com/testcontainers/testcontainers-go v0.35.0 // indirect + github.com/testcontainers/testcontainers-go/modules/postgres v0.35.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/driver/mysql v1.5.7 // indirect ) diff --git a/go.sum b/go.sum index 9df69ecb3..788958ed1 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,15 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/gqlgen v0.17.66 h1:2/SRc+h3115fCOZeTtsqrB5R5gTGm+8qCAwcrZa+CXA= github.com/99designs/gqlgen v0.17.66/go.mod h1:gucrb5jK5pgCKzAGuOMMVU9C8PnReecHEHd2UxLQwCg= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE= github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= @@ -39,6 +45,8 @@ github.com/bytedance/sonic/loader v0.2.1 h1:1GgorWTqf12TA8mma4DDSbaQigE2wOgQo7iC github.com/bytedance/sonic/loader v0.2.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/capnm/sysinfo v0.0.0-20130621111458-5909a53897f3 h1:IHZ1Le1ejzkmS7Si7dIzJvYDWe+BIoNmqMnfWHBZSVw= github.com/capnm/sysinfo v0.0.0-20130621111458-5909a53897f3/go.mod h1:M5XHQLu90v2JNm/bW2tdsYar+5vhV0gEcBcmDBNAN1Y= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -49,9 +57,17 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= +github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/coocood/freecache v1.2.4 h1:UdR6Yz/X1HW4fZOuH0Z94KwG851GWOSknua5VUbb/5M= github.com/coocood/freecache v1.2.4/go.mod h1:RBUWa/Cy+OHdfTGFEhEuE1pMCMX51Ncizj7rthiQ3vk= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -60,9 +76,19 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fergusstrange/embedded-postgres v1.30.0 h1:ewv1e6bBlqOIYtgGgRcEnNDpfGlmfPxB8T3PO9tV68Q= github.com/fergusstrange/embedded-postgres v1.30.0/go.mod h1:w0YvnCgf19o6tskInrOOACtnqfVlOvluz3hlNLY7tRk= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -83,10 +109,13 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= @@ -123,6 +152,8 @@ github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlnd github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= @@ -145,6 +176,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -182,6 +214,8 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -201,6 +235,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -222,6 +258,16 @@ github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -229,6 +275,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrz1836/go-cache v0.11.3 h1:tEOvfW/YO9DmVpM7s9f1SDajfldjVifRLIg4Ks29xsU= github.com/mrz1836/go-cache v0.11.3/go.mod h1:LHSl5+egt4RakeRCh6Z9I2xxvrOvcX5EUmwZX0PuvCY= github.com/mrz1836/go-cachestore v0.5.2 h1:eWFYghb/4qmgB8dqYActEI5thbBAyMhZAFhECRuAkgQ= @@ -269,6 +317,10 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= @@ -278,6 +330,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA= github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= @@ -307,6 +361,13 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4= github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= @@ -332,6 +393,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -342,6 +404,14 @@ github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+z github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo= github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A= github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg= +github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo= +github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4= +github.com/testcontainers/testcontainers-go/modules/postgres v0.35.0 h1:eEGx9kYzZb2cNhRbBrNOCL/YPOM7+RMJiy3bB+ie0/I= +github.com/testcontainers/testcontainers-go/modules/postgres v0.35.0/go.mod h1:hfH71Mia/WWLBgMD2YctYcMlfsbnT0hflweL1dy8Q4s= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -358,12 +428,17 @@ github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9N github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.elastic.co/ecszerolog v0.2.0 h1:nbX4dQ08jb3+vsvACfmzAqGDoBh8F2HQDUgpqwAVTg0= go.elastic.co/ecszerolog v0.2.0/go.mod h1:wR5Mv0BVQJ17LopUX5Fd0LLKCC9iF++58iKY+lL09lc= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= @@ -388,6 +463,7 @@ golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4= golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -396,6 +472,7 @@ golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -408,6 +485,7 @@ golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -417,23 +495,30 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -451,7 +536,9 @@ golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=