Skip to content
This repository has been archived by the owner on Jun 10, 2022. It is now read-only.

Commit

Permalink
display on-screen error if functional test fails/throws exception. (#151
Browse files Browse the repository at this point in the history
)

* display on-screen error if functional test fails/throws exception. clean up event handlers on context exit, clean up actors and event handlers on test complete

* PRfeedback
  • Loading branch information
sorenhan authored and Steven Vergenz committed Jan 30, 2019
1 parent 65e2cef commit 7f80482
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -332,3 +332,4 @@ built
npm-debug.log
lerna-debug.log
.openode
Dockerfile
9 changes: 8 additions & 1 deletion packages/altspacevr-extras/src/videoPlayerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@ export class VideoPlayerManager {
}

this._RPC = new ContextRPC(context);
this.context.onUserJoined(user => this.userJoined(user));

this.userJoined = this.userJoined.bind(this);
this.context.onUserJoined(this.userJoined);
}

public cleanup() {
this.context.offUserJoined(this.userJoined);
this._RPC.cleanup();
}

private userJoined(user: User) {
Expand Down
40 changes: 36 additions & 4 deletions packages/functional-tests/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import RigidBodyTest from './tests/rigid-body-test';
import Test from './tests/test';
import TextTest from './tests/text-test';
import UserTest from './tests/user-test';
import delay from './utils/delay';
import destroyActors from './utils/destroyActors';

/**
Expand Down Expand Up @@ -78,7 +79,7 @@ export default class App {
testName = this.params.test as string;
}
if (testName) {
await this.startTest(testName, user);
await this.runTest(testName, user);
this.rpc.send('functional-test:close-connection');
} else {
if (!this.firstUser) {
Expand All @@ -91,31 +92,62 @@ export default class App {
console.log(`user-left: ${user.name}, ${user.id}`);
delete this._connectedUsers[user.id];
}
private async startTest(testName: string, user: MRESDK.User) {
private async runTest(testName: string, user: MRESDK.User) {
if (this.activeTests[testName]) {
console.log(`Test already running: '${testName}'`);
} else if (!this.testFactories[testName]) {
console.log(`error: Unrecognized test: '${testName}'`);
} else {
this.rpc.send('functional-test:test-starting', testName);
console.log(`Test starting: '${testName}'`);
const test = this.activeTests[testName] = this.testFactories[testName](user);
this.rpc.send('functional-test:test-started', testName);
console.log(`Test started: '${testName}'`);

let success: boolean;
try {
success = await test.run();
if (!success) {
await this.displayError("Test Failed: '${testName}'");
}
} catch (e) {
console.log(e);
await this.displayError("Test Triggered Exception: " + e);
success = false;
}
console.log(`Test complete: '${testName}'. Success: ${success}`);
this.rpc.send('functional-test:test-complete', testName, success);

test.cleanup();

delete this.activeTests[testName];
// Delete all actors
destroyActors(this.context.rootActors);
this.context.assetManager.cleanup();
}
}

private async displayError(errorString: string) {
const errorLabel = await MRESDK.Actor.CreateEmpty(this.context, {
actor: {
name: 'label',
text: {
contents: errorString,
height: 0.5,
anchor: MRESDK.TextAnchorLocation.MiddleCenter
},
transform: {
position: { x: 0, y: 0, z: 0 }
}
}
});
await delay(2000);
destroyActors(errorLabel);
}

private async displayFunctionalTestChoices(rootActor: MRESDK.ActorLike): Promise<string> {
return new Promise<string>((resolve) => {
let y = 0;
let y = 0.3;
for (const key in this.testFactories) {
if (this.testFactories.hasOwnProperty(key)) {
const button = MRESDK.Actor.CreatePrimitive(this.context, {
Expand Down Expand Up @@ -163,7 +195,7 @@ export default class App {
const rootActor = MRESDK.Actor.CreateEmpty(this.context, {});
const selectedTestName = await this.displayFunctionalTestChoices(rootActor.value);
destroyActors(rootActor.value);
await this.startTest(selectedTestName, this.firstUser);
await this.runTest(selectedTestName, this.firstUser);
}
}
}
3 changes: 3 additions & 0 deletions packages/functional-tests/src/tests/altspacevr-video-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export default class AltspaceVRVideoTest extends Test {
super(app);
this.videoPlayerManager = new VideoPlayerManager(app.context);
}
public cleanup() {
this.videoPlayerManager.cleanup();
}

public async run(): Promise<boolean> {
let success = true;
Expand Down
2 changes: 2 additions & 0 deletions packages/functional-tests/src/tests/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ export default abstract class Test {
}

public abstract run(): Promise<boolean>;
public cleanup() {
}
}
10 changes: 9 additions & 1 deletion packages/sdk/src/rpc/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,18 @@ export class ContextRPC extends RPC {
*/
constructor(context: Context) {
super(context);
this.context.internal.__rpc = this;
if (this.context.internal.__rpc === undefined) {
this.context.internal.__rpc = this;
}
this._receive = this._receive.bind(this);
this.context.onReceiveRPC(this._receive);
}
public cleanup() {
if (this.context.internal.__rpc === this) {
this.context.internal.__rpc = undefined;
}
this.context.offReceiveRPC(this._receive);
}

public channel(channelName: string, create = true) {
if (!this.channels[channelName]) {
Expand Down
1 change: 1 addition & 0 deletions packages/sdk/src/types/internal/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,7 @@ export class InternalContext {
delete this.interval;
this.protocol.stopListening();
this.context.emitter.emit('stopped');
this.context.emitter.clearAll();
}

public incrementGeneration() {
Expand Down
2 changes: 2 additions & 0 deletions packages/sdk/src/types/runtime/assets/assetManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export class AssetManager {
/** @hidden */
public constructor(public context: Context) { }

public cleanup() {
}
/** Fetch a group by name. */
public get groups() { return Object.freeze({ ...this._groups }); }

Expand Down
51 changes: 48 additions & 3 deletions packages/sdk/src/types/runtime/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,16 @@ export class Context {
}

/**
* The 'onUserLeft event is raised when the given user has left the Context. After the last user leaves, the Context
* Remove the onUserJoined event handler from the Context.
* @event
*/
public offUserJoined(handler: (user: User) => void): this {
this.emitter.off('user-joined', handler);
return this;
}

/**
* The onUserLeft event is raised when the given user has left the Context. After the last user leaves, the Context
* will be shutdown (and a 'stopped' event will soon follow).
* @event
*/
Expand All @@ -112,11 +121,20 @@ export class Context {
return this;
}

/**
* Remove the onUserLeft event handler from the Context
* @event
*/
public offUserLeft(handler: (user: User) => void): this {
this.emitter.off('user-left', handler);
return this;
}

/**
* @hidden
* (for now)
*/
public onActorCreated(handler: (user: User) => void): this {
public onActorCreated(handler: (actor: Actor) => void): this {
this.emitter.on('actor-created', handler);
return this;
}
Expand All @@ -125,11 +143,29 @@ export class Context {
* @hidden
* (for now)
*/
public onActorDestroyed(handler: (user: User) => void): this {
public offActorCreated(handler: (actor: Actor) => void): this {
this.emitter.off('actor-created', handler);
return this;
}

/**
* @hidden
* (for now)
*/
public onActorDestroyed(handler: (actor: Actor) => void): this {
this.emitter.on('actor-destroyed', handler);
return this;
}

/**
* @hidden
* (for now)
*/
public offActorDestroyed(handler: (actor: Actor) => void): this {
this.emitter.off('actor-destroyed', handler);
return this;
}

/**
* @hidden
*/
Expand All @@ -138,4 +174,13 @@ export class Context {
this.emitter.on('context.receive-rpc', handler);
return this;
}

/**
* @hidden
*/
// tslint:disable-next-line:max-line-length
public offReceiveRPC(handler: (procName: string, channelName: string, args: any[]) => void): this {
this.emitter.off('context.receive-rpc', handler);
return this;
}
}
5 changes: 4 additions & 1 deletion packages/sdk/src/utils/bufferedEventEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export default class BufferedEventEmitter implements EventEmitterLike {
private emitter = new events.EventEmitter();
private queuedEvents: { [key: string]: QueuedEvent[] } = {};

public clearAll() {
this.emitter.removeAllListeners();
}
public on(event: string | symbol, listener: (...args: any[]) => void): this {
this.emitter.on(event, listener);
process.nextTick(() => {
Expand All @@ -40,7 +43,7 @@ export default class BufferedEventEmitter implements EventEmitterLike {
}

public off(event: string | symbol, listener: (...args: any[]) => void): this {
this.emitter.off(event, listener);
this.emitter.removeListener(event, listener);
return this;
}

Expand Down

0 comments on commit 7f80482

Please sign in to comment.