Initial release.
This commit is contained in:
commit
8c599e8e5c
13 changed files with 3651 additions and 0 deletions
77
test/go/doubleselect.js
Normal file
77
test/go/doubleselect.js
Normal 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()
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue