gpu.js/test/internal/function-tracer.js
Robert Plummer 83cedd89a7 fix: Unit tests for #500, #501, #502, #503, #504
fix: typescript to include video and KernelValues
fix: Duplicate image in unit test
fix: Bump and build
2019-09-24 10:22:16 -04:00

525 lines
14 KiB
JavaScript

const { assert, test, skip, module: describe, only } = require('qunit');
const { FunctionTracer } = require('../../src');
describe('internal: FunctionTracer');
test('works with Program', () => {
const mockBody = {};
let called = false;
let calledBody = null;
const mockInstance = {
scan: (body) => {
called = true;
calledBody = body;
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'Program', body: mockBody });
assert.ok(called);
assert.equal(calledBody, mockBody);
});
test('works with BlockStatement', () => {
const mockBody = {};
let called = false;
let calledBody = null;
const mockInstance = {
contexts: [],
runningContexts: [],
newContext: FunctionTracer.prototype.newContext,
scan: (body) => {
called = true;
calledBody = body;
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'BlockStatement', body: mockBody });
assert.ok(called);
assert.equal(calledBody, mockBody);
assert.equal(mockInstance.contexts.length, 1);
});
test('works with AssignmentExpression', () => {
const mockLeft = {};
const mockRight = {};
let called = false;
let calledSides = [];
const mockInstance = {
scan: (side) => {
called = true;
calledSides.push(side);
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'AssignmentExpression', left: mockLeft, right: mockRight });
assert.ok(called);
assert.deepEqual(calledSides, [mockLeft, mockRight]);
});
test('works with LogicalExpression', () => {
const mockLeft = {};
const mockRight = {};
let called = false;
let calledSides = [];
const mockInstance = {
scan: (side) => {
called = true;
calledSides.push(side);
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'LogicalExpression', left: mockLeft, right: mockRight });
assert.ok(called);
assert.deepEqual(calledSides, [mockLeft, mockRight]);
});
test('works with BinaryExpression', () => {
const mockLeft = {};
const mockRight = {};
let called = false;
let calledSides = [];
const mockInstance = {
scan: (side) => {
called = true;
calledSides.push(side);
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'BinaryExpression', left: mockLeft, right: mockRight });
assert.ok(called);
assert.deepEqual(calledSides, [mockLeft, mockRight]);
});
test('works with UpdateExpression', () => {
const mockArgument = {};
let called = false;
let calledBody = null;
const mockInstance = {
scan: (argument) => {
called = true;
calledBody = argument;
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'UpdateExpression', argument: mockArgument });
assert.ok(called);
assert.equal(calledBody, mockArgument);
});
test('works with UnaryExpression', () => {
const mockArgument = {};
let called = false;
let calledArgument = null;
const mockInstance = {
scan: (argument) => {
called = true;
calledArgument = argument;
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'UpdateExpression', argument: mockArgument });
assert.ok(called);
assert.equal(calledArgument, mockArgument);
});
test('works with VariableDeclaration', () => {
const mockDeclarations = {};
let called = false;
let calledDeclarations = null;
const mockInstance = {
scan: (declarations) => {
called = true;
calledDeclarations = declarations;
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'VariableDeclaration', declarations: mockDeclarations });
assert.ok(called);
assert.equal(calledDeclarations, mockDeclarations);
});
test('works with VariableDeclarator', () => {
const mockDeclarations = {};
const mockCurrentContext = {};
let called = false;
let calledDeclarators = [];
const mockInstance = {
inLoopInit: false,
declarations: [],
currentContext: mockCurrentContext,
scan: (declarator) => {
called = true;
calledDeclarators.push(declarator);
}
};
const mockId = {
name: 'bob'
};
const mockInit = {};
const mockAst = {
type: 'VariableDeclarator',
declarations: mockDeclarations,
id: mockId,
init: mockInit
};
FunctionTracer.prototype.scan.call(mockInstance, mockAst);
assert.ok(called);
assert.deepEqual(calledDeclarators, [mockId, mockInit]);
const expecting = {
ast: mockAst,
context: mockCurrentContext,
name: 'bob',
origin: 'declaration',
forceInteger: false,
assignable: true,
};
assert.deepEqual(mockCurrentContext.bob, expecting);
assert.deepEqual(mockInstance.declarations[0], expecting);
});
test('works with FunctionExpression when runningContexts.length = 0', () => {
const mockBody = {};
let called = false;
let calledBody = null;
const mockInstance = {
runningContexts: [],
functions: [],
scan: (body) => {
called = true;
calledBody = body;
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'FunctionExpression', body: mockBody });
assert.ok(called);
assert.equal(calledBody, mockBody);
assert.equal(mockInstance.functions.length, 0);
});
test('works with FunctionDeclaration when runningContexts.length = 0', () => {
const mockBody = {};
let called = false;
let calledBody = null;
const mockInstance = {
runningContexts: [],
functions: [],
scan: (body) => {
called = true;
calledBody = body;
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'FunctionDeclaration', body: mockBody });
assert.ok(called);
assert.equal(calledBody, mockBody);
assert.equal(mockInstance.functions.length, 0);
});
test('works with FunctionExpression when runningContexts.length > 0', () => {
const mockBody = {};
const mockInstance = {
functions: [],
runningContexts: [null],
scan: () => {
throw new Error('should not be called');
}
};
const mockAst = { type: 'FunctionExpression', body: mockBody };
FunctionTracer.prototype.scan.call(mockInstance, mockAst);
assert.equal(mockInstance.functions.length, 1);
assert.equal(mockInstance.functions[0], mockAst);
});
test('works with FunctionDeclaration when runningContexts.length > 0', () => {
const mockBody = {};
const mockInstance = {
functions: [],
runningContexts: [null],
scan: () => {
throw new Error('should not be called');
}
};
const mockAst = { type: 'FunctionDeclaration', body: mockBody };
FunctionTracer.prototype.scan.call(mockInstance, mockAst);
assert.equal(mockInstance.functions.length, 1);
assert.equal(mockInstance.functions[0], mockAst);
});
test('works with IfStatement', () => {
const mockTest = {};
const mockConsequent = {};
const mockAlternate = {};
let called = false;
let calledArgs = [];
const mockInstance = {
scan: (arg) => {
called = true;
calledArgs.push(arg);
}
};
FunctionTracer.prototype.scan.call(mockInstance, {
type: 'IfStatement',
test: mockTest,
consequent: mockConsequent,
alternate: mockAlternate,
});
assert.ok(called);
assert.deepEqual(calledArgs, [mockTest, mockConsequent, mockAlternate]);
});
test('works with ForStatement', () => {
const mockInit = {};
const mockTest = {};
const mockUpdate = {};
const mockBody = {};
let called = false;
let calledArgs = [];
const mockInstance = {
contexts: [],
runningContexts: [],
newContext: FunctionTracer.prototype.newContext,
scan: (arg) => {
called = true;
calledArgs.push(arg);
}
};
FunctionTracer.prototype.scan.call(mockInstance, {
type: 'ForStatement',
init: mockInit,
test: mockTest,
update: mockUpdate,
body: mockBody,
});
assert.ok(called);
assert.deepEqual(calledArgs, [mockInit, mockTest, mockUpdate, mockBody]);
assert.equal(mockInstance.contexts.length, 2);
});
test('works with DoWhileStatement', () => {
const mockBody = {};
const mockTest = {};
let called = false;
let calledArgs = [];
const mockInstance = {
contexts: [],
runningContexts: [],
newContext: FunctionTracer.prototype.newContext,
scan: (arg) => {
called = true;
calledArgs.push(arg);
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'DoWhileStatement', body: mockBody, test: mockTest });
assert.ok(called);
assert.deepEqual(calledArgs, [mockBody, mockTest]);
});
test('works with WhileStatement', () => {
const mockBody = {};
const mockTest = {};
let called = false;
let calledArgs = [];
const mockInstance = {
contexts: [],
runningContexts: [],
newContext: FunctionTracer.prototype.newContext,
scan: (arg) => {
called = true;
calledArgs.push(arg);
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'WhileStatement', body: mockBody, test: mockTest });
assert.ok(called);
assert.deepEqual(calledArgs, [mockBody, mockTest]);
});
test('works with Identifier', () => {
const mockCurrentContext = {};
const mockInstance = {
identifiers: [],
currentContext: mockCurrentContext,
};
const mockAst = { type: 'Identifier' };
FunctionTracer.prototype.scan.call(mockInstance, mockAst);
assert.deepEqual(mockInstance.identifiers, [
{
context: mockInstance.currentContext,
ast: mockAst
}
]);
});
test('works with ReturnStatement', () => {
const mockArgument = {};
let called = false;
let calledArgument = null;
const mockInstance = {
returnStatements: [],
scan: (argument) => {
called = true;
calledArgument = argument;
}
};
const mockAst = { type: 'ReturnStatement', argument: mockArgument };
FunctionTracer.prototype.scan.call(mockInstance, mockAst);
assert.ok(called);
assert.equal(calledArgument, mockArgument);
assert.equal(mockInstance.returnStatements[0], mockAst);
});
test('works with MemberExpression', () => {
const mockBody = {};
const mockProperty = {};
let called = false;
let calledArgs = [];
const mockInstance = {
scan: (arg) => {
called = true;
calledArgs.push(arg);
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'MemberExpression', object: mockBody, property: mockProperty });
assert.ok(called);
assert.deepEqual(calledArgs, [mockBody, mockProperty]);
});
test('works with ExpressionStatement', () => {
const mockExpression = {};
let called = false;
let calledExpression = null;
const mockInstance = {
scan: (body) => {
called = true;
calledExpression = body;
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'ExpressionStatement', expression: mockExpression });
assert.ok(called);
assert.equal(calledExpression, mockExpression);
});
test('works with CallExpression', () => {
const mockArguments = {};
let called = false;
let calledArguments = null;
const mockCurrentContext = {};
const mockInstance = {
currentContext: mockCurrentContext,
functionCalls: [],
scan: (_arguments) => {
called = true;
calledArguments = _arguments;
}
};
const mockAst = { type: 'CallExpression', arguments: mockArguments };
FunctionTracer.prototype.scan.call(mockInstance, mockAst);
assert.ok(called);
assert.equal(calledArguments, mockArguments);
assert.deepEqual(mockInstance.functionCalls, [
{
context: mockCurrentContext,
ast: mockAst
}
]);
});
test('works with ArrayExpression', () => {
const mockElements = {};
let called = false;
let calledElements = null;
const mockInstance = {
scan: (elements) => {
called = true;
calledElements = elements;
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'ArrayExpression', elements: mockElements });
assert.ok(called);
assert.equal(calledElements, mockElements);
});
test('works with ConditionalExpression', () => {
const mockTest = {};
const mockAlternate = {};
const mockConsequent = {};
let called = false;
let calledArgs = [];
const mockInstance = {
scan: (arg) => {
called = true;
calledArgs.push(arg);
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'ConditionalExpression', test: mockTest, alternate: mockAlternate, consequent: mockConsequent });
assert.ok(called);
assert.deepEqual(calledArgs, [mockTest, mockConsequent, mockConsequent]);
});
test('works with SwitchStatement', () => {
const mockDiscriminant = {};
const mockCases = {};
let called = false;
let calledArgs = [];
const mockInstance = {
scan: (arg) => {
called = true;
calledArgs.push(arg);
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'SwitchStatement', discriminant: mockDiscriminant, cases: mockCases });
assert.ok(called);
assert.deepEqual(calledArgs, [mockDiscriminant, mockCases]);
});
test('works with SwitchCase', () => {
const mockTest = {};
const mockConsequent = {};
let called = false;
let calledArgs = [];
const mockInstance = {
scan: (arg) => {
called = true;
calledArgs.push(arg);
}
};
FunctionTracer.prototype.scan.call(mockInstance, { type: 'SwitchCase', test: mockTest, consequent: mockConsequent });
assert.ok(called);
assert.deepEqual(calledArgs, [mockTest, mockConsequent]);
});
test('does nothing with un-scan-ables', () => {
let called = false;
const mockInstance = {
scan: () => {
called = true;
}
};
[
'ThisExpression',
'Literal',
'DebuggerStatement',
'EmptyStatement',
'BreakStatement',
'ContinueStatement'
].forEach(type => {
FunctionTracer.prototype.scan.call(mockInstance, { type });
});
assert.ok(!called);
});
test('when called with fake type, throws', () => {
assert.throws(() => {
FunctionTracer.prototype.scan.call({}, { type: 'Made Up' });
});
});
test('can handle direct arrays', () => {
const mockBlockBody = {};
const mockProgramBody = {};
const asts = [
{ type: 'BlockStatement' },
{ type: 'Program' },
];
const calledAsts = [];
const mockInstance = {
scan: (ast) => {
calledAsts.push(ast);
}
};
FunctionTracer.prototype.scan.call(mockInstance, asts);
assert.deepEqual(calledAsts, asts);
});