package appmetrics import ( "encoding/json" "fmt" "io/ioutil" "os" "testing" "time" "github.com/status-im/status-go/appdatabase" "github.com/stretchr/testify/require" ) func setupTestDB(t *testing.T) (*Database, func()) { tmpfile, err := ioutil.TempFile("", "appmetrics-tests-") require.NoError(t, err) db, err := appdatabase.InitializeDB(tmpfile.Name(), "appmetrics-tests") require.NoError(t, err) return NewDB(db), func() { require.NoError(t, db.Close()) require.NoError(t, os.Remove(tmpfile.Name())) } } func TestSaveAppMetrics(t *testing.T) { sessionID := "rand-omse-ssid" db, stop := setupTestDB(t) defer stop() // we need backticks (``) for value because it is expected by gojsonschema // it considers text inside tics to be stringified json appMetrics := []AppMetric{ {Event: NavigateTo, Value: json.RawMessage(`{"view_id": "some-view-id", "params": {"screen": "login"}}`), OS: "android", AppVersion: "1.11"}, } err := db.SaveAppMetrics(appMetrics, sessionID) require.NoError(t, err) appMetricsPage, err := db.GetAppMetrics(10, 0) res := appMetricsPage.AppMetrics count := appMetricsPage.TotalCount require.NoError(t, err) require.Equal(t, appMetrics[0].Event, res[0].Event) require.Equal(t, appMetrics[0].Value, res[0].Value) require.Equal(t, appMetrics[0].OS, res[0].OS) require.Equal(t, appMetrics[0].AppVersion, res[0].AppVersion) require.False(t, res[0].Processed) require.NotNil(t, res[0].CreatedAt) require.Equal(t, count, 1) } func TestDatabase_GetUnprocessedMetrics(t *testing.T) { db, stop := setupTestDB(t) defer stop() var uam []AppMetric metricsPerSession := 10 unprocessedMetricsPerSession := 5 numberOfSessions := 3 numberOfSessionSaves := 5 for i := 0; i < numberOfSessionSaves; i++ { for ii := 1; ii < numberOfSessions+1; ii++ { err := db.SaveAppMetrics(GenerateMetrics(metricsPerSession), "rand-omse-ssid-"+fmt.Sprint(ii)) require.NoError(t, err) uam, err = db.GetUnprocessed() require.NoError(t, err) require.Len(t, uam, unprocessedMetricsPerSession*ii+(i*numberOfSessions*unprocessedMetricsPerSession)) } } // Test metrics are grouped by session_id lastSessionID := "" sessionCount := 0 for _, m := range uam { if lastSessionID != m.SessionID { lastSessionID = m.SessionID sessionCount++ } } require.Equal(t, numberOfSessions, sessionCount) } func TestDatabase_SetProcessedMetrics(t *testing.T) { db, stop := setupTestDB(t) defer stop() // Add sample data to the DB err := db.SaveAppMetrics(GenerateMetrics(20), "rand-omse-ssid") require.NoError(t, err) // Get only the unprocessed metrics uam, err := db.GetUnprocessed() require.NoError(t, err) // Extract the ids from the metrics IDs ids := GetAppMetricsIDs(uam) // Add some more metrics to the DB err = db.SaveAppMetrics(GenerateMetrics(20), "rand-omse-ssid-2") require.NoError(t, err) // Set metrics as processed with the given ids err = db.SetToProcessedByIDs(ids) require.NoError(t, err) // Check we have the expected number of unprocessed metrics in the db uam, err = db.GetUnprocessed() require.NoError(t, err) require.Len(t, uam, 10) } func TestDatabase_GetUnprocessedGroupedBySession(t *testing.T) { db, stop := setupTestDB(t) defer stop() // Add sample data to the DB err := db.SaveAppMetrics(GenerateMetrics(20), "rand-omse-ssid") require.NoError(t, err) // Add some more metrics to the DB err = db.SaveAppMetrics(GenerateMetrics(20), "rand-omse-ssid-2") require.NoError(t, err) // Check we have the expected number of unprocessed metrics in the db uam, err := db.GetUnprocessedGroupedBySession() require.NoError(t, err) // Check we have 2 groups / sessions require.Len(t, uam, 2) require.Len(t, uam["rand-omse-ssid"], 10) require.Len(t, uam["rand-omse-ssid-2"], 10) } func TestDatabase_DeleteOlderThan(t *testing.T) { db, stop := setupTestDB(t) defer stop() threeHoursAgo := time.Now().Add(time.Hour * -3) // go is annoying sometimes oneHourHence := time.Now().Add(time.Hour) // Add sample data to the DB err := db.SaveAppMetrics(GenerateMetrics(20), "rand-omse-ssid") require.NoError(t, err) // Delete all messages older than 3 hours old err = db.DeleteOlderThan(&threeHoursAgo) require.NoError(t, err) // Get all metrics from DB, none should be deleted ams, err := db.GetAppMetrics(100, 0) require.NoError(t, err) require.Len(t, ams.AppMetrics, 20) // Delete all messages older than 1 hours in the future err = db.DeleteOlderThan(&oneHourHence) require.NoError(t, err) // Get all metrics from DB, all should be deleted ams, err = db.GetAppMetrics(100, 0) require.NoError(t, err) require.Len(t, ams.AppMetrics, 0) }