github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/analytics/tilt_analytics_test.go (about)

     1  package analytics
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  
     9  	"github.com/tilt-dev/wmclient/pkg/analytics"
    10  )
    11  
    12  const versionTest = "v0.0.0"
    13  
    14  type testCase struct {
    15  	name         string
    16  	opt          analytics.Opt
    17  	expectRecord bool
    18  }
    19  
    20  var testTags = map[string]string{"bar": "baz"}
    21  
    22  func testCases(expectedWhenOptedIn, expectedWhenOptedOut, expectedWhenNoOpt bool) []testCase {
    23  	return []testCase{
    24  		{"opt in", analytics.OptIn, expectedWhenOptedIn},
    25  		{"opt out", analytics.OptOut, expectedWhenOptedOut},
    26  		{"opt default", analytics.OptDefault, expectedWhenNoOpt},
    27  	}
    28  }
    29  
    30  type userOptSetting struct {
    31  	opt analytics.Opt
    32  }
    33  
    34  func (os *userOptSetting) ReadUserOpt() (analytics.Opt, error) {
    35  	return os.opt, nil
    36  }
    37  
    38  func (os *userOptSetting) SetUserOpt(opt analytics.Opt) error {
    39  	os.opt = opt
    40  	return nil
    41  }
    42  
    43  func TestCount(t *testing.T) {
    44  	for _, test := range testCases(true, false, true) {
    45  		t.Run(test.name, func(t *testing.T) {
    46  			ma := analytics.NewMemoryAnalytics()
    47  			os := &userOptSetting{opt: test.opt}
    48  			a, _ := NewTiltAnalytics(os, ma, versionTest)
    49  			a.opt.env = analytics.OptDefault
    50  			a.Count("foo", testTags, 1)
    51  			var expectedCounts []analytics.CountEvent
    52  			if test.expectRecord {
    53  				expectedCounts = append(expectedCounts, analytics.CountEvent{
    54  					Name: "foo",
    55  					Tags: testTags,
    56  					N:    1,
    57  				})
    58  			}
    59  			assert.Equal(t, expectedCounts, ma.Counts)
    60  		})
    61  	}
    62  }
    63  
    64  func TestIncr(t *testing.T) {
    65  	for _, test := range testCases(true, false, true) {
    66  		t.Run(test.name, func(t *testing.T) {
    67  			ma := analytics.NewMemoryAnalytics()
    68  			os := &userOptSetting{opt: test.opt}
    69  			a, _ := NewTiltAnalytics(os, ma, versionTest)
    70  			a.opt.env = analytics.OptDefault
    71  			a.Incr("foo", testTags)
    72  			var expectedCounts []analytics.CountEvent
    73  			if test.expectRecord {
    74  				expectedCounts = append(expectedCounts, analytics.CountEvent{
    75  					Name: "foo",
    76  					Tags: testTags,
    77  					N:    1,
    78  				})
    79  			}
    80  			assert.Equal(t, expectedCounts, ma.Counts)
    81  		})
    82  	}
    83  }
    84  
    85  func TestTimer(t *testing.T) {
    86  	for _, test := range testCases(true, false, true) {
    87  		t.Run(test.name, func(t *testing.T) {
    88  			ma := analytics.NewMemoryAnalytics()
    89  			os := &userOptSetting{opt: test.opt}
    90  			a, _ := NewTiltAnalytics(os, ma, versionTest)
    91  			a.opt.env = analytics.OptDefault
    92  			a.Timer("foo", time.Second, testTags)
    93  			var expectedTimes []analytics.TimeEvent
    94  			if test.expectRecord {
    95  				expectedTimes = append(expectedTimes, analytics.TimeEvent{
    96  					Name: "foo",
    97  					Tags: testTags,
    98  					Dur:  time.Second,
    99  				})
   100  			}
   101  			assert.Equal(t, expectedTimes, ma.Timers)
   102  		})
   103  	}
   104  }
   105  
   106  func TestWithoutGlobalTags(t *testing.T) {
   107  	ma := analytics.NewMemoryAnalytics()
   108  	os := &userOptSetting{opt: analytics.OptIn}
   109  	a, _ := NewTiltAnalytics(os, ma, versionTest)
   110  	a.opt.env = analytics.OptDefault
   111  	a.WithoutGlobalTags().Incr("foo", testTags)
   112  
   113  	// memory analytics doesn't have global tags, so there's really
   114  	// nothing to test. We mainly want to make sure this doesn't crash.
   115  	assert.Equal(t, 1, len(ma.Counts))
   116  }
   117  
   118  func TestOptPrecedence(t *testing.T) {
   119  	for _, tc := range []struct {
   120  		name                 string
   121  		envOpt               analytics.Opt
   122  		userOpt              analytics.Opt
   123  		tiltfileOpt          analytics.Opt
   124  		expectedEffectiveOpt analytics.Opt
   125  	}{
   126  		{"env opt overrides all", analytics.OptOut, analytics.OptIn, analytics.OptIn, analytics.OptOut},
   127  		{"tiltfile opt overrides user", analytics.OptDefault, analytics.OptOut, analytics.OptIn, analytics.OptIn},
   128  		{"user opt controls if others unset", analytics.OptDefault, analytics.OptOut, analytics.OptDefault, analytics.OptOut},
   129  		{"default opt if none set", analytics.OptDefault, analytics.OptDefault, analytics.OptDefault, analytics.OptDefault},
   130  	} {
   131  		t.Run(tc.name, func(t *testing.T) {
   132  			ma := analytics.NewMemoryAnalytics()
   133  			os := &userOptSetting{opt: tc.userOpt}
   134  			a, _ := NewTiltAnalytics(os, ma, versionTest)
   135  			a.opt.env = tc.envOpt
   136  			a.SetTiltfileOpt(tc.tiltfileOpt)
   137  
   138  			// compare strings for readability
   139  			assert.Equal(t, tc.expectedEffectiveOpt.String(), a.EffectiveOpt().String())
   140  		})
   141  	}
   142  }
   143  
   144  func analyticsViaTransition(t *testing.T, initialOpt, newOpt analytics.Opt) (*TiltAnalytics, *analytics.MemoryAnalytics) {
   145  	ma := analytics.NewMemoryAnalytics()
   146  	os := &userOptSetting{opt: initialOpt}
   147  	a, _ := NewTiltAnalytics(os, ma, versionTest)
   148  	a.opt.env = analytics.OptDefault
   149  	err := a.SetUserOpt(newOpt)
   150  	if !assert.NoError(t, err) {
   151  		assert.FailNow(t, err.Error())
   152  	}
   153  
   154  	if !assert.Equal(t, newOpt, os.opt) {
   155  		t.FailNow()
   156  	}
   157  
   158  	// wipe out the reports of opt-in/out, since those are side effects of test setup, not the test itself
   159  	ma.Counts = nil
   160  
   161  	return a, ma
   162  }
   163  
   164  type transitionTestCase struct {
   165  	name         string
   166  	initialOpt   analytics.Opt
   167  	newOpt       analytics.Opt
   168  	expectRecord bool
   169  }
   170  
   171  func TestOptTransitionIncr(t *testing.T) {
   172  	for _, test := range []transitionTestCase{
   173  		{"default -> out", analytics.OptDefault, analytics.OptOut, false},
   174  		{"default -> in", analytics.OptDefault, analytics.OptIn, true},
   175  		{"in -> out", analytics.OptIn, analytics.OptOut, false},
   176  		{"out -> in", analytics.OptOut, analytics.OptIn, true},
   177  	} {
   178  		t.Run(test.name, func(t *testing.T) {
   179  			a, ma := analyticsViaTransition(t, test.initialOpt, test.newOpt)
   180  			a.Incr("foo", testTags)
   181  			var expectedCounts []analytics.CountEvent
   182  			if test.expectRecord {
   183  				expectedCounts = append(expectedCounts, analytics.CountEvent{
   184  					Name: "foo",
   185  					Tags: testTags,
   186  					N:    1,
   187  				})
   188  			}
   189  			assert.Equal(t, expectedCounts, ma.Counts)
   190  		})
   191  	}
   192  }