diff --git a/pkg/services/cloudmigration/cloudmigrationimpl/cloudmigration_test.go b/pkg/services/cloudmigration/cloudmigrationimpl/cloudmigration_test.go index 348bf8b1e98..246e74c6da7 100644 --- a/pkg/services/cloudmigration/cloudmigrationimpl/cloudmigration_test.go +++ b/pkg/services/cloudmigration/cloudmigrationimpl/cloudmigration_test.go @@ -20,7 +20,6 @@ import ( "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" - "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/httpclient" "github.com/grafana/grafana/pkg/infra/kvstore" "github.com/grafana/grafana/pkg/infra/tracing" @@ -47,6 +46,7 @@ import ( "github.com/grafana/grafana/pkg/services/quota/quotatest" secretsfakes "github.com/grafana/grafana/pkg/services/secrets/fakes" secretskv "github.com/grafana/grafana/pkg/services/secrets/kvstore" + "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user/usertest" "github.com/grafana/grafana/pkg/setting" @@ -60,6 +60,8 @@ func Test_NoopServiceDoesNothing(t *testing.T) { } func Test_CreateGetAndDeleteToken(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false) createResp, err := s.CreateToken(context.Background()) @@ -82,6 +84,8 @@ func Test_CreateGetAndDeleteToken(t *testing.T) { } func Test_GetSnapshotStatusFromGMS(t *testing.T) { + t.Parallel() + setupTest := func(ctx context.Context) (service *Service, snapshotUID string, sessionUID string) { s := setUpServiceTest(t, false).(*Service) @@ -150,6 +154,8 @@ func Test_GetSnapshotStatusFromGMS(t *testing.T) { } t.Run("test case: gms snapshot initialized", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -172,6 +178,8 @@ func Test_GetSnapshotStatusFromGMS(t *testing.T) { }) t.Run("test case: gms snapshot processing", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -194,6 +202,8 @@ func Test_GetSnapshotStatusFromGMS(t *testing.T) { }) t.Run("test case: gms snapshot finished", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -216,6 +226,8 @@ func Test_GetSnapshotStatusFromGMS(t *testing.T) { }) t.Run("test case: gms snapshot canceled", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -238,6 +250,8 @@ func Test_GetSnapshotStatusFromGMS(t *testing.T) { }) t.Run("test case: gms snapshot error", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -260,6 +274,8 @@ func Test_GetSnapshotStatusFromGMS(t *testing.T) { }) t.Run("test case: gms snapshot unknown", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -292,6 +308,8 @@ func Test_GetSnapshotStatusFromGMS(t *testing.T) { }) t.Run("GMS results applied to local snapshot", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -335,6 +353,8 @@ func Test_GetSnapshotStatusFromGMS(t *testing.T) { } func Test_OnlyQueriesStatusFromGMSWhenRequired(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) gmsClientMock := &gmsClientMock{ @@ -407,6 +427,8 @@ func Test_OnlyQueriesStatusFromGMSWhenRequired(t *testing.T) { } func Test_DeletedDashboardsNotMigrated(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) // modify what the mock returns for just this test case @@ -454,6 +476,8 @@ func Test_SortFolders(t *testing.T) { } func TestDeleteSession(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) user := &user.SignedInUser{UserUID: "user123"} @@ -496,7 +520,11 @@ func TestDeleteSession(t *testing.T) { } func TestReportEvent(t *testing.T) { + t.Parallel() + t.Run("when the session is nil, it does not report the event", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -513,6 +541,8 @@ func TestReportEvent(t *testing.T) { }) t.Run("when the session is not nil, it reports the event", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -530,6 +560,8 @@ func TestReportEvent(t *testing.T) { } func TestGetFolderNamesForFolderUIDs(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -594,6 +626,8 @@ func TestGetFolderNamesForFolderUIDs(t *testing.T) { } func TestGetParentNames(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -654,6 +688,8 @@ func TestGetParentNames(t *testing.T) { } func TestGetLibraryElementsCommands(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) ctx, cancel := context.WithCancel(context.Background()) @@ -718,6 +754,8 @@ func TestIsPublicSignatureType(t *testing.T) { } func TestGetPlugins(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) ctx, cancel := context.WithCancel(context.Background()) @@ -817,7 +855,6 @@ func TestGetPlugins(t *testing.T) { type configOverrides func(c *setting.Cfg) func setUpServiceTest(t *testing.T, withDashboardMock bool, cfgOverrides ...configOverrides) cloudmigration.Service { - sqlStore := db.InitTestDB(t) secretsService := secretsfakes.NewFakeSecretsService() rr := routing.NewRouteRegister() tracer := tracing.InitializeTracerForTest() @@ -862,6 +899,14 @@ func setUpServiceTest(t *testing.T, withDashboardMock bool, cfgOverrides ...conf featuremgmt.FlagDashboardRestore, // needed for skipping creating soft-deleted dashboards in the snapshot. ) + sqlStore := sqlstore.NewTestStore(t, + sqlstore.WithCfg(cfg), + sqlstore.WithFeatureFlags( + featuremgmt.FlagOnPremToCloudMigrations, + featuremgmt.FlagDashboardRestore, // needed for skipping creating soft-deleted dashboards in the snapshot. + ), + ) + kvStore := kvstore.ProvideService(sqlStore) bus := bus.ProvideBus(tracer) diff --git a/pkg/services/cloudmigration/cloudmigrationimpl/snapshot_mgmt_alerts_test.go b/pkg/services/cloudmigration/cloudmigrationimpl/snapshot_mgmt_alerts_test.go index 91d7ecc5cd7..c7a42105dd8 100644 --- a/pkg/services/cloudmigration/cloudmigrationimpl/snapshot_mgmt_alerts_test.go +++ b/pkg/services/cloudmigration/cloudmigrationimpl/snapshot_mgmt_alerts_test.go @@ -22,10 +22,14 @@ import ( ) func TestGetAlertMuteTimings(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) t.Run("it returns the mute timings", func(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) s.features = featuremgmt.WithFeatures(featuremgmt.FlagOnPremToCloudMigrations) @@ -42,10 +46,14 @@ func TestGetAlertMuteTimings(t *testing.T) { } func TestGetNotificationTemplates(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) t.Run("it returns the notification templates", func(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) user := &user.SignedInUser{OrgID: 1} @@ -61,10 +69,14 @@ func TestGetNotificationTemplates(t *testing.T) { } func TestGetContactPoints(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) t.Run("it returns the contact points", func(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) user := &user.SignedInUser{ @@ -89,10 +101,14 @@ func TestGetContactPoints(t *testing.T) { } func TestGetNotificationPolicies(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) t.Run("it returns the contact points", func(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) user := &user.SignedInUser{OrgID: 1} @@ -113,10 +129,14 @@ func TestGetNotificationPolicies(t *testing.T) { } func TestGetAlertRules(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) t.Run("it returns the alert rules", func(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) user := &user.SignedInUser{OrgID: 1} @@ -130,6 +150,8 @@ func TestGetAlertRules(t *testing.T) { }) t.Run("when the alert_rules_state config is `paused`, then the alert rules are all returned in `paused` state", func(t *testing.T) { + t.Parallel() + alertRulesState := func(c *setting.Cfg) { c.CloudMigration.AlertRulesState = setting.GMSAlertRulesPaused } @@ -153,10 +175,14 @@ func TestGetAlertRules(t *testing.T) { } func TestGetAlertRuleGroups(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) t.Run("it returns the alert rule groups", func(t *testing.T) { + t.Parallel() + s := setUpServiceTest(t, false).(*Service) user := &user.SignedInUser{OrgID: 1} @@ -190,6 +216,8 @@ func TestGetAlertRuleGroups(t *testing.T) { }) t.Run("with the alert rules state set to paused, it returns the alert rule groups with alert rules paused", func(t *testing.T) { + t.Parallel() + alertRulesState := func(c *setting.Cfg) { c.CloudMigration.AlertRulesState = setting.GMSAlertRulesPaused } diff --git a/pkg/services/cloudmigration/cloudmigrationimpl/xorm_store_test.go b/pkg/services/cloudmigration/cloudmigrationimpl/xorm_store_test.go index 03ab9065c57..9b86735c5d6 100644 --- a/pkg/services/cloudmigration/cloudmigrationimpl/xorm_store_test.go +++ b/pkg/services/cloudmigration/cloudmigrationimpl/xorm_store_test.go @@ -6,21 +6,17 @@ import ( "strconv" "testing" - "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/services/cloudmigration" fakeSecrets "github.com/grafana/grafana/pkg/services/secrets/fakes" secretskv "github.com/grafana/grafana/pkg/services/secrets/kvstore" "github.com/grafana/grafana/pkg/services/sqlstore" - "github.com/grafana/grafana/pkg/tests/testsuite" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestMain(m *testing.M) { - testsuite.Run(m) -} - func Test_GetAllCloudMigrationSessions(t *testing.T) { + t.Parallel() + _, s := setUpTest(t) ctx := context.Background() @@ -47,6 +43,8 @@ func Test_GetAllCloudMigrationSessions(t *testing.T) { } func Test_CreateMigrationSession(t *testing.T) { + t.Parallel() + _, s := setUpTest(t) ctx := context.Background() @@ -77,8 +75,11 @@ func Test_CreateMigrationSession(t *testing.T) { } func Test_GetMigrationSessionByUID(t *testing.T) { + t.Parallel() + _, s := setUpTest(t) ctx := context.Background() + t.Run("find session by uid", func(t *testing.T) { uid := "qwerty" orgId := int64(1) @@ -114,6 +115,8 @@ func Test_DeleteMigrationSession(t *testing.T) { */ func Test_SnapshotManagement(t *testing.T) { + t.Parallel() + _, s := setUpTest(t) ctx := context.Background() @@ -166,6 +169,8 @@ func Test_SnapshotManagement(t *testing.T) { } func Test_SnapshotResources(t *testing.T) { + t.Parallel() + _, s := setUpTest(t) ctx := context.Background() @@ -242,6 +247,8 @@ func Test_SnapshotResources(t *testing.T) { } func TestGetSnapshotList(t *testing.T) { + t.Parallel() + _, s := setUpTest(t) // Taken from setUpTest sessionUID := "qwerty" @@ -367,7 +374,8 @@ func TestDecryptToken(t *testing.T) { } func setUpTest(t *testing.T) (*sqlstore.SQLStore, *sqlStore) { - testDB := db.InitTestDB(t) + testDB := sqlstore.NewTestStore(t) + s := &sqlStore{ db: testDB, secretsService: fakeSecrets.FakeSecretsService{}, diff --git a/pkg/services/pluginsintegration/angulardetectorsprovider/dynamic_test.go b/pkg/services/pluginsintegration/angulardetectorsprovider/dynamic_test.go index b5c01e5ec23..f2211e14f57 100644 --- a/pkg/services/pluginsintegration/angulardetectorsprovider/dynamic_test.go +++ b/pkg/services/pluginsintegration/angulardetectorsprovider/dynamic_test.go @@ -337,7 +337,7 @@ func TestDynamicAngularDetectorsProviderBackgroundService(t *testing.T) { t.Run("background service", func(t *testing.T) { oldBackgroundJobInterval := backgroundJobIntervalOnPrem - backgroundJobIntervalOnPrem = time.Millisecond * 500 + backgroundJobIntervalOnPrem = 10 * time.Millisecond t.Cleanup(func() { backgroundJobIntervalOnPrem = oldBackgroundJobInterval }) @@ -387,7 +387,7 @@ func TestDynamicAngularDetectorsProviderBackgroundService(t *testing.T) { lastJobTime := time.Now() var jobCalls counter - const jobInterval = time.Millisecond * 500 + const jobInterval = time.Millisecond * 20 done := make(chan struct{}) gcom := newDefaultGCOMScenario(func(_ http.ResponseWriter, _ *http.Request) { now := time.Now() diff --git a/pkg/tsdb/mysql/mysql_test.go b/pkg/tsdb/mysql/mysql_test.go index 014c56cadf5..3325ca7c071 100644 --- a/pkg/tsdb/mysql/mysql_test.go +++ b/pkg/tsdb/mysql/mysql_test.go @@ -1,8 +1,10 @@ package mysql import ( + "cmp" "context" "database/sql" + "encoding/json" "fmt" "math/rand" "os" @@ -10,6 +12,7 @@ import ( "time" "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/stretchr/testify/require" @@ -30,7 +33,7 @@ func TestIntegrationMySQL(t *testing.T) { } // change to true to run the MySQL tests runMySQLTests := false - // runMySqlTests := true + // runMySQLTests := true if !(isTestDbMySQL() || runMySQLTests) { t.Skip() @@ -45,33 +48,59 @@ func TestIntegrationMySQL(t *testing.T) { return sql } - dsInfo := sqleng.DataSourceInfo{ - JsonData: sqleng.JsonData{ - MaxOpenConns: 0, - MaxIdleConns: 2, - ConnMaxLifetime: 14400, + logger := backend.NewLoggerWith("logger", "mysql.test") + + jsonData := sqleng.JsonData{ + MaxOpenConns: 0, + MaxIdleConns: 2, + ConnMaxLifetime: 14400, + } + + rawJsonData, err := json.Marshal(&jsonData) + require.NoError(t, err) + + pluginCtx := backend.PluginContext{ + DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{ + ID: 0, + UID: "mysql-test", + URL: fmt.Sprintf("%s:%s", cmp.Or(os.Getenv("MYSQL_HOST"), "localhost"), cmp.Or(os.Getenv("MYSQL_PORT"), "3306")), + Type: "mysql", + Name: "mysql-test", + User: "grafana", + Database: "grafana_ds_tests", + JSONData: rawJsonData, + DecryptedSecureJSONData: map[string]string{ + "password": "password", + }, }, } - config := sqleng.DataPluginConfiguration{ - DSInfo: dsInfo, - TimeColumnNames: []string{"time", "time_sec"}, - MetricColumnTypes: []string{"CHAR", "VARCHAR", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT"}, - RowLimit: 1000000, + cfg := backend.NewGrafanaCfg(map[string]string{ + backend.SQLMaxOpenConnsDefault: "0", + backend.SQLMaxIdleConnsDefault: "2", + backend.SQLMaxConnLifetimeSecondsDefault: "14400", + backend.SQLRowLimit: "1000000", + backend.UserFacingDefaultError: "", + }) + + ctx := backend.WithGrafanaConfig(context.Background(), cfg) + + exe := &Service{ + im: datasource.NewInstanceManager(NewInstanceSettings(logger)), + logger: logger, } - rowTransformer := mysqlQueryResultTransformer{} - - logger := backend.NewLoggerWith("logger", "mysql.test") - - db := InitMySQLTestDB(t, config.DSInfo.JsonData) - - exe, err := sqleng.NewQueryDataHandler("", db, config, &rowTransformer, newMysqlMacroEngine(logger, ""), logger) - - require.NoError(t, err) + db := InitMySQLTestDB(t, jsonData) fromStart := time.Date(2018, 3, 15, 13, 0, 0, 0, time.UTC) + queryWithPluginCtx := func(q backend.QueryDataRequest) *backend.QueryDataRequest { + return &backend.QueryDataRequest{ + PluginContext: pluginCtx, + Queries: q.Queries, + } + } + t.Run("Given a table with different native data types", func(t *testing.T) { _, err = db.Exec("DROP TABLE IF EXISTS mysql_types") require.NoError(t, err) @@ -125,7 +154,7 @@ func TestIntegrationMySQL(t *testing.T) { require.NoError(t, err) t.Run("Query with Table format should map MySQL column types to Go types", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -135,9 +164,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -217,7 +246,7 @@ func TestIntegrationMySQL(t *testing.T) { } t.Run("When doing a metric query using timeGroup", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -227,9 +256,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -261,7 +290,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using timeGroup with NULL fill enabled", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -275,9 +304,9 @@ func TestIntegrationMySQL(t *testing.T) { }, }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -322,7 +351,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("Should replace $__interval", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -337,9 +366,9 @@ func TestIntegrationMySQL(t *testing.T) { }, }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -350,7 +379,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using timeGroup with value fill enabled", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -364,9 +393,9 @@ func TestIntegrationMySQL(t *testing.T) { }, }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -379,7 +408,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using timeGroup with previous fill enabled", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -393,9 +422,9 @@ func TestIntegrationMySQL(t *testing.T) { }, }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -518,7 +547,7 @@ func TestIntegrationMySQL(t *testing.T) { } t.Run("When doing a metric query using time as time column should return metric with time in time.Time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -528,9 +557,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -543,7 +572,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using tinyint as value column should return metric with value in *float64", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -553,9 +582,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -567,7 +596,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using smallint as value column should return metric with value in *float64", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -577,9 +606,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -591,7 +620,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using time (nullable) as time column should return metric with time in time.Time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -601,9 +630,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -614,7 +643,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using epoch (int64) as time column and value column (int64) should return metric with time in time.Time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -624,9 +653,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -637,7 +666,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using epoch (int64 nullable) as time column and value column (int64 nullable) should return metric with time in time.Time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -647,9 +676,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -660,7 +689,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using epoch (float64) as time column and value column (float64) should return metric with time in time.Time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -670,9 +699,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -683,7 +712,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using epoch (float64 nullable) as time column and value column (float64 nullable) should return metric with time in time.Time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -693,9 +722,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -706,7 +735,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using epoch (int32) as time column and value column (int32) should return metric with time in time.Time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -716,9 +745,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -729,7 +758,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using epoch (int32 nullable) as time column and value column (int32 nullable) should return metric with time in time.Time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -739,9 +768,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -752,7 +781,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using epoch (float32) as time column and value column (float32) should return metric with time in time.Time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -762,9 +791,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -776,7 +805,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query using epoch (float32 nullable) as time column and value column (float32 nullable) should return metric with time in time.Time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -786,9 +815,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -800,7 +829,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query grouping by time and select metric column should return correct series", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -810,9 +839,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -825,7 +854,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query with metric column and multiple value columns", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -835,9 +864,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -857,7 +886,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a metric query grouping by time should return correct series", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -867,9 +896,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -884,7 +913,7 @@ func TestIntegrationMySQL(t *testing.T) { t.Run("When doing a query with timeFrom,timeTo,unixEpochFrom,unixEpochTo macros", func(t *testing.T) { sqleng.Interpolate = origInterpolate - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -895,9 +924,9 @@ func TestIntegrationMySQL(t *testing.T) { TimeRange: backend.TimeRange{From: fromStart.Add(-5 * time.Minute), To: fromStart}, }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -939,7 +968,7 @@ func TestIntegrationMySQL(t *testing.T) { } t.Run("When doing an annotation query of deploy events should return expected result", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -953,9 +982,9 @@ func TestIntegrationMySQL(t *testing.T) { }, }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["Deploys"] @@ -966,7 +995,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing an annotation query of ticket events should return expected result", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -980,9 +1009,9 @@ func TestIntegrationMySQL(t *testing.T) { }, }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["Tickets"] frames := queryResult.Frames @@ -995,16 +1024,16 @@ func TestIntegrationMySQL(t *testing.T) { dt := time.Date(2018, 3, 14, 21, 20, 6, 0, time.UTC) dtFormat := "2006-01-02 15:04:05.999999999" queryJson := fmt.Sprintf("{\"rawSql\": \"SELECT CAST('%s' as datetime) as time_sec, 'message' as text, 'tag1,tag2' as tags\", \"format\": \"table\"}", dt.Format(dtFormat)) - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(queryJson), RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -1019,16 +1048,16 @@ func TestIntegrationMySQL(t *testing.T) { t.Run("When doing an annotation query with a time column in epoch second format should return ms", func(t *testing.T) { dt := time.Date(2018, 3, 14, 21, 20, 6, 527e6, time.UTC) queryJson := fmt.Sprintf("{\"rawSql\": \"SELECT %d as time_sec, 'message' as text, 'tag1,tag2' as tags\", \"format\": \"table\"}", dt.Unix()) - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(queryJson), RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -1043,16 +1072,16 @@ func TestIntegrationMySQL(t *testing.T) { t.Run("When doing an annotation query with a time column in epoch second format (signed integer) should return ms", func(t *testing.T) { dt := time.Date(2018, 3, 14, 21, 20, 6, 0, time.Local) queryJson := fmt.Sprintf("{\"rawSql\": \"SELECT CAST('%d' as signed integer) as time_sec, 'message' as text, 'tag1,tag2' as tags\", \"format\": \"table\"}", dt.Unix()) - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(queryJson), RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -1068,16 +1097,16 @@ func TestIntegrationMySQL(t *testing.T) { dt := time.Date(2018, 3, 14, 21, 20, 6, 527e6, time.UTC) queryJson := fmt.Sprintf("{\"rawSql\": \"SELECT %d as time_sec, 'message' as text, 'tag1,tag2' as tags\", \"format\": \"table\"}", dt.Unix()*1000) - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(queryJson), RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -1090,7 +1119,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing an annotation query with a time column holding a unsigned integer null value should return nil", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -1100,9 +1129,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -1116,7 +1145,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing an annotation query with a time column holding a DATETIME null value should return nil", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -1126,9 +1155,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -1142,7 +1171,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing an annotation query with a time and timeend column should return two fields of type time", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -1152,9 +1181,9 @@ func TestIntegrationMySQL(t *testing.T) { RefID: "A", }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] require.NoError(t, queryResult.Error) @@ -1182,7 +1211,7 @@ func TestIntegrationMySQL(t *testing.T) { require.NoError(t, err) t.Run("When doing a table query that returns 2 rows should limit the result to 1 row", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -1196,7 +1225,7 @@ func TestIntegrationMySQL(t *testing.T) { }, }, }, - } + }) resp, err := handler.QueryData(context.Background(), query) require.NoError(t, err) @@ -1212,7 +1241,7 @@ func TestIntegrationMySQL(t *testing.T) { }) t.Run("When doing a time series that returns 2 rows should limit the result to 1 row", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -1226,7 +1255,7 @@ func TestIntegrationMySQL(t *testing.T) { }, }, }, - } + }) resp, err := handler.QueryData(context.Background(), query) require.NoError(t, err) @@ -1251,7 +1280,7 @@ func TestIntegrationMySQL(t *testing.T) { require.NoError(t, err) t.Run("When no rows are returned, should return an empty frame", func(t *testing.T) { - query := &backend.QueryDataRequest{ + query := queryWithPluginCtx(backend.QueryDataRequest{ Queries: []backend.DataQuery{ { JSON: []byte(`{ @@ -1265,9 +1294,9 @@ func TestIntegrationMySQL(t *testing.T) { }, }, }, - } + }) - resp, err := exe.QueryData(context.Background(), query) + resp, err := exe.QueryData(ctx, query) require.NoError(t, err) queryResult := resp.Responses["A"] diff --git a/pkg/util/shortid_generator_race_test.go b/pkg/util/shortid_generator_race_test.go new file mode 100644 index 00000000000..5ff85f93f87 --- /dev/null +++ b/pkg/util/shortid_generator_race_test.go @@ -0,0 +1,25 @@ +//go:build race +// +build race + +package util + +import ( + "sync" + "testing" +) + +// Run with "go test -race -run ^TestThreadSafe$ github.com/grafana/grafana/pkg/util" +func TestThreadSafe(t *testing.T) { + // Use 1000 go routines to create 100 UIDs each at roughly the same time. + var wg sync.WaitGroup + for i := 0; i < 1000; i++ { + go func() { + for ii := 0; ii < 100; ii++ { + _ = GenerateShortUID() + } + wg.Done() + }() + wg.Add(1) + } + wg.Wait() +} diff --git a/pkg/util/shortid_generator_test.go b/pkg/util/shortid_generator_test.go index 6bc4bb05b5c..b00e89d628c 100644 --- a/pkg/util/shortid_generator_test.go +++ b/pkg/util/shortid_generator_test.go @@ -2,7 +2,6 @@ package util import ( "fmt" - "sync" "testing" "cuelang.org/go/pkg/strings" @@ -19,25 +18,6 @@ func TestAllowedCharMatchesUidPattern(t *testing.T) { } } -// Run with "go test -race -run ^TestThreadSafe$ github.com/grafana/grafana/pkg/util" -func TestThreadSafe(t *testing.T) { - // This test was used to showcase the bug, unfortunately there is - // no way to enable the -race flag programmatically. - t.Skip() - // Use 1000 go routines to create 100 UIDs each at roughly the same time. - var wg sync.WaitGroup - for i := 0; i < 1000; i++ { - go func() { - for ii := 0; ii < 100; ii++ { - _ = GenerateShortUID() - } - wg.Done() - }() - wg.Add(1) - } - wg.Wait() -} - func TestRandomUIDs(t *testing.T) { for i := 0; i < 100; i++ { v := GenerateShortUID() @@ -48,10 +28,7 @@ func TestRandomUIDs(t *testing.T) { if validation != nil { t.Fatalf("created invalid name: %v", validation) } - - // fmt.Println(v) } - // t.FailNow() } func TestCaseInsensitiveCollisionsUIDs(t *testing.T) {