diff --git a/pkg/services/queryhistory/database.go b/pkg/services/queryhistory/database.go index 4162118bab9..512f74fbd1b 100644 --- a/pkg/services/queryhistory/database.go +++ b/pkg/services/queryhistory/database.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "strconv" - "time" "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/services/user" @@ -19,7 +18,7 @@ func (s QueryHistoryService) createQuery(ctx context.Context, user *user.SignedI Queries: cmd.Queries, DatasourceUID: cmd.DatasourceUID, CreatedBy: user.UserID, - CreatedAt: time.Now().Unix(), + CreatedAt: s.now().Unix(), Comment: "", } @@ -50,7 +49,7 @@ func (s QueryHistoryService) searchQueries(ctx context.Context, user *user.Signe var allQueries []interface{} if query.To <= 0 { - query.To = time.Now().Unix() + query.To = s.now().Unix() } if query.Page <= 0 { diff --git a/pkg/services/queryhistory/queryhistory.go b/pkg/services/queryhistory/queryhistory.go index 0bd3a3fe228..2f963a262f4 100644 --- a/pkg/services/queryhistory/queryhistory.go +++ b/pkg/services/queryhistory/queryhistory.go @@ -2,6 +2,7 @@ package queryhistory import ( "context" + "time" "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/infra/db" @@ -16,6 +17,7 @@ func ProvideService(cfg *setting.Cfg, sqlStore db.DB, routeRegister routing.Rout Cfg: cfg, RouteRegister: routeRegister, log: log.New("query-history"), + now: time.Now, } // Register routes only when query history is enabled @@ -43,6 +45,7 @@ type QueryHistoryService struct { Cfg *setting.Cfg RouteRegister routing.RouteRegister log log.Logger + now func() time.Time } func (s QueryHistoryService) CreateQueryInQueryHistory(ctx context.Context, user *user.SignedInUser, cmd CreateQueryInQueryHistoryCommand) (QueryHistoryDTO, error) { diff --git a/pkg/services/queryhistory/queryhistory_delete_stale_test.go b/pkg/services/queryhistory/queryhistory_delete_stale_test.go index 84ed7839572..354be9cdc62 100644 --- a/pkg/services/queryhistory/queryhistory_delete_stale_test.go +++ b/pkg/services/queryhistory/queryhistory_delete_stale_test.go @@ -3,7 +3,6 @@ package queryhistory import ( "context" "testing" - "time" "github.com/stretchr/testify/require" @@ -16,7 +15,7 @@ func TestIntegrationDeleteStaleQueryFromQueryHistory(t *testing.T) { } testScenarioWithQueryInQueryHistory(t, "Stale query history can be deleted", func(t *testing.T, sc scenarioContext) { - olderThan := time.Now().Unix() + 60 + olderThan := sc.service.now().Unix() + 60 rowsDeleted, err := sc.service.DeleteStaleQueriesInQueryHistory(context.Background(), olderThan) require.NoError(t, err) require.Equal(t, 1, rowsDeleted) @@ -28,7 +27,7 @@ func TestIntegrationDeleteStaleQueryFromQueryHistory(t *testing.T) { resp := sc.service.starHandler(sc.reqContext) require.Equal(t, 200, resp.Status()) - olderThan := time.Now().Unix() + 60 + olderThan := sc.service.now().Unix() + 60 rowsDeleted, err := sc.service.DeleteStaleQueriesInQueryHistory(context.Background(), olderThan) require.NoError(t, err) require.Equal(t, 0, rowsDeleted) @@ -36,7 +35,7 @@ func TestIntegrationDeleteStaleQueryFromQueryHistory(t *testing.T) { testScenarioWithQueryInQueryHistory(t, "Not stale query history is not deleted", func(t *testing.T, sc scenarioContext) { - olderThan := time.Now().Unix() - 60 + olderThan := sc.service.now().Unix() - 60 rowsDeleted, err := sc.service.DeleteStaleQueriesInQueryHistory(context.Background(), olderThan) require.NoError(t, err) require.Equal(t, 0, rowsDeleted) @@ -45,7 +44,7 @@ func TestIntegrationDeleteStaleQueryFromQueryHistory(t *testing.T) { // In this scenario we have 2 starred queries and 1 not starred query testScenarioWithMultipleQueriesInQueryHistory(t, "Stale starred query history can not be deleted", func(t *testing.T, sc scenarioContext) { - olderThan := time.Now().Unix() + 60 + olderThan := sc.service.now().Unix() + 60 rowsDeleted, err := sc.service.DeleteStaleQueriesInQueryHistory(context.Background(), olderThan) require.NoError(t, err) require.Equal(t, 1, rowsDeleted) diff --git a/pkg/services/queryhistory/queryhistory_migrate_test.go b/pkg/services/queryhistory/queryhistory_migrate_test.go index a8f5667eb25..5c2d393a5ba 100644 --- a/pkg/services/queryhistory/queryhistory_migrate_test.go +++ b/pkg/services/queryhistory/queryhistory_migrate_test.go @@ -3,7 +3,6 @@ package queryhistory import ( "encoding/json" "testing" - "time" "github.com/stretchr/testify/require" @@ -25,7 +24,7 @@ func TestIntegrationMigrateQueriesToQueryHistory(t *testing.T) { }), Comment: "", Starred: false, - CreatedAt: time.Now().Unix(), + CreatedAt: sc.service.now().Unix(), }, }, } @@ -51,7 +50,7 @@ func TestIntegrationMigrateQueriesToQueryHistory(t *testing.T) { }), Comment: "", Starred: false, - CreatedAt: time.Now().Unix(), + CreatedAt: sc.service.now().Unix(), }, { DatasourceUID: "NCzh67i", @@ -60,7 +59,7 @@ func TestIntegrationMigrateQueriesToQueryHistory(t *testing.T) { }), Comment: "", Starred: false, - CreatedAt: time.Now().Unix() - int64(100), + CreatedAt: sc.service.now().Unix() - int64(100), }, { DatasourceUID: "ABch68f", @@ -69,7 +68,7 @@ func TestIntegrationMigrateQueriesToQueryHistory(t *testing.T) { }), Comment: "", Starred: false, - CreatedAt: time.Now().Unix() - int64(1000), + CreatedAt: sc.service.now().Unix() - int64(1000), }, }, } @@ -95,7 +94,7 @@ func TestIntegrationMigrateQueriesToQueryHistory(t *testing.T) { }), Comment: "", Starred: true, - CreatedAt: time.Now().Unix(), + CreatedAt: sc.service.now().Unix(), }, { DatasourceUID: "NCzh67i", @@ -104,7 +103,7 @@ func TestIntegrationMigrateQueriesToQueryHistory(t *testing.T) { }), Comment: "", Starred: false, - CreatedAt: time.Now().Unix() - int64(100), + CreatedAt: sc.service.now().Unix() - int64(100), }, }, } diff --git a/pkg/services/queryhistory/queryhistory_search_test.go b/pkg/services/queryhistory/queryhistory_search_test.go index 24ca3f67f11..ccce6d8a5f6 100644 --- a/pkg/services/queryhistory/queryhistory_search_test.go +++ b/pkg/services/queryhistory/queryhistory_search_test.go @@ -4,7 +4,6 @@ import ( "encoding/json" "strconv" "testing" - "time" "github.com/stretchr/testify/require" ) @@ -123,7 +122,7 @@ func TestIntegrationGetQueriesFromQueryHistory(t *testing.T) { testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from filter, it should return correct queries", func(t *testing.T, sc scenarioContext) { - sc.reqContext.Req.Form.Add("from", strconv.FormatInt(time.Now().UnixMilli()-60*1000, 10)) + sc.reqContext.Req.Form.Add("from", strconv.FormatInt(sc.service.now().UnixMilli()-60*1000, 10)) resp := sc.service.searchHandler(sc.reqContext) var response QueryHistorySearchResponse err := json.Unmarshal(resp.Body(), &response) @@ -145,7 +144,7 @@ func TestIntegrationGetQueriesFromQueryHistory(t *testing.T) { testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from filter, it should return no queries", func(t *testing.T, sc scenarioContext) { - sc.reqContext.Req.Form.Add("from", strconv.FormatInt(time.Now().UnixMilli()+60*1000, 10)) + sc.reqContext.Req.Form.Add("from", strconv.FormatInt(sc.service.now().UnixMilli()+60*1000, 10)) resp := sc.service.searchHandler(sc.reqContext) var response QueryHistorySearchResponse err := json.Unmarshal(resp.Body(), &response) @@ -167,7 +166,7 @@ func TestIntegrationGetQueriesFromQueryHistory(t *testing.T) { testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using to filter, it should return correct queries", func(t *testing.T, sc scenarioContext) { - sc.reqContext.Req.Form.Add("to", strconv.FormatInt(time.Now().UnixMilli(), 10)) + sc.reqContext.Req.Form.Add("to", strconv.FormatInt(sc.service.now().UnixMilli(), 10)) resp := sc.service.searchHandler(sc.reqContext) var response QueryHistorySearchResponse err := json.Unmarshal(resp.Body(), &response) @@ -189,7 +188,7 @@ func TestIntegrationGetQueriesFromQueryHistory(t *testing.T) { testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using to filter, it should return no queries", func(t *testing.T, sc scenarioContext) { - sc.reqContext.Req.Form.Add("to", strconv.FormatInt(time.Now().UnixMilli()-60*1000, 10)) + sc.reqContext.Req.Form.Add("to", strconv.FormatInt(sc.service.now().UnixMilli()-60*1000, 10)) resp := sc.service.searchHandler(sc.reqContext) var response QueryHistorySearchResponse err := json.Unmarshal(resp.Body(), &response) @@ -211,8 +210,8 @@ func TestIntegrationGetQueriesFromQueryHistory(t *testing.T) { testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from and to filter, it should return correct queries", func(t *testing.T, sc scenarioContext) { - sc.reqContext.Req.Form.Add("to", strconv.FormatInt(time.Now().UnixMilli(), 10)) - sc.reqContext.Req.Form.Add("from", strconv.FormatInt(time.Now().UnixMilli()-60*1000, 10)) + sc.reqContext.Req.Form.Add("to", strconv.FormatInt(sc.service.now().UnixMilli(), 10)) + sc.reqContext.Req.Form.Add("from", strconv.FormatInt(sc.service.now().UnixMilli()-60*1000, 10)) resp := sc.service.searchHandler(sc.reqContext) var response QueryHistorySearchResponse err := json.Unmarshal(resp.Body(), &response) @@ -223,8 +222,8 @@ func TestIntegrationGetQueriesFromQueryHistory(t *testing.T) { testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from and to filter with other filters, it should return correct queries", func(t *testing.T, sc scenarioContext) { - sc.reqContext.Req.Form.Add("to", strconv.FormatInt(time.Now().UnixMilli(), 10)) - sc.reqContext.Req.Form.Add("from", strconv.FormatInt(time.Now().UnixMilli()-60*1000, 10)) + sc.reqContext.Req.Form.Add("to", strconv.FormatInt(sc.service.now().UnixMilli(), 10)) + sc.reqContext.Req.Form.Add("from", strconv.FormatInt(sc.service.now().UnixMilli()-60*1000, 10)) sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1) sc.reqContext.Req.Form.Add("searchString", "2") resp := sc.service.searchHandler(sc.reqContext) @@ -251,8 +250,8 @@ func TestIntegrationGetQueriesFromQueryHistory(t *testing.T) { testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from and to filter with other filters, it should return no query", func(t *testing.T, sc scenarioContext) { - sc.reqContext.Req.Form.Add("to", strconv.FormatInt(time.Now().UnixMilli()-60, 10)) - sc.reqContext.Req.Form.Add("from", strconv.FormatInt(time.Now().UnixMilli()+60, 10)) + sc.reqContext.Req.Form.Add("to", strconv.FormatInt(sc.service.now().UnixMilli()-60, 10)) + sc.reqContext.Req.Form.Add("from", strconv.FormatInt(sc.service.now().UnixMilli()+60, 10)) sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1) sc.reqContext.Req.Form.Add("searchString", "2") resp := sc.service.searchHandler(sc.reqContext) diff --git a/pkg/services/queryhistory/queryhistory_test.go b/pkg/services/queryhistory/queryhistory_test.go index d112d6cdcb4..37265114ade 100644 --- a/pkg/services/queryhistory/queryhistory_test.go +++ b/pkg/services/queryhistory/queryhistory_test.go @@ -54,6 +54,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo service := QueryHistoryService{ Cfg: setting.NewCfg(), store: sqlStore, + now: time.Now, } service.Cfg.QueryHistoryEnabled = true quotaService := quotatest.New(false, nil) @@ -69,7 +70,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo Email: "signed.in.user@test.com", OrgID: testOrgID, OrgRole: org.RoleViewer, - LastSeenAt: time.Now(), + LastSeenAt: service.now(), } _, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{ @@ -113,6 +114,8 @@ func testScenarioWithMultipleQueriesInQueryHistory(t *testing.T, desc string, fn t.Helper() testScenario(t, desc, func(t *testing.T, sc scenarioContext) { + start := time.Now().Add(-3 * time.Second) + sc.service.now = func() time.Time { return start } command1 := CreateQueryInQueryHistoryCommand{ DatasourceUID: testDsUID1, Queries: simplejson.NewFromAny(map[string]interface{}{ @@ -129,7 +132,7 @@ func testScenarioWithMultipleQueriesInQueryHistory(t *testing.T, desc string, fn sc.reqContext.Req.Body = mockRequestBody(cmd) sc.service.patchCommentHandler(sc.reqContext) - time.Sleep(1 * time.Second) + sc.service.now = func() time.Time { return start.Add(time.Second) } command2 := CreateQueryInQueryHistoryCommand{ DatasourceUID: testDsUID1, Queries: simplejson.NewFromAny(map[string]interface{}{ @@ -142,7 +145,7 @@ func testScenarioWithMultipleQueriesInQueryHistory(t *testing.T, desc string, fn sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result2.Result.UID}) sc.service.starHandler(sc.reqContext) - time.Sleep(1 * time.Second) + sc.service.now = func() time.Time { return start.Add(2 * time.Second) } command3 := CreateQueryInQueryHistoryCommand{ DatasourceUID: testDsUID2, Queries: simplejson.NewFromAny(map[string]interface{}{