Initial release.

This commit is contained in:
David Braun 2017-10-06 21:01:34 -04:00
commit 8c599e8e5c
No known key found for this signature in database
GPG key ID: 5694EEC4D129BDCF
13 changed files with 3651 additions and 0 deletions

1
test/go/README.md Normal file
View file

@ -0,0 +1 @@
The tests in this directory are translated from [Go's tests](https://github.com/golang/go/tree/bad5abf64d76f9c302c084c5f62e6f70920d3c81/test/chan).

77
test/go/doubleselect.js Normal file
View file

@ -0,0 +1,77 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test the situation in which two cases of a select can
// both end up running. See http://codereview.appspot.com/180068.
'use strict'
const Channel = require('../../lib')
it(`doubleselect`, async function () {
this.timeout(10 * 1000)
const iterations = 100000 // number of iterations
// sender sends a counter to one of four different channels. If two cases both
// end up running in the same iteration, the same value will be sent to two
// different channels.
const sender = async (n, c1, c2, c3, c4) => {
for (let i = 0; i < n; i++) {
await Channel.select(c1.push(i), c2.push(i), c3.push(i), c4.push(i))
}
c1.close()
c2.close()
c3.close()
c4.close()
}
// mux receives the values from sender and forwards them onto another channel.
// It would be simpler to just have sender's four cases all be the same
// channel, but this doesn't actually trigger the bug.
const mux = async (output, input, done) => {
await input.forEach(async (value) => {
await output.push(value)
})
await done.push(true)
}
// recver gets a steam of values from the four mux's and checks for
// duplicates.
const recver = (input) => {
const seen = new Map()
input.forEach((v) => {
if (seen.has(v)) {
throw new Error(`got duplicate value: ${v}`)
}
seen.set(v, true)
})
}
const c1 = Channel()
const c2 = Channel()
const c3 = Channel()
const c4 = Channel()
const done = Channel()
const cmux = Channel()
sender(iterations, c1, c2, c3, c4)
mux(cmux, c1, done)
mux(cmux, c2, done)
mux(cmux, c3, done)
mux(cmux, c4, done)
// We keep the recver because it might catch more bugs in the future.
// However, the result of the bug linked to at the top is that we'll
// end up panicking with: "throw: bad g->status in ready".
recver(cmux)
await done.shift()
await done.shift()
await done.shift()
await done.shift()
cmux.close()
})

61
test/go/fifo.js Normal file
View file

@ -0,0 +1,61 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test that unbuffered channels act as pure fifos.
'use strict'
const Channel = require('../../lib')
it(`fifo`, function () {
const N = 10
const AsynchFifo = async () => {
const ch = Channel(10)
for (let i = 0; i < N; i++) {
await ch.push(i)
}
for (let i = 0; i < N; i++) {
if (await ch.shift() !== i) {
throw new Error(`bad receive`)
}
}
}
const Chain = async (ch, val, input, output) => {
await input.shift()
if (await ch.shift() !== val) {
throw new Error(val)
}
await output.push(1)
}
// thread together a daisy chain to read the elements in sequence
const SynchFifo = async () => {
const ch = Channel()
let input = Channel()
let start = input
for (let i = 0; i < N; i++) {
const output = Channel()
Chain(ch, i, input, output)
input = output
}
await start.push(0)
for (let i = 0; i < N; i++) {
await ch.push(i)
}
await input.shift()
}
AsynchFifo()
SynchFifo()
})

33
test/go/goroutines.js Normal file
View file

@ -0,0 +1,33 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Torture test for goroutines.
// Make a lot of goroutines, threaded together, and tear them down cleanly.
'use strict'
const Channel = require('../../lib')
it(`goroutines`, async function () {
const f = async (left, right) => {
await left.push(await right.shift())
}
const n = 10000
const leftmost = Channel()
let right = leftmost
let left = leftmost
for (let i = 0; i < n; i++) {
right = Channel()
f(left, right)
left = right
}
;(async (c) => {
await c.push(1)
})(right)
await leftmost.shift()
})

73
test/go/select.js Normal file
View file

@ -0,0 +1,73 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test simple select.
'use strict'
const Channel = require('../../lib')
it(`select`, async function () {
const closed = Channel()
closed.close()
let counter = 0
let shift = 0
const GetValue = () => {
counter++
return 1 << shift
}
const Send = async (a, b) => {
let done = false
let i = 0
do {
switch (await Channel.select(a.push(GetValue()), b.push(GetValue()),
closed.shift())) {
case a:
i++
a = Channel()
break
case b:
i++
b = Channel()
break
default:
done = true
}
shift++
} while (!done)
return i
}
let a = Channel(1)
let b = Channel(1)
let v = await Send(a, b)
if (v !== 2) {
throw new Error(`Send returned ${v} !== 2`)
}
const av = await a.shift()
const bv = await b.shift()
if ((av | bv) !== 3) {
throw new Error(`bad values ${av} ${bv}`)
}
v = await Send(a, Channel())
if (v !== 1) {
throw new Error(`Send returned ${v} !== 1`)
}
if (counter !== 10) {
throw new Error(`counter is ${counter} !== 10`)
}
})