1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package driver
16
17 import (
18 "context"
19 "fmt"
20 "os/exec"
21 "regexp"
22 "runtime"
23 "strings"
24 "testing"
25 "time"
26
27 _ "embed"
28
29 "github.com/chromedp/chromedp"
30 )
31
32 func maybeSkipBrowserTest(t *testing.T) {
33
34
35
36 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
37 t.Skip("This test only works on x86-64 Linux")
38 }
39
40
41 if _, err := exec.LookPath("google-chrome"); err == nil {
42 return
43 }
44 if _, err := exec.LookPath("chrome"); err == nil {
45 return
46 }
47 t.Skip("chrome not available")
48 }
49
50
51
52 const browserDeadline = time.Second * 60
53
54 func TestTopTable(t *testing.T) {
55 maybeSkipBrowserTest(t)
56
57 prof := makeFakeProfile()
58 server := makeTestServer(t, prof)
59 ctx, cancel := context.WithTimeout(context.Background(), browserDeadline)
60 defer cancel()
61 ctx, cancel = chromedp.NewContext(ctx)
62 defer cancel()
63
64 err := chromedp.Run(ctx,
65 chromedp.Navigate(server.URL+"/top"),
66 chromedp.WaitVisible(`#toptable`, chromedp.ByID),
67
68
69 matchRegexp(t, "#node0", `200ms.*F2`),
70 matchInOrder(t, "#toptable", "F2", "F3", "F1"),
71
72
73 chromedp.Click(`#cumhdr1`, chromedp.ByID),
74 matchInOrder(t, "#toptable", "F1", "F2", "F3"),
75 )
76 if err != nil {
77 t.Fatal(err)
78 }
79 }
80
81 func TestFlameGraph(t *testing.T) {
82 maybeSkipBrowserTest(t)
83
84 prof := makeFakeProfile()
85 server := makeTestServer(t, prof)
86 ctx, cancel := context.WithTimeout(context.Background(), browserDeadline)
87 defer cancel()
88 ctx, cancel = chromedp.NewContext(ctx)
89 defer cancel()
90
91 var ignored []byte
92 err := chromedp.Run(ctx,
93 chromedp.Navigate(server.URL+"/flamegraph"),
94 chromedp.Evaluate(jsTestFixture, &ignored),
95 eval(t, jsCheckFlame),
96 )
97 if err != nil {
98 t.Fatal(err)
99 }
100 }
101
102
103 var jsCheckFlame string
104
105 func TestSource(t *testing.T) {
106 maybeSkipBrowserTest(t)
107
108 prof := makeFakeProfile()
109 server := makeTestServer(t, prof)
110 ctx, cancel := context.WithTimeout(context.Background(), browserDeadline)
111 defer cancel()
112 ctx, cancel = chromedp.NewContext(ctx)
113 defer cancel()
114
115 err := chromedp.Run(ctx,
116 chromedp.Navigate(server.URL+"/source?f=F3"),
117 chromedp.WaitVisible(`#content`, chromedp.ByID),
118 matchRegexp(t, "#content", `F3`),
119 matchRegexp(t, "#content", `Total:.*100ms`),
120 matchRegexp(t, "#content", `\b22\b.*100ms`),
121 )
122 if err != nil {
123 t.Fatal(err)
124 }
125 }
126
127
128
129 func matchRegexp(t *testing.T, query, re string) chromedp.ActionFunc {
130 return func(ctx context.Context) error {
131 var value string
132 err := chromedp.Text(query, &value, chromedp.ByQuery).Do(ctx)
133 if err != nil {
134 return fmt.Errorf("text %s: %v", query, err)
135 }
136 t.Logf("text %s:\n%s", query, value)
137 m, err := regexp.MatchString(re, value)
138 if err != nil {
139 return err
140 }
141 if !m {
142 return fmt.Errorf("%s: did not find %q in\n%s", query, re, value)
143 }
144 return nil
145 }
146 }
147
148
149
150
151 func matchInOrder(t *testing.T, query string, sequence ...string) chromedp.ActionFunc {
152 return func(ctx context.Context) error {
153 var value string
154 err := chromedp.Text(query, &value, chromedp.ByQuery).Do(ctx)
155 if err != nil {
156 return fmt.Errorf("text %s: %v", query, err)
157 }
158 t.Logf("text %s:\n%s", query, value)
159 remaining := value
160 for _, s := range sequence {
161 pos := strings.Index(remaining, s)
162 if pos < 0 {
163 return fmt.Errorf("%s: did not find %q in expected order %v in\n%s", query, s, sequence, value)
164 }
165 remaining = remaining[pos+len(s):]
166 }
167 return nil
168 }
169 }
170
171
172
173
174 func eval(t *testing.T, js string) chromedp.ActionFunc {
175 return func(ctx context.Context) error {
176 var result [][]any
177 err := chromedp.Evaluate(js, &result).Do(ctx)
178 if err != nil {
179 return err
180 }
181 for _, s := range result {
182 if len(s) > 0 && s[0] == "LOG" {
183 t.Log(s[1:]...)
184 } else if len(s) > 0 && s[0] == "ERROR" {
185 t.Error(s[1:]...)
186 } else {
187 t.Error(s...)
188 }
189 }
190 return nil
191 }
192 }
193
194
195 var jsTestFixture string
196
View as plain text