]>
Commit | Line | Data |
---|---|---|
dd931d9b ILT |
1 | // Copyright 2018 The Go Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style | |
3 | // license that can be found in the LICENSE file. | |
4 | ||
5 | // +build js,wasm | |
6 | ||
4f4a855d ILT |
7 | // To run these tests: |
8 | // | |
9 | // - Install Node | |
10 | // - Add /path/to/go/misc/wasm to your $PATH (so that "go test" can find | |
11 | // "go_js_wasm_exec"). | |
12 | // - GOOS=js GOARCH=wasm go test | |
13 | // | |
14 | // See -exec in "go help test", and "go help run" for details. | |
15 | ||
dd931d9b ILT |
16 | package js_test |
17 | ||
18 | import ( | |
19 | "fmt" | |
20 | "math" | |
5a8ea165 | 21 | "runtime" |
dd931d9b ILT |
22 | "syscall/js" |
23 | "testing" | |
24 | ) | |
25 | ||
26 | var dummys = js.Global().Call("eval", `({ | |
27 | someBool: true, | |
28 | someString: "abc\u1234", | |
29 | someInt: 42, | |
30 | someFloat: 42.123, | |
31 | someArray: [41, 42, 43], | |
4f4a855d | 32 | someDate: new Date(), |
dd931d9b ILT |
33 | add: function(a, b) { |
34 | return a + b; | |
35 | }, | |
4f4a855d ILT |
36 | zero: 0, |
37 | stringZero: "0", | |
dd931d9b | 38 | NaN: NaN, |
4f4a855d ILT |
39 | emptyObj: {}, |
40 | emptyArray: [], | |
41 | Infinity: Infinity, | |
42 | NegInfinity: -Infinity, | |
43 | objNumber0: new Number(0), | |
44 | objBooleanFalse: new Boolean(false), | |
dd931d9b ILT |
45 | })`) |
46 | ||
47 | func TestBool(t *testing.T) { | |
48 | want := true | |
49 | o := dummys.Get("someBool") | |
50 | if got := o.Bool(); got != want { | |
51 | t.Errorf("got %#v, want %#v", got, want) | |
52 | } | |
53 | dummys.Set("otherBool", want) | |
54 | if got := dummys.Get("otherBool").Bool(); got != want { | |
55 | t.Errorf("got %#v, want %#v", got, want) | |
56 | } | |
5a8ea165 | 57 | if !dummys.Get("someBool").Equal(dummys.Get("someBool")) { |
dd931d9b ILT |
58 | t.Errorf("same value not equal") |
59 | } | |
60 | } | |
61 | ||
62 | func TestString(t *testing.T) { | |
63 | want := "abc\u1234" | |
64 | o := dummys.Get("someString") | |
65 | if got := o.String(); got != want { | |
66 | t.Errorf("got %#v, want %#v", got, want) | |
67 | } | |
68 | dummys.Set("otherString", want) | |
69 | if got := dummys.Get("otherString").String(); got != want { | |
70 | t.Errorf("got %#v, want %#v", got, want) | |
71 | } | |
5a8ea165 | 72 | if !dummys.Get("someString").Equal(dummys.Get("someString")) { |
dd931d9b ILT |
73 | t.Errorf("same value not equal") |
74 | } | |
75 | ||
aa8901e9 ILT |
76 | if got, want := js.Undefined().String(), "<undefined>"; got != want { |
77 | t.Errorf("got %#v, want %#v", got, want) | |
78 | } | |
79 | if got, want := js.Null().String(), "<null>"; got != want { | |
80 | t.Errorf("got %#v, want %#v", got, want) | |
81 | } | |
82 | if got, want := js.ValueOf(true).String(), "<boolean: true>"; got != want { | |
83 | t.Errorf("got %#v, want %#v", got, want) | |
84 | } | |
85 | if got, want := js.ValueOf(42.5).String(), "<number: 42.5>"; got != want { | |
86 | t.Errorf("got %#v, want %#v", got, want) | |
87 | } | |
88 | if got, want := js.Global().Call("Symbol").String(), "<symbol>"; got != want { | |
89 | t.Errorf("got %#v, want %#v", got, want) | |
90 | } | |
91 | if got, want := js.Global().String(), "<object>"; got != want { | |
92 | t.Errorf("got %#v, want %#v", got, want) | |
93 | } | |
94 | if got, want := js.Global().Get("setTimeout").String(), "<function>"; got != want { | |
95 | t.Errorf("got %#v, want %#v", got, want) | |
dd931d9b ILT |
96 | } |
97 | } | |
98 | ||
99 | func TestInt(t *testing.T) { | |
100 | want := 42 | |
101 | o := dummys.Get("someInt") | |
102 | if got := o.Int(); got != want { | |
103 | t.Errorf("got %#v, want %#v", got, want) | |
104 | } | |
105 | dummys.Set("otherInt", want) | |
106 | if got := dummys.Get("otherInt").Int(); got != want { | |
107 | t.Errorf("got %#v, want %#v", got, want) | |
108 | } | |
5a8ea165 | 109 | if !dummys.Get("someInt").Equal(dummys.Get("someInt")) { |
dd931d9b ILT |
110 | t.Errorf("same value not equal") |
111 | } | |
4f4a855d ILT |
112 | if got := dummys.Get("zero").Int(); got != 0 { |
113 | t.Errorf("got %#v, want %#v", got, 0) | |
114 | } | |
dd931d9b ILT |
115 | } |
116 | ||
117 | func TestIntConversion(t *testing.T) { | |
118 | testIntConversion(t, 0) | |
119 | testIntConversion(t, 1) | |
120 | testIntConversion(t, -1) | |
121 | testIntConversion(t, 1<<20) | |
122 | testIntConversion(t, -1<<20) | |
123 | testIntConversion(t, 1<<40) | |
124 | testIntConversion(t, -1<<40) | |
125 | testIntConversion(t, 1<<60) | |
126 | testIntConversion(t, -1<<60) | |
127 | } | |
128 | ||
129 | func testIntConversion(t *testing.T, want int) { | |
130 | if got := js.ValueOf(want).Int(); got != want { | |
131 | t.Errorf("got %#v, want %#v", got, want) | |
132 | } | |
133 | } | |
134 | ||
135 | func TestFloat(t *testing.T) { | |
136 | want := 42.123 | |
137 | o := dummys.Get("someFloat") | |
138 | if got := o.Float(); got != want { | |
139 | t.Errorf("got %#v, want %#v", got, want) | |
140 | } | |
141 | dummys.Set("otherFloat", want) | |
142 | if got := dummys.Get("otherFloat").Float(); got != want { | |
143 | t.Errorf("got %#v, want %#v", got, want) | |
144 | } | |
5a8ea165 | 145 | if !dummys.Get("someFloat").Equal(dummys.Get("someFloat")) { |
dd931d9b ILT |
146 | t.Errorf("same value not equal") |
147 | } | |
148 | } | |
149 | ||
150 | func TestObject(t *testing.T) { | |
5a8ea165 | 151 | if !dummys.Get("someArray").Equal(dummys.Get("someArray")) { |
dd931d9b ILT |
152 | t.Errorf("same value not equal") |
153 | } | |
154 | ||
155 | // An object and its prototype should not be equal. | |
156 | proto := js.Global().Get("Object").Get("prototype") | |
157 | o := js.Global().Call("eval", "new Object()") | |
5a8ea165 | 158 | if proto.Equal(o) { |
dd931d9b ILT |
159 | t.Errorf("object equals to its prototype") |
160 | } | |
161 | } | |
162 | ||
163 | func TestFrozenObject(t *testing.T) { | |
164 | o := js.Global().Call("eval", "(function () { let o = new Object(); o.field = 5; Object.freeze(o); return o; })()") | |
165 | want := 5 | |
166 | if got := o.Get("field").Int(); want != got { | |
167 | t.Errorf("got %#v, want %#v", got, want) | |
168 | } | |
169 | } | |
170 | ||
5a8ea165 ILT |
171 | func TestEqual(t *testing.T) { |
172 | if !dummys.Get("someFloat").Equal(dummys.Get("someFloat")) { | |
173 | t.Errorf("same float is not equal") | |
174 | } | |
175 | if !dummys.Get("emptyObj").Equal(dummys.Get("emptyObj")) { | |
176 | t.Errorf("same object is not equal") | |
177 | } | |
178 | if dummys.Get("someFloat").Equal(dummys.Get("someInt")) { | |
179 | t.Errorf("different values are not unequal") | |
180 | } | |
181 | } | |
182 | ||
dd931d9b | 183 | func TestNaN(t *testing.T) { |
5a8ea165 ILT |
184 | if !dummys.Get("NaN").IsNaN() { |
185 | t.Errorf("JS NaN is not NaN") | |
186 | } | |
187 | if !js.ValueOf(math.NaN()).IsNaN() { | |
188 | t.Errorf("Go NaN is not NaN") | |
189 | } | |
190 | if dummys.Get("NaN").Equal(dummys.Get("NaN")) { | |
191 | t.Errorf("NaN is equal to NaN") | |
dd931d9b ILT |
192 | } |
193 | } | |
194 | ||
195 | func TestUndefined(t *testing.T) { | |
5a8ea165 ILT |
196 | if !js.Undefined().IsUndefined() { |
197 | t.Errorf("undefined is not undefined") | |
198 | } | |
199 | if !js.Undefined().Equal(js.Undefined()) { | |
200 | t.Errorf("undefined is not equal to undefined") | |
201 | } | |
202 | if dummys.IsUndefined() { | |
203 | t.Errorf("object is undefined") | |
204 | } | |
205 | if js.Undefined().IsNull() { | |
206 | t.Errorf("undefined is null") | |
207 | } | |
208 | if dummys.Set("test", js.Undefined()); !dummys.Get("test").IsUndefined() { | |
209 | t.Errorf("could not set undefined") | |
dd931d9b ILT |
210 | } |
211 | } | |
212 | ||
213 | func TestNull(t *testing.T) { | |
5a8ea165 ILT |
214 | if !js.Null().IsNull() { |
215 | t.Errorf("null is not null") | |
216 | } | |
217 | if !js.Null().Equal(js.Null()) { | |
218 | t.Errorf("null is not equal to null") | |
219 | } | |
220 | if dummys.IsNull() { | |
221 | t.Errorf("object is null") | |
222 | } | |
223 | if js.Null().IsUndefined() { | |
224 | t.Errorf("null is undefined") | |
225 | } | |
226 | if dummys.Set("test", js.Null()); !dummys.Get("test").IsNull() { | |
227 | t.Errorf("could not set null") | |
228 | } | |
229 | if dummys.Set("test", nil); !dummys.Get("test").IsNull() { | |
230 | t.Errorf("could not set nil") | |
dd931d9b ILT |
231 | } |
232 | } | |
233 | ||
234 | func TestLength(t *testing.T) { | |
235 | if got := dummys.Get("someArray").Length(); got != 3 { | |
236 | t.Errorf("got %#v, want %#v", got, 3) | |
237 | } | |
238 | } | |
239 | ||
aa8901e9 ILT |
240 | func TestGet(t *testing.T) { |
241 | // positive cases get tested per type | |
242 | ||
243 | expectValueError(t, func() { | |
244 | dummys.Get("zero").Get("badField") | |
245 | }) | |
246 | } | |
247 | ||
248 | func TestSet(t *testing.T) { | |
249 | // positive cases get tested per type | |
250 | ||
251 | expectValueError(t, func() { | |
252 | dummys.Get("zero").Set("badField", 42) | |
253 | }) | |
254 | } | |
255 | ||
5a8ea165 ILT |
256 | func TestDelete(t *testing.T) { |
257 | dummys.Set("test", 42) | |
258 | dummys.Delete("test") | |
259 | if dummys.Call("hasOwnProperty", "test").Bool() { | |
260 | t.Errorf("property still exists") | |
261 | } | |
262 | ||
263 | expectValueError(t, func() { | |
264 | dummys.Get("zero").Delete("badField") | |
265 | }) | |
266 | } | |
267 | ||
dd931d9b ILT |
268 | func TestIndex(t *testing.T) { |
269 | if got := dummys.Get("someArray").Index(1).Int(); got != 42 { | |
270 | t.Errorf("got %#v, want %#v", got, 42) | |
271 | } | |
aa8901e9 ILT |
272 | |
273 | expectValueError(t, func() { | |
274 | dummys.Get("zero").Index(1) | |
275 | }) | |
dd931d9b ILT |
276 | } |
277 | ||
278 | func TestSetIndex(t *testing.T) { | |
279 | dummys.Get("someArray").SetIndex(2, 99) | |
280 | if got := dummys.Get("someArray").Index(2).Int(); got != 99 { | |
281 | t.Errorf("got %#v, want %#v", got, 99) | |
282 | } | |
aa8901e9 ILT |
283 | |
284 | expectValueError(t, func() { | |
285 | dummys.Get("zero").SetIndex(2, 99) | |
286 | }) | |
dd931d9b ILT |
287 | } |
288 | ||
289 | func TestCall(t *testing.T) { | |
290 | var i int64 = 40 | |
291 | if got := dummys.Call("add", i, 2).Int(); got != 42 { | |
292 | t.Errorf("got %#v, want %#v", got, 42) | |
293 | } | |
294 | if got := dummys.Call("add", js.Global().Call("eval", "40"), 2).Int(); got != 42 { | |
295 | t.Errorf("got %#v, want %#v", got, 42) | |
296 | } | |
aa8901e9 ILT |
297 | |
298 | expectPanic(t, func() { | |
299 | dummys.Call("zero") | |
300 | }) | |
301 | expectValueError(t, func() { | |
302 | dummys.Get("zero").Call("badMethod") | |
303 | }) | |
dd931d9b ILT |
304 | } |
305 | ||
306 | func TestInvoke(t *testing.T) { | |
307 | var i int64 = 40 | |
308 | if got := dummys.Get("add").Invoke(i, 2).Int(); got != 42 { | |
309 | t.Errorf("got %#v, want %#v", got, 42) | |
310 | } | |
aa8901e9 ILT |
311 | |
312 | expectValueError(t, func() { | |
313 | dummys.Get("zero").Invoke() | |
314 | }) | |
dd931d9b ILT |
315 | } |
316 | ||
317 | func TestNew(t *testing.T) { | |
318 | if got := js.Global().Get("Array").New(42).Length(); got != 42 { | |
319 | t.Errorf("got %#v, want %#v", got, 42) | |
320 | } | |
aa8901e9 ILT |
321 | |
322 | expectValueError(t, func() { | |
323 | dummys.Get("zero").New() | |
324 | }) | |
dd931d9b ILT |
325 | } |
326 | ||
327 | func TestInstanceOf(t *testing.T) { | |
328 | someArray := js.Global().Get("Array").New() | |
329 | if got, want := someArray.InstanceOf(js.Global().Get("Array")), true; got != want { | |
330 | t.Errorf("got %#v, want %#v", got, want) | |
331 | } | |
332 | if got, want := someArray.InstanceOf(js.Global().Get("Function")), false; got != want { | |
333 | t.Errorf("got %#v, want %#v", got, want) | |
334 | } | |
335 | } | |
336 | ||
337 | func TestType(t *testing.T) { | |
338 | if got, want := js.Undefined().Type(), js.TypeUndefined; got != want { | |
339 | t.Errorf("got %s, want %s", got, want) | |
340 | } | |
341 | if got, want := js.Null().Type(), js.TypeNull; got != want { | |
342 | t.Errorf("got %s, want %s", got, want) | |
343 | } | |
344 | if got, want := js.ValueOf(true).Type(), js.TypeBoolean; got != want { | |
345 | t.Errorf("got %s, want %s", got, want) | |
346 | } | |
4f4a855d ILT |
347 | if got, want := js.ValueOf(0).Type(), js.TypeNumber; got != want { |
348 | t.Errorf("got %s, want %s", got, want) | |
349 | } | |
dd931d9b ILT |
350 | if got, want := js.ValueOf(42).Type(), js.TypeNumber; got != want { |
351 | t.Errorf("got %s, want %s", got, want) | |
352 | } | |
353 | if got, want := js.ValueOf("test").Type(), js.TypeString; got != want { | |
354 | t.Errorf("got %s, want %s", got, want) | |
355 | } | |
356 | if got, want := js.Global().Get("Symbol").Invoke("test").Type(), js.TypeSymbol; got != want { | |
357 | t.Errorf("got %s, want %s", got, want) | |
358 | } | |
359 | if got, want := js.Global().Get("Array").New().Type(), js.TypeObject; got != want { | |
360 | t.Errorf("got %s, want %s", got, want) | |
361 | } | |
362 | if got, want := js.Global().Get("Array").Type(), js.TypeFunction; got != want { | |
363 | t.Errorf("got %s, want %s", got, want) | |
364 | } | |
365 | } | |
366 | ||
367 | type object = map[string]interface{} | |
368 | type array = []interface{} | |
369 | ||
370 | func TestValueOf(t *testing.T) { | |
371 | a := js.ValueOf(array{0, array{0, 42, 0}, 0}) | |
372 | if got := a.Index(1).Index(1).Int(); got != 42 { | |
373 | t.Errorf("got %v, want %v", got, 42) | |
374 | } | |
375 | ||
376 | o := js.ValueOf(object{"x": object{"y": 42}}) | |
377 | if got := o.Get("x").Get("y").Int(); got != 42 { | |
378 | t.Errorf("got %v, want %v", got, 42) | |
379 | } | |
380 | } | |
381 | ||
4f4a855d ILT |
382 | func TestZeroValue(t *testing.T) { |
383 | var v js.Value | |
5a8ea165 | 384 | if !v.IsUndefined() { |
4f4a855d ILT |
385 | t.Error("zero js.Value is not js.Undefined()") |
386 | } | |
387 | } | |
388 | ||
389 | func TestFuncOf(t *testing.T) { | |
dd931d9b | 390 | c := make(chan struct{}) |
4f4a855d | 391 | cb := js.FuncOf(func(this js.Value, args []js.Value) interface{} { |
dd931d9b ILT |
392 | if got := args[0].Int(); got != 42 { |
393 | t.Errorf("got %#v, want %#v", got, 42) | |
394 | } | |
395 | c <- struct{}{} | |
4f4a855d | 396 | return nil |
dd931d9b ILT |
397 | }) |
398 | defer cb.Release() | |
399 | js.Global().Call("setTimeout", cb, 0, 42) | |
400 | <-c | |
401 | } | |
402 | ||
4f4a855d ILT |
403 | func TestInvokeFunction(t *testing.T) { |
404 | called := false | |
405 | cb := js.FuncOf(func(this js.Value, args []js.Value) interface{} { | |
406 | cb2 := js.FuncOf(func(this js.Value, args []js.Value) interface{} { | |
407 | called = true | |
408 | return 42 | |
dd931d9b | 409 | }) |
4f4a855d ILT |
410 | defer cb2.Release() |
411 | return cb2.Invoke() | |
412 | }) | |
413 | defer cb.Release() | |
414 | if got := cb.Invoke().Int(); got != 42 { | |
415 | t.Errorf("got %#v, want %#v", got, 42) | |
416 | } | |
417 | if !called { | |
418 | t.Error("function not called") | |
dd931d9b ILT |
419 | } |
420 | } | |
421 | ||
5a8ea165 ILT |
422 | func TestInterleavedFunctions(t *testing.T) { |
423 | c1 := make(chan struct{}) | |
424 | c2 := make(chan struct{}) | |
425 | ||
426 | js.Global().Get("setTimeout").Invoke(js.FuncOf(func(this js.Value, args []js.Value) interface{} { | |
427 | c1 <- struct{}{} | |
428 | <-c2 | |
429 | return nil | |
430 | }), 0) | |
431 | ||
432 | <-c1 | |
433 | c2 <- struct{}{} | |
434 | // this goroutine is running, but the callback of setTimeout did not return yet, invoke another function now | |
435 | f := js.FuncOf(func(this js.Value, args []js.Value) interface{} { | |
436 | return nil | |
437 | }) | |
438 | f.Invoke() | |
439 | } | |
440 | ||
4f4a855d ILT |
441 | func ExampleFuncOf() { |
442 | var cb js.Func | |
443 | cb = js.FuncOf(func(this js.Value, args []js.Value) interface{} { | |
dd931d9b | 444 | fmt.Println("button clicked") |
4f4a855d ILT |
445 | cb.Release() // release the function if the button will not be clicked again |
446 | return nil | |
dd931d9b ILT |
447 | }) |
448 | js.Global().Get("document").Call("getElementById", "myButton").Call("addEventListener", "click", cb) | |
449 | } | |
4f4a855d ILT |
450 | |
451 | // See | |
452 | // - https://developer.mozilla.org/en-US/docs/Glossary/Truthy | |
453 | // - https://stackoverflow.com/questions/19839952/all-falsey-values-in-javascript/19839953#19839953 | |
454 | // - http://www.ecma-international.org/ecma-262/5.1/#sec-9.2 | |
455 | func TestTruthy(t *testing.T) { | |
456 | want := true | |
457 | for _, key := range []string{ | |
458 | "someBool", "someString", "someInt", "someFloat", "someArray", "someDate", | |
459 | "stringZero", // "0" is truthy | |
460 | "add", // functions are truthy | |
461 | "emptyObj", "emptyArray", "Infinity", "NegInfinity", | |
462 | // All objects are truthy, even if they're Number(0) or Boolean(false). | |
463 | "objNumber0", "objBooleanFalse", | |
464 | } { | |
465 | if got := dummys.Get(key).Truthy(); got != want { | |
466 | t.Errorf("%s: got %#v, want %#v", key, got, want) | |
467 | } | |
468 | } | |
469 | ||
470 | want = false | |
471 | if got := dummys.Get("zero").Truthy(); got != want { | |
472 | t.Errorf("got %#v, want %#v", got, want) | |
473 | } | |
474 | if got := dummys.Get("NaN").Truthy(); got != want { | |
475 | t.Errorf("got %#v, want %#v", got, want) | |
476 | } | |
477 | if got := js.ValueOf("").Truthy(); got != want { | |
478 | t.Errorf("got %#v, want %#v", got, want) | |
479 | } | |
480 | if got := js.Null().Truthy(); got != want { | |
481 | t.Errorf("got %#v, want %#v", got, want) | |
482 | } | |
483 | if got := js.Undefined().Truthy(); got != want { | |
484 | t.Errorf("got %#v, want %#v", got, want) | |
485 | } | |
486 | } | |
aa8901e9 ILT |
487 | |
488 | func expectValueError(t *testing.T, fn func()) { | |
489 | defer func() { | |
490 | err := recover() | |
491 | if _, ok := err.(*js.ValueError); !ok { | |
492 | t.Errorf("expected *js.ValueError, got %T", err) | |
493 | } | |
494 | }() | |
495 | fn() | |
496 | } | |
497 | ||
498 | func expectPanic(t *testing.T, fn func()) { | |
499 | defer func() { | |
500 | err := recover() | |
501 | if err == nil { | |
502 | t.Errorf("expected panic") | |
503 | } | |
504 | }() | |
505 | fn() | |
506 | } | |
507 | ||
508 | var copyTests = []struct { | |
509 | srcLen int | |
510 | dstLen int | |
511 | copyLen int | |
512 | }{ | |
513 | {5, 3, 3}, | |
514 | {3, 5, 3}, | |
515 | {0, 0, 0}, | |
516 | } | |
517 | ||
518 | func TestCopyBytesToGo(t *testing.T) { | |
519 | for _, tt := range copyTests { | |
520 | t.Run(fmt.Sprintf("%d-to-%d", tt.srcLen, tt.dstLen), func(t *testing.T) { | |
521 | src := js.Global().Get("Uint8Array").New(tt.srcLen) | |
522 | if tt.srcLen >= 2 { | |
523 | src.SetIndex(1, 42) | |
524 | } | |
525 | dst := make([]byte, tt.dstLen) | |
526 | ||
527 | if got, want := js.CopyBytesToGo(dst, src), tt.copyLen; got != want { | |
528 | t.Errorf("copied %d, want %d", got, want) | |
529 | } | |
530 | if tt.dstLen >= 2 { | |
531 | if got, want := int(dst[1]), 42; got != want { | |
532 | t.Errorf("got %d, want %d", got, want) | |
533 | } | |
534 | } | |
535 | }) | |
536 | } | |
537 | } | |
538 | ||
539 | func TestCopyBytesToJS(t *testing.T) { | |
540 | for _, tt := range copyTests { | |
541 | t.Run(fmt.Sprintf("%d-to-%d", tt.srcLen, tt.dstLen), func(t *testing.T) { | |
542 | src := make([]byte, tt.srcLen) | |
543 | if tt.srcLen >= 2 { | |
544 | src[1] = 42 | |
545 | } | |
546 | dst := js.Global().Get("Uint8Array").New(tt.dstLen) | |
547 | ||
548 | if got, want := js.CopyBytesToJS(dst, src), tt.copyLen; got != want { | |
549 | t.Errorf("copied %d, want %d", got, want) | |
550 | } | |
551 | if tt.dstLen >= 2 { | |
552 | if got, want := dst.Index(1).Int(), 42; got != want { | |
553 | t.Errorf("got %d, want %d", got, want) | |
554 | } | |
555 | } | |
556 | }) | |
557 | } | |
558 | } | |
5a8ea165 ILT |
559 | |
560 | func TestGarbageCollection(t *testing.T) { | |
561 | before := js.JSGo.Get("_values").Length() | |
562 | for i := 0; i < 1000; i++ { | |
563 | _ = js.Global().Get("Object").New().Call("toString").String() | |
564 | runtime.GC() | |
565 | } | |
566 | after := js.JSGo.Get("_values").Length() | |
567 | if after-before > 500 { | |
568 | t.Errorf("garbage collection ineffective") | |
569 | } | |
570 | } | |
571 | ||
572 | // BenchmarkDOM is a simple benchmark which emulates a webapp making DOM operations. | |
573 | // It creates a div, and sets its id. Then searches by that id and sets some data. | |
574 | // Finally it removes that div. | |
575 | func BenchmarkDOM(b *testing.B) { | |
576 | document := js.Global().Get("document") | |
577 | if document.IsUndefined() { | |
578 | b.Skip("Not a browser environment. Skipping.") | |
579 | } | |
580 | const data = "someString" | |
581 | for i := 0; i < b.N; i++ { | |
582 | div := document.Call("createElement", "div") | |
583 | div.Call("setAttribute", "id", "myDiv") | |
584 | document.Get("body").Call("appendChild", div) | |
585 | myDiv := document.Call("getElementById", "myDiv") | |
586 | myDiv.Set("innerHTML", data) | |
587 | ||
588 | if got, want := myDiv.Get("innerHTML").String(), data; got != want { | |
589 | b.Errorf("got %s, want %s", got, want) | |
590 | } | |
591 | document.Get("body").Call("removeChild", div) | |
592 | } | |
593 | } |