Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SharedArrayBuffer and Atomics tests #839

Merged
merged 20 commits into from
Feb 7, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b07a01e
Add SharedArrayBuffer and Atomics tests
Jan 13, 2017
d1fccaa
Add Atomics[@@toStringTag] test
syg Jan 20, 2017
40bb0d2
Fix new SAB tests' copyright lines to say Mozilla
syg Jan 23, 2017
6e2b2e5
Refactor Atomics tests
syg Jan 24, 2017
9d97d3c
Fix style in SharedArrayBuffer.prototype.slice tests
syg Jan 24, 2017
49ab6c5
Remove features: [Symbol] from SharedArrayBuffer tests
syg Jan 24, 2017
291563d
Split out SharedArrayBuffer versions of TypedArrays/buffer-arg-* tests
syg Jan 24, 2017
388466d
Revert buffer-arg tests to only test ArrayBuffer
syg Jan 24, 2017
ab2ca76
Split out SharedArrayBuffer DataView tests
syg Jan 24, 2017
1297867
Revert DataView tests to only test ArrayBuffer
syg Jan 24, 2017
89a0f73
Remove agent_spidermonkey.js for merging
syg Jan 24, 2017
c55033e
Revert "Fix new SAB tests' copyright lines to say Mozilla"
syg Jan 24, 2017
32ba9c0
Append Mozilla copyright instead of replacing original copyright in m…
syg Jan 24, 2017
b970a8d
Copy more analogous ArrayBuffer tests to SharedArrayBuffer
syg Jan 24, 2017
03e19ad
Adding missing testTypedArray.js include in Atomics tests
syg Jan 24, 2017
2d74325
Refactor 100 to $ATOMICS_MAX_TIME_EPSILON in atomicsHelper.js
syg Jan 24, 2017
28abb1d
Combine two features: lines
syg Jan 24, 2017
adae9e8
Add tests for [Shared]ArrayBuffer.prototype.{byteLength,slice} being …
syg Jan 24, 2017
70e2166
Add test for new %TypedArray%(new %TypedArray%(SAB))
syg Jan 25, 2017
f076541
Add versions of %TypedArray%.prototype.set on SharedArrayBuffer-backe…
syg Jan 25, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions INTERPRETING.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,33 @@ properties of the global scope prior to test execution.

- **`global`** - a reference to the global object on which `$` was initially
defined
- **`agent`** - an ordinary object with the following properties:
- **`start`** - a function that takes a script source string and runs
the script in a concurrent agent. Will block until that agent is
running. The agent has no representation. The agent script will be
run in an environment that has an object `$` with a property `agent`
with the following properties:
- **`receiveBroadcast`** - a function that takes a function and
calls the function when it has received a broadcast from the parent,
passing it the broadcast as two arguments, a SharedArrayBuffer and
an Int32. This function may return before a broadcast is received
(eg to return to an event loop to await a message) and no code should
follow the call to this function.
- **`report`** - a function that takes a string and places it in a
transmit queue whence the parent will retrieve it. Messages
should be short.
- **`sleep`** - a function that takes a millisecond argument and
sleeps the agent for approximately that duration.
- **`leaving`** - a function that signals that the agent is done and
may be terminated (if possible).
- **`broadcast`** - a function that takes a SharedArrayBuffer and an Int32
and broadcasts the two values to all concurrent agents. The function
blocks until all agents have retrieved the message. Note, this assumes
that all agents that were started are still running.
- **`getReport`** - a function that reads an incoming string from any agent,
and returns it if it exists, or returns `null` otherwise.
- **`sleep`** - a function that takes a millisecond argument and
sleeps the execution for approximately that duration.

### Strict Mode

Expand Down
123 changes: 123 additions & 0 deletions harness/agent_spidermonkey.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright (C) 2015 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
//
// An implementation of '$.agent' for the SpiderMonkey shell.
// See ../INTERPRETING.md for the API definition.

if (typeof $ == 'undefined')
$ = {};

$.agent = (function () {

// The SpiderMonkey implementation uses a designated shared buffer _ia
// for coordination, and spinlocks for everything except sleeping.

var _MSG_LOC = 0; // Low bit set: broadcast available; High bits: seq #
var _ID_LOC = 1; // ID sent with broadcast
var _ACK_LOC = 2; // Worker increments this to ack that broadcast was received
var _RDY_LOC = 3; // Worker increments this to ack that worker is up and running
var _LOCKTXT_LOC = 4; // Writer lock for the text buffer: 0=open, 1=closed
var _NUMTXT_LOC = 5; // Count of messages in text buffer
var _NEXT_LOC = 6; // First free location in the buffer
var _SLEEP_LOC = 7; // Used for sleeping

var _FIRST = 10; // First location of first message

var _ia = new Int32Array(new SharedArrayBuffer(65536));
_ia[_NEXT_LOC] = _FIRST;

var _worker_prefix = `
if (typeof $ == 'undefined')
$ = {};

$.agent = (function () {

var _ia;

var agent = {
_ia: null,

receiveBroadcast: function(receiver) {
var k;
while (((k = Atomics.load(_ia, ${_MSG_LOC})) & 1) == 0)
;
var received_sab = getSharedArrayBuffer();
var received_id = Atomics.load(_ia, ${_ID_LOC});
Atomics.add(_ia, ${_ACK_LOC}, 1);
while (Atomics.load(_ia, ${_MSG_LOC}) == k)
;
receiver(received_sab, received_id);
},

report: function(msg) {
while (Atomics.compareExchange(_ia, ${_LOCKTXT_LOC}, 0, 1) == 1)
;
msg = "" + msg;
var i = _ia[${_NEXT_LOC}];
_ia[i++] = msg.length;
for ( let j=0 ; j < msg.length ; j++ )
_ia[i++] = msg.charCodeAt(j);
_ia[${_NEXT_LOC}] = i;
Atomics.add(_ia, ${_NUMTXT_LOC}, 1);
Atomics.store(_ia, ${_LOCKTXT_LOC}, 0);
},

sleep: function(s) {
Atomics.wait(_ia, ${_SLEEP_LOC}, 0, s);
},

leaving: function() {}
};

_ia = new Int32Array(getSharedArrayBuffer());
Atomics.add(_ia, ${_RDY_LOC}, 1);

return agent;
})();
`;

var agent =
{
_numWorkers: 0,
_numReports: 0,
_reportPtr: _FIRST,

start: function (script) {
setSharedArrayBuffer(_ia.buffer);
var oldrdy = Atomics.load(_ia, _RDY_LOC);
evalInWorker(_worker_prefix + script);
while (Atomics.load(_ia, _RDY_LOC) == oldrdy)
;
this._numWorkers++;
},

broadcast: function (sab, id) {
setSharedArrayBuffer(sab);
Atomics.store(_ia, _ID_LOC, id);
Atomics.store(_ia, _ACK_LOC, 0);
Atomics.add(_ia, _MSG_LOC, 1);
while (Atomics.load(_ia, _ACK_LOC) < this._numWorkers)
;
Atomics.add(_ia, _MSG_LOC, 1);
},

getReport: function () {
if (this._numReports == Atomics.load(_ia, _NUMTXT_LOC))
return null;
var s = "";
var i = this._reportPtr;
var len = _ia[i++];
for ( let j=0 ; j < len ; j++ )
s += String.fromCharCode(_ia[i++]);
this._reportPtr = i;
this._numReports++;
return s;
},

sleep: function(s) {
Atomics.wait(_ia, _SLEEP_LOC, 0, s);
},
}

return agent;
})();
20 changes: 20 additions & 0 deletions test/built-ins/Atomics/Symbol.toStringTag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (C) 2017 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
`Symbol.toStringTag` property descriptor on Atomics
info: >
The initial value of the @@toStringTag property is the String value
"Atomics".

This property has the attributes { [[Writable]]: false, [[Enumerable]]:
false, [[Configurable]]: true }.
includes: [propertyHelper.js]
features: [Symbol.toStringTag]
---*/

assert.sameValue(Atomics[Symbol.toStringTag], 'Atomics');

verifyNotEnumerable(Atomics, Symbol.toStringTag);
verifyNotWritable(Atomics, Symbol.toStringTag);
verifyConfigurable(Atomics, Symbol.toStringTag);
33 changes: 33 additions & 0 deletions test/built-ins/Atomics/add/bad-range.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (C) 2015 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: >
Test range checking of Atomics.add on arrays that allow atomic operations
---*/

var sab = new SharedArrayBuffer(4);

var views = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array];

var bad_indices = [ (view) => -1,
(view) => view.length,
(view) => view.length*2,
(view) => undefined,
(view) => Number.NaN,
(view) => Number.POSITIVE_INFINITY,
(view) => Number.NEGATIVE_INFINITY,
(view) => '3.5',
(view) => 3.5,
(view) => { password: "qumquat" },
(view) => ({ valueOf: () => 125 }),
(view) => ({ toString: () => '125', valueOf: false }) // non-callable valueOf triggers invocation of toString
];

for ( let View of views ) {
let view = new View(sab);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's already a harness helper that can be used to loop on different TypedArray constructors, even on specific constructors...

testWithTypedArrayConstructors(fn(View) { let view = new View(sab); ... }, views) can be used as it also tells where the error is if an assertion fail.

for ( let IdxGen of bad_indices ) {
var Idx = IdxGen(view);
assert.throws(RangeError, () => Atomics.add(view, Idx, 10));
}
}
11 changes: 11 additions & 0 deletions test/built-ins/Atomics/add/descriptor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2015 Microsoft Corporation. All rights reserved.
// This code is governed by the license found in the LICENSE file.

/*---
description: Testing descriptor property of Atomics.add
includes: [propertyHelper.js]
---*/

verifyWritable(Atomics, "add");
verifyNotEnumerable(Atomics, "add");
verifyConfigurable(Atomics, "add");
59 changes: 59 additions & 0 deletions test/built-ins/Atomics/add/good-views.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (C) 2016 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: Test Atomics.add on arrays that allow atomic operations.
---*/

var sab = new SharedArrayBuffer(1024);
var ab = new ArrayBuffer(16);

var int_views = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array];

var good_indices = [ (view) => 0/-1, // -0
(view) => '-0',
(view) => view.length - 1,
(view) => ({ valueOf: () => 0 }),
(view) => ({ toString: () => '0', valueOf: false }) // non-callable valueOf triggers invocation of toString
];

for ( let View of int_views ) {
// Make it interesting - use non-zero byteOffsets and non-zero indexes.

var view = new View(sab, 32, 20);
var control = new View(ab, 0, 2);

// Add positive number
view[8] = 0;
assert.sameValue(Atomics.add(view, 8, 10), 0);
assert.sameValue(view[8], 10);

// Add negative number
assert.sameValue(Atomics.add(view, 8, -5), 10);
assert.sameValue(view[8], 5);

// Result is "negative" though subject to coercion
view[3] = -5;
control[0] = -5;
assert.sameValue(Atomics.add(view, 3, 0), control[0]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those comments would serve great as assertion messages. Once again, it helps identifying the point of failure.

assert.sameValue(Atomics.add(view, 3, 0), control[0], 'Result is "negative" though subject to coercion');


// Result is subject to chopping
control[0] = 12345;
view[3] = 12345;
assert.sameValue(Atomics.add(view, 3, 0), control[0]);

// And again
control[0] = 123456789;
view[3] = 123456789;
assert.sameValue(Atomics.add(view, 3, 0), control[0]);

// In-bounds boundary cases for indexing
for ( let IdxGen of good_indices ) {
let Idx = IdxGen(view);
view.fill(0);
// Atomics.store() computes an index from Idx in the same way as other
// Atomics operations, not quite like view[Idx].
Atomics.store(view, Idx, 37);
assert.sameValue(Atomics.add(view, Idx, 0), 37);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

once again an assertion message here indicating the used index

}
}
28 changes: 28 additions & 0 deletions test/built-ins/Atomics/add/length.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (C) 2015 André Bargull. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test format is based from a work of André Bargull, but the test for this specific case (length prop of Atomics.add is made by you, so Mozilla Corporation applies well here, AFAIK.

// This code is governed by the BSD license found in the LICENSE file.

/*---
description: >
Atomics.add.length is 3.
info: >
Atomics.add ( ia, index, val )

17 ECMAScript Standard Built-in Objects:
Every built-in Function object, including constructors, has a length
property whose value is an integer. Unless otherwise specified, this
value is equal to the largest number of named arguments shown in the
subclause headings for the function description, including optional
parameters. However, rest parameters shown using the form “...name”
are not included in the default argument count.

Unless otherwise specified, the length property of a built-in Function
object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
[[Configurable]]: true }.
includes: [propertyHelper.js]
---*/

assert.sameValue(Atomics.add.length, 3);

verifyNotEnumerable(Atomics.add, "length");
verifyNotWritable(Atomics.add, "length");
verifyConfigurable(Atomics.add, "length");
14 changes: 14 additions & 0 deletions test/built-ins/Atomics/add/name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (C) 2015 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: >
Atomics.add.name is "add".
includes: [propertyHelper.js]
---*/

assert.sameValue(Atomics.add.name, "add");

verifyNotEnumerable(Atomics.add, "name");
verifyNotWritable(Atomics.add, "name");
verifyConfigurable(Atomics.add, "name");
42 changes: 42 additions & 0 deletions test/built-ins/Atomics/add/non-views.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (C) 2015 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: >
Test Atomics.add on view values other than TypedArrays
---*/

var values = [null,
undefined,
true,
false,
new Boolean(true),
10,
3.14,
new Number(4),
"Hi there",
new Date,
/a*utomaton/g,
{ password: "qumquat" },
new DataView(new ArrayBuffer(10)),
new ArrayBuffer(128),
new SharedArrayBuffer(128),
new Error("Ouch"),
[1,1,2,3,5,8],
((x) => -x),
new Map(),
new Set(),
new WeakMap(),
new WeakSet(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while it does not hurt adding more and more, I don't believe it's really necessary to have extra objects as instances of Map, Set, Date, Error, etc...

A case with all the primitive values, an array, an ordinary object, should be enough.

this.Promise ? new Promise(() => "done") : undefined,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be removed as well

Symbol("halleluja"),
// TODO: Proxy?
Object,
Int32Array,
Date,
Math,
Atomics ];

for ( var view of values ) {
assert.throws(TypeError, (() => Atomics.add(view, 0, 0)));
}
17 changes: 17 additions & 0 deletions test/built-ins/Atomics/add/nonshared-int-views.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (C) 2015 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: >
Test Atomics.add on non-shared integer TypedArrays
---*/

var ab = new ArrayBuffer(16);

var int_views = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array];

for ( var View of int_views ) {
var view = new View(ab);

assert.throws(TypeError, (() => Atomics.add(view, 0, 0)));
}
Loading