mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-08 13:03:39 +00:00
@@ -0,0 +1,34 @@
|
||||
package wasm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/chromedp/chromedp"
|
||||
)
|
||||
|
||||
func TestChan(t *testing.T) {
|
||||
|
||||
t.Parallel()
|
||||
|
||||
err := run("tinygo build -o " + wasmTmpDir + "/chan.wasm -target wasm testdata/chan.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ctx, cancel := chromectx(5 * time.Second)
|
||||
defer cancel()
|
||||
|
||||
err = chromedp.Run(ctx,
|
||||
chromedp.Navigate("http://localhost:8826/run?file=chan.wasm"),
|
||||
waitLog(`1
|
||||
2
|
||||
4
|
||||
3
|
||||
true`),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// +build go1.14
|
||||
|
||||
package wasm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/chromedp/chromedp"
|
||||
)
|
||||
|
||||
func TestEvent(t *testing.T) {
|
||||
|
||||
t.Parallel()
|
||||
|
||||
err := run("tinygo build -o " + wasmTmpDir + "/event.wasm -target wasm testdata/event.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ctx, cancel := chromectx(5 * time.Second)
|
||||
defer cancel()
|
||||
|
||||
var log1, log2 string
|
||||
err = chromedp.Run(ctx,
|
||||
chromedp.Navigate("http://localhost:8826/run?file=event.wasm"),
|
||||
chromedp.WaitVisible("#log"),
|
||||
chromedp.Sleep(time.Second),
|
||||
chromedp.InnerHTML("#log", &log1),
|
||||
waitLog(`1
|
||||
4`),
|
||||
chromedp.Click("#testbtn"),
|
||||
chromedp.Sleep(time.Second),
|
||||
chromedp.InnerHTML("#log", &log2),
|
||||
waitLog(`1
|
||||
4
|
||||
2
|
||||
3
|
||||
true`),
|
||||
)
|
||||
t.Logf("log1: %s", log1)
|
||||
t.Logf("log2: %s", log2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// +build go1.14
|
||||
|
||||
package wasm
|
||||
|
||||
// NOTE: this should work in go1.13 but panics with:
|
||||
// panic: syscall/js: call of Value.Get on string
|
||||
// which is coming from here: https://github.com/golang/go/blob/release-branch.go1.13/src/syscall/js/js.go#L252
|
||||
// But I'm not sure how import "fmt" results in this.
|
||||
// To reproduce, install Go 1.13.x and change the build tag above
|
||||
// to go1.13 and run this test.
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/chromedp/chromedp"
|
||||
)
|
||||
|
||||
func TestFmt(t *testing.T) {
|
||||
|
||||
t.Parallel()
|
||||
|
||||
err := run("tinygo build -o " + wasmTmpDir + "/fmt.wasm -target wasm testdata/fmt.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ctx, cancel := chromectx(5 * time.Second)
|
||||
defer cancel()
|
||||
|
||||
var log1 string
|
||||
err = chromedp.Run(ctx,
|
||||
chromedp.Navigate("http://localhost:8826/run?file=fmt.wasm"),
|
||||
chromedp.Sleep(time.Second),
|
||||
chromedp.InnerHTML("#log", &log1),
|
||||
waitLog(`did not panic`),
|
||||
)
|
||||
t.Logf("log1: %s", log1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// +build go1.14
|
||||
|
||||
package wasm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/chromedp/chromedp"
|
||||
)
|
||||
|
||||
func TestFmtprint(t *testing.T) {
|
||||
|
||||
t.Parallel()
|
||||
|
||||
err := run("tinygo build -o " + wasmTmpDir + "/fmtprint.wasm -target wasm testdata/fmtprint.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ctx, cancel := chromectx(5 * time.Second)
|
||||
defer cancel()
|
||||
|
||||
var log1 string
|
||||
err = chromedp.Run(ctx,
|
||||
chromedp.Navigate("http://localhost:8826/run?file=fmtprint.wasm"),
|
||||
chromedp.Sleep(time.Second),
|
||||
chromedp.InnerHTML("#log", &log1),
|
||||
waitLog(`test from fmtprint 1
|
||||
test from fmtprint 2
|
||||
test from fmtprint 3
|
||||
test from fmtprint 4`),
|
||||
)
|
||||
t.Logf("log1: %s", log1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package wasm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/chromedp/cdproto/cdp"
|
||||
"github.com/chromedp/chromedp"
|
||||
)
|
||||
|
||||
var addr = flag.String("addr", ":8826", "Host:port to listen on for wasm test server")
|
||||
|
||||
var wasmTmpDir string // set in TestMain to a temp directory for build output
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
|
||||
os.Exit(func() int {
|
||||
|
||||
var err error
|
||||
wasmTmpDir, err = ioutil.TempDir("", "wasm_test")
|
||||
if err != nil {
|
||||
log.Fatalf("unable to create temp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(wasmTmpDir) // cleanup even on panic and before os.Exit
|
||||
|
||||
startServer(wasmTmpDir)
|
||||
|
||||
return m.Run()
|
||||
}())
|
||||
|
||||
}
|
||||
|
||||
func run(cmdline string) error {
|
||||
args := strings.Fields(cmdline)
|
||||
return runargs(args...)
|
||||
}
|
||||
|
||||
func runargs(args ...string) error {
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
b, err := cmd.CombinedOutput()
|
||||
log.Printf("Command: %s; err=%v; full output:\n%s", strings.Join(args, " "), err, b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func chromectx(timeout time.Duration) (context.Context, context.CancelFunc) {
|
||||
|
||||
var ctx context.Context
|
||||
|
||||
// looks for locally installed Chrome
|
||||
ctx, _ = chromedp.NewContext(context.Background())
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||
|
||||
return ctx, cancel
|
||||
}
|
||||
|
||||
func startServer(tmpDir string) {
|
||||
|
||||
fsh := http.FileServer(http.Dir(tmpDir))
|
||||
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if r.URL.Path == "/wasm_exec.js" {
|
||||
http.ServeFile(w, r, "../../targets/wasm_exec.js")
|
||||
return
|
||||
}
|
||||
|
||||
if r.URL.Path == "/run" {
|
||||
fmt.Fprintf(w, `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test</title>
|
||||
<meta charset="utf-8"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="main"></div>
|
||||
<pre id="log"></pre>
|
||||
<script>
|
||||
window.wasmLogOutput = [];
|
||||
(function() {
|
||||
var logdiv = document.getElementById('log');
|
||||
var cl = console.log;
|
||||
console.log = function() {
|
||||
var a = [];
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
a.push(arguments[i]);
|
||||
}
|
||||
var line = a.join(' ') + "\n";
|
||||
window.wasmLogOutput.push(line);
|
||||
var ret = cl.apply(console, arguments)
|
||||
var el = document.createElement('span');
|
||||
el.innerText = line;
|
||||
logdiv.appendChild(el);
|
||||
return ret
|
||||
}
|
||||
})()
|
||||
</script>
|
||||
<script src="/wasm_exec.js"></script>
|
||||
<script>
|
||||
var wasmSupported = (typeof WebAssembly === "object");
|
||||
if (wasmSupported) {
|
||||
var mainWasmReq = fetch("/%s").then(function(res) {
|
||||
if (res.ok) {
|
||||
const go = new Go();
|
||||
WebAssembly.instantiateStreaming(res, go.importObject).then((result) => {
|
||||
go.run(result.instance);
|
||||
});
|
||||
} else {
|
||||
res.text().then(function(txt) {
|
||||
var el = document.getElementById("main");
|
||||
el.style = 'font-family: monospace; background: black; color: red; padding: 10px';
|
||||
el.innerText = txt;
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
document.getElementById("main").innerHTML = 'This application requires WebAssembly support. Please upgrade your browser.';
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>`, r.FormValue("file"))
|
||||
return
|
||||
}
|
||||
|
||||
fsh.ServeHTTP(w, r)
|
||||
})
|
||||
|
||||
log.Printf("Starting server at %q for dir: %s", *addr, tmpDir)
|
||||
go func() {
|
||||
log.Fatal(http.ListenAndServe(*addr, h))
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
func waitLog(logText string) chromedp.QueryAction {
|
||||
return waitInnerTextTrimEq("#log", logText)
|
||||
}
|
||||
|
||||
// waitInnerTextTrimEq will wait for the innerText of the specified element to match a specific string after whitespace trimming.
|
||||
func waitInnerTextTrimEq(sel, innerText string) chromedp.QueryAction {
|
||||
|
||||
return chromedp.Query(sel, func(s *chromedp.Selector) {
|
||||
|
||||
chromedp.WaitFunc(func(ctx context.Context, cur *cdp.Frame, ids ...cdp.NodeID) ([]*cdp.Node, error) {
|
||||
|
||||
nodes := make([]*cdp.Node, len(ids))
|
||||
cur.RLock()
|
||||
for i, id := range ids {
|
||||
nodes[i] = cur.Nodes[id]
|
||||
if nodes[i] == nil {
|
||||
cur.RUnlock()
|
||||
// not yet ready
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
cur.RUnlock()
|
||||
|
||||
var ret string
|
||||
err := chromedp.EvaluateAsDevTools("document.querySelector('"+sel+"').innerText", &ret).Do(ctx)
|
||||
if err != nil {
|
||||
return nodes, err
|
||||
}
|
||||
if strings.TrimSpace(ret) != innerText {
|
||||
// log.Printf("found text: %s", ret)
|
||||
return nodes, errors.New("unexpected value: " + ret)
|
||||
}
|
||||
|
||||
// log.Printf("NodeValue: %#v", nodes[0])
|
||||
|
||||
// return nil, errors.New("not ready yet")
|
||||
return nodes, nil
|
||||
})(s)
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
|
||||
ch := make(chan bool, 1)
|
||||
println("1")
|
||||
go func() {
|
||||
println("2")
|
||||
ch <- true
|
||||
println("3")
|
||||
}()
|
||||
println("4")
|
||||
v := <-ch
|
||||
println(v)
|
||||
|
||||
}
|
||||
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import "syscall/js"
|
||||
|
||||
func main() {
|
||||
|
||||
ch := make(chan bool, 1)
|
||||
|
||||
println("1")
|
||||
|
||||
js.Global().
|
||||
Get("document").
|
||||
Call("querySelector", "#main").
|
||||
Set("innerHTML", `<button id="testbtn">Test</button>`)
|
||||
|
||||
js.Global().
|
||||
Get("document").
|
||||
Call("querySelector", "#testbtn").
|
||||
Call("addEventListener", "click",
|
||||
js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
println("2")
|
||||
ch <- true
|
||||
println("3")
|
||||
return nil
|
||||
}))
|
||||
|
||||
println("4")
|
||||
v := <-ch
|
||||
println(v)
|
||||
|
||||
}
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
var _ fmt.Stringer
|
||||
println("did not panic")
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("test from fmtprint 1")
|
||||
fmt.Print("test from fmtprint 2\n")
|
||||
fmt.Print("test from fmtp")
|
||||
fmt.Print("rint 3\n")
|
||||
fmt.Printf("test from fmtprint %d\n", 4)
|
||||
}
|
||||
Reference in New Issue
Block a user