github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libpages/stats_mysql_test.go (about)

     1  // Copyright 2020 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build integration
     6  // +build integration
     7  
     8  package libpages
     9  
    10  import (
    11  	"context"
    12  	"database/sql"
    13  	"fmt"
    14  	"os"
    15  	"strconv"
    16  	"testing"
    17  	"time"
    18  
    19  	_ "github.com/go-sql-driver/mysql"
    20  	"github.com/keybase/client/go/kbfs/test/clocktest"
    21  	"github.com/keybase/client/go/kbfs/tlf"
    22  	"github.com/stretchr/testify/require"
    23  	"go.uber.org/zap"
    24  )
    25  
    26  const defaultTestDSN = "root@unix(/tmp/mysql.sock)/kbp_test?parseTime=true"
    27  const TestDSNEnvName = "TEST_DB_DSN"
    28  
    29  func makeMySQLActivityStatsStorerForTest(t *testing.T) (
    30  	*mysqlActivityStatsStorer, *clocktest.TestClock) {
    31  	logger, err := zap.NewDevelopment()
    32  	require.NoError(t, err)
    33  	dsn := os.Getenv(TestDSNEnvName)
    34  	if len(dsn) == 0 {
    35  		dsn = defaultTestDSN
    36  	}
    37  	db, err := sql.Open("mysql", dsn)
    38  	require.NoError(t, err, "open mysql")
    39  	clock := clocktest.NewTestClockNow()
    40  	return newMySQLActivityStatsStorerNoStart(clock, db, logger), clock
    41  }
    42  
    43  func TestMySQLActivityStatsStorer(t *testing.T) {
    44  	storer, clock := makeMySQLActivityStatsStorerForTest(t)
    45  	storer.createTablesIfNotExists(context.Background())
    46  
    47  	// Make a prefix based on time so we don't have to clear the DB in test.
    48  	domainPrefix := strconv.FormatInt(time.Now().Unix(), 16)
    49  	makeDomain := func(id int) string {
    50  		return fmt.Sprintf("%s-%d.example.com", domainPrefix, id)
    51  	}
    52  
    53  	tlfID1, err := tlf.MakeRandomID(tlf.Public)
    54  	require.NoError(t, err)
    55  	tlfID2, err := tlf.MakeRandomID(tlf.Public)
    56  	require.NoError(t, err)
    57  	host1 := makeDomain(1)
    58  	host2 := makeDomain(2)
    59  	host3 := makeDomain(3)
    60  
    61  	clock.Add(30 * time.Second)
    62  
    63  	// At 00:30
    64  	storer.RecordActives(tlfID1, host1)
    65  	storer.RecordActives(tlfID1, host2)
    66  	storer.RecordActives(tlfID2, host3)
    67  
    68  	clock.Add(time.Minute)
    69  
    70  	// At 01:30
    71  	storer.RecordActives(tlfID1, host1)
    72  	storer.RecordActives(tlfID1, host2)
    73  
    74  	clock.Add(30 * time.Second)
    75  
    76  	storer.flushInserts()
    77  
    78  	// Now we're at 02:00
    79  
    80  	check := func() {
    81  		activeTlfs, activeHosts, err := storer.GetActives(time.Minute)
    82  		require.NoError(t, err)
    83  		require.Equal(t, 1, activeTlfs)
    84  		require.Equal(t, 2, activeHosts)
    85  
    86  		activeTlfs, activeHosts, err = storer.GetActives(2 * time.Minute)
    87  		require.NoError(t, err)
    88  		require.Equal(t, 2, activeTlfs)
    89  		require.Equal(t, 3, activeHosts)
    90  	}
    91  	check()
    92  
    93  	t.Logf("make sure older time don't override newer time")
    94  	clock.Add(-5 * time.Minute)
    95  	storer.RecordActives(tlfID1, host1)
    96  	storer.RecordActives(tlfID1, host2)
    97  	storer.RecordActives(tlfID2, host3)
    98  	clock.Add(5 * time.Minute)
    99  	storer.flushInserts()
   100  	check()
   101  }