返回 DeepSeek-Reasonix
telemetry_app_test.go
根目录 / desktop / telemetry_app_test.go
1 package main
2
3 import (
4 "context"
5 "crypto/rand"
6 "encoding/json"
7 "io"
8 "net/http"
9 "net/http/httptest"
10 "sync"
11 "sync/atomic"
12 "testing"
13 )
14
15 func TestInstallIDStableAcrossCalls(t *testing.T) {
16 isolateDesktopUserDirs(t)
17 first, err := installID()
18 if err != nil {
19 t.Fatal(err)
20 }
21 if !installIDPattern.MatchString(first) {
22 t.Fatalf("installID() = %q, want 32 hex chars", first)
23 }
24 second, err := installID()
25 if err != nil {
26 t.Fatal(err)
27 }
28 if second != first {
29 t.Errorf("second call returned %q, want stable %q", second, first)
30 }
31 }
32
33 func TestInstallIDConcurrentFirstUseGeneratesOneIdentity(t *testing.T) {
34 isolateDesktopUserDirs(t)
35 originalRandRead := installIDRandRead
36 defer func() { installIDRandRead = originalRandRead }()
37
38 firstGenerationStarted := make(chan struct{})
39 releaseGeneration := make(chan struct{})
40 var generations atomic.Int32
41 installIDRandRead = func(p []byte) (int, error) {
42 if generations.Add(1) == 1 {
43 close(firstGenerationStarted)
44 <-releaseGeneration
45 }
46 return rand.Read(p)
47 }
48
49 const callers = 16
50 start := make(chan struct{})
51 results := make(chan string, callers)
52 errors := make(chan error, callers)
53 var ready sync.WaitGroup
54 var done sync.WaitGroup
55 for range callers {
56 ready.Add(1)
57 done.Go(func() {
58 ready.Done()
59 <-start
60 id, err := installID()
61 if err != nil {
62 errors <- err
63 return
64 }
65 results <- id
66 })
67 }
68 ready.Wait()
69 close(start)
70 <-firstGenerationStarted
71 close(releaseGeneration)
72 done.Wait()
73 close(results)
74 close(errors)
75
76 for err := range errors {
77 t.Fatalf("installID: %v", err)
78 }
79 var canonical string
80 for id := range results {
81 if canonical == "" {
82 canonical = id
83 }
84 if id != canonical {
85 t.Fatalf("concurrent install IDs differ: got %q, want %q", id, canonical)
86 }
87 }
88 if got := generations.Load(); got != 1 {
89 t.Fatalf("identity generations = %d, want 1", got)
90 }
91 }
92
93 func TestPostStartupPing(t *testing.T) {
94 var got startupPing
95 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
96 body, _ := io.ReadAll(r.Body)
97 if err := json.Unmarshal(body, &got); err != nil {
98 t.Errorf("body not JSON: %v", err)
99 }
100 w.WriteHeader(http.StatusAccepted)
101 }))
102 defer srv.Close()
103
104 p := startupPing{InstallID: "0123456789abcdef0123456789abcdef", Version: "v9.9.9", OS: "windows", Arch: "amd64", OSVersion: "Windows 10.0 build 26200"}
105 if err := postStartupPing(context.Background(), srv.Client(), srv.URL, p); err != nil {
106 t.Fatal(err)
107 }
108 if got != p {
109 t.Errorf("server received %+v, want %+v", got, p)
110 }
111 }
112
113 func TestSendStartupPingSkipsDevBuild(t *testing.T) {
114 isolateDesktopUserDirs(t)
115 hits := 0
116 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
117 hits++
118 w.WriteHeader(http.StatusAccepted)
119 }))
120 defer srv.Close()
121 old := pingEndpoint
122 pingEndpoint = srv.URL
123 defer func() { pingEndpoint = old }()
124
125 NewApp().sendStartupPing()
126 if hits != 0 {
127 t.Errorf("dev build sent %d pings, want 0", hits)
128 }
129 }
130
130 lines GO