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 }