Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorAustin Schaffer <austin.schaffer@ryansg.com>2019-12-02 10:00:23 -0500
committerAustin Schaffer <austin.schaffer@ryansg.com>2019-12-12 10:14:54 -0500
commitd9ee999adbfbd22ed7a9f67766d0ce243c30bd90 (patch)
treed3aafc862d299983498410f2f395a1af1a06319d /test
parent1ddb6f29eb7e9e1b55820f1c94ea9a4b73db7fb7 (diff)
downloadliza-d9ee999adbfbd22ed7a9f67766d0ce243c30bd90.tar.gz
liza-d9ee999adbfbd22ed7a9f67766d0ce243c30bd90.tar.bz2
liza-d9ee999adbfbd22ed7a9f67766d0ce243c30bd90.zip
[DEV-5312] Refactor class dependencies
Move create config functions out of the main delta-processor.ts file. Change some any types to more specific types. Define document structure better. Move prometheus logic out of processor class. Do not call logger directly, listen for events and log them. Change logger to more PSR-3 compliant style. Extract amqp connection into its own class. Create avro and mongo objects in factory.
Diffstat (limited to 'test')
-rw-r--r--test/server/db/MongoServerDaoTest.js157
-rw-r--r--test/server/db/MongoServerDaoTest.ts7
-rw-r--r--test/system/DeltaProcessorTest.ts312
-rw-r--r--test/system/DeltaPublisherTest.ts221
-rw-r--r--test/system/EventLoggerTest.ts103
-rw-r--r--test/system/EventMediatorTest.ts139
-rw-r--r--test/system/MetricsCollectorTest.ts26
-rw-r--r--test/system/StandardLoggerTest.ts178
8 files changed, 776 insertions, 367 deletions
diff --git a/test/server/db/MongoServerDaoTest.js b/test/server/db/MongoServerDaoTest.js
deleted file mode 100644
index d6c8bf1..0000000
--- a/test/server/db/MongoServerDaoTest.js
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * Tests MongoServerDao
- *
- * Copyright (C) 2010-2019 R-T Specialty, LLC.
- *
- * This file is part of the Liza Data Collection Framework.
- *
- * liza is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-'use strict';
-Object.defineProperty(exports, "__esModule", { value: true });
-var MongoServerDao_1 = require("../../../src/server/db/MongoServerDao");
-var chai_1 = require("chai");
-chai_1.use(require('chai-as-promised'));
-describe('MongoServerDao', function () {
- describe('#saveQuote', function () {
- describe("with no save data or push data", function () {
- it("saves entire metabucket record individually", function (done) {
- var metadata = {
- foo: ['bar', 'baz'],
- bar: [{ quux: 'quuux' }],
- };
- var quote = createStubQuote(metadata);
- var sut = new MongoServerDao_1.MongoServerDao(createMockDb(
- // update
- function (_selector, data) {
- chai_1.expect(data.$set['meta.foo'])
- .to.deep.equal(metadata.foo);
- chai_1.expect(data.$set['meta.bar'])
- .to.deep.equal(metadata.bar);
- chai_1.expect(data.$push).to.equal(undefined);
- done();
- }));
- sut.init(function () {
- return sut.saveQuote(quote, function () { }, function () { });
- });
- });
- });
- describe("with push data", function () {
- it("adds push data to the collection", function (done) {
- var push_data = {
- foo: ['bar', 'baz'],
- bar: [{ quux: 'quuux' }],
- };
- var quote = createStubQuote({});
- var sut = new MongoServerDao_1.MongoServerDao(createMockDb(
- // update
- function (_selector, data) {
- chai_1.expect(data.$push['foo'])
- .to.deep.equal(push_data.foo);
- chai_1.expect(data.$push['bar'])
- .to.deep.equal(push_data.bar);
- done();
- }));
- sut.init(function () {
- return sut.saveQuote(quote, function () { }, function () { }, undefined, push_data);
- });
- });
- it("skips push data when it is an empty object", function (done) {
- var push_data = {};
- var quote = createStubQuote({});
- var sut = new MongoServerDao_1.MongoServerDao(createMockDb(
- // update
- function (_selector, data) {
- chai_1.expect(data.$push).to.equal(undefined);
- done();
- }));
- sut.init(function () {
- return sut.saveQuote(quote, function () { }, function () { }, undefined, push_data);
- });
- });
- });
- });
-});
-function createMockDb(on_update) {
- var collection_quotes = {
- update: on_update,
- createIndex: function (_, __, c) { return c(); },
- };
- var collection_seq = {
- find: function (_, __, c) {
- c(null, {
- toArray: function (c) { return c(null, { length: 5 }); },
- });
- },
- };
- var db = {
- collection: function (id, c) {
- var coll = (id === 'quotes')
- ? collection_quotes
- : collection_seq;
- c(null, coll);
- },
- };
- var driver = {
- open: function (c) { return c(null, db); },
- on: function () { },
- };
- return driver;
-}
-function createStubQuote(metadata) {
- var program = {
- getId: function () { return '1'; },
- ineligibleLockCount: 0,
- apis: {},
- internal: {},
- meta: {
- arefs: {},
- fields: {},
- groups: {},
- qdata: {},
- qtypes: {},
- },
- mapis: {},
- initQuote: function () { },
- };
- var quote = {
- getBucket: function () { return ({
- getData: function () { },
- }); },
- getMetabucket: function () { return ({
- getData: function () { return metadata; },
- }); },
- getId: function () { return 123; },
- getProgramVersion: function () { return 'Foo'; },
- getLastPremiumDate: function () { return 0; },
- getRatedDate: function () { return 0; },
- getExplicitLockReason: function () { return ""; },
- getExplicitLockStep: function () { return 1; },
- isImported: function () { return false; },
- isBound: function () { return false; },
- getTopVisitedStepId: function () { return 1; },
- getTopSavedStepId: function () { return 1; },
- setRatedDate: function () { return quote; },
- setRateBucket: function () { return quote; },
- setRatingData: function () { return quote; },
- getRatingData: function () { return ({ _unavailable_all: '0' }); },
- getProgram: function () { return program; },
- setExplicitLock: function () { return quote; },
- getProgramId: function () { return 'Foo'; },
- getCurrentStepId: function () { return 0; },
- setLastPremiumDate: function () { return quote; },
- };
- return quote;
-}
-//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTW9uZ29TZXJ2ZXJEYW9UZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiTW9uZ29TZXJ2ZXJEYW9UZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBRUgsWUFBWSxDQUFDOztBQUViLHdFQUE4RTtBQUU5RSw2QkFBK0M7QUFRL0MsVUFBUSxDQUFFLE9BQU8sQ0FBRSxrQkFBa0IsQ0FBRSxDQUFFLENBQUM7QUFHMUMsUUFBUSxDQUFFLGdCQUFnQixFQUFFO0lBRXhCLFFBQVEsQ0FBRSxZQUFZLEVBQUU7UUFFcEIsUUFBUSxDQUFFLGdDQUFnQyxFQUFFO1lBRXhDLEVBQUUsQ0FBRSw2Q0FBNkMsRUFBRSxVQUFBLElBQUk7Z0JBRW5ELElBQU0sUUFBUSxHQUFHO29CQUNiLEdBQUcsRUFBRSxDQUFFLEtBQUssRUFBRSxLQUFLLENBQUU7b0JBQ3JCLEdBQUcsRUFBRSxDQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFFO2lCQUM3QixDQUFDO2dCQUVGLElBQU0sS0FBSyxHQUFHLGVBQWUsQ0FBRSxRQUFRLENBQUUsQ0FBQztnQkFFMUMsSUFBTSxHQUFHLEdBQUcsSUFBSSwrQkFBRyxDQUFFLFlBQVk7Z0JBQzdCLFNBQVM7Z0JBQ1QsVUFBRSxTQUF3QixFQUFFLElBQWlCO29CQUV6QyxhQUFNLENBQUUsSUFBSSxDQUFDLElBQUksQ0FBRSxVQUFVLENBQUUsQ0FBRTt5QkFDNUIsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUUsUUFBUSxDQUFDLEdBQUcsQ0FBRSxDQUFDO29CQUVuQyxhQUFNLENBQUUsSUFBSSxDQUFDLElBQUksQ0FBRSxVQUFVLENBQUUsQ0FBRTt5QkFDNUIsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUUsUUFBUSxDQUFDLEdBQUcsQ0FBRSxDQUFDO29CQUduQyxhQUFNLENBQUUsSUFBSSxDQUFDLEtBQUssQ0FBRSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENB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 \ No newline at end of file
diff --git a/test/server/db/MongoServerDaoTest.ts b/test/server/db/MongoServerDaoTest.ts
index b0a83bb..58e6ab9 100644
--- a/test/server/db/MongoServerDaoTest.ts
+++ b/test/server/db/MongoServerDaoTest.ts
@@ -22,7 +22,7 @@
'use strict';
import { MongoServerDao as Sut } from "../../../src/server/db/MongoServerDao";
-import { MongoSelector, MongoUpdate } from "mongodb";
+import { MongoSelector, MongoUpdate, MongoDb } from "mongodb";
import { expect, use as chai_use } from 'chai';
import { ServerSideQuote } from "../../../src/server/quote/ServerSideQuote";
import { PositiveInteger } from "../../../src/numeric";
@@ -139,7 +139,7 @@ describe( 'MongoServerDao', () =>
} );
-function createMockDb( on_update: any )
+function createMockDb( on_update: any ): MongoDb
{
const collection_quotes = {
update: on_update,
@@ -166,8 +166,9 @@ function createMockDb( on_update: any )
},
};
- const driver = {
+ const driver = <MongoDb>{
open: ( c: any ) => c( null, db ),
+ close: () => {},
on: () => {},
};
diff --git a/test/system/DeltaProcessorTest.ts b/test/system/DeltaProcessorTest.ts
index d0cd8f8..3998d68 100644
--- a/test/system/DeltaProcessorTest.ts
+++ b/test/system/DeltaProcessorTest.ts
@@ -22,7 +22,8 @@
import { DeltaProcessor as Sut } from '../../src/system/DeltaProcessor';
import { AmqpPublisher } from '../../src/system/AmqpPublisher';
import { DeltaDao } from '../../src/system/db/DeltaDao';
-import { DeltaType } from "../../src/bucket/delta";
+import { DeltaType, DeltaDocument } from "../../src/bucket/delta";
+import { DocumentId } from '../../src/document/Document';
import { EventEmitter } from 'events';
import { expect, use as chai_use } from 'chai';
@@ -308,11 +309,12 @@ describe( 'system.DeltaProcessor', () =>
}[]>[
{
label: 'No deltas are processed',
- docs: [
+ given: [
{
id: 123,
lastUpdate: 123123123,
- bucket: {},
+ data: {},
+ ratedata: {},
rdelta: {},
},
],
@@ -324,7 +326,8 @@ describe( 'system.DeltaProcessor', () =>
{
id: 123,
lastUpdate: 123123123,
- bucket: { foo: [ 'start_bar' ] },
+ data: { foo: [ 'start_bar' ] },
+ ratedata: {},
rdelta: {
data: [
{
@@ -341,14 +344,16 @@ describe( 'system.DeltaProcessor', () =>
],
expected: [
{
- delta: { foo: [ 'first_bar' ] },
- bucket: { foo: [ 'first_bar' ] },
- doc_id: 123,
+ doc_id: 123,
+ delta: { foo: [ 'first_bar' ] },
+ bucket: { foo: [ 'first_bar' ] },
+ ratedata: {},
},
{
- delta: { foo: [ 'second_bar' ] },
- bucket: { foo: [ 'second_bar' ] },
- doc_id: 123,
+ doc_id: 123,
+ delta: { foo: [ 'second_bar' ] },
+ bucket: { foo: [ 'second_bar' ] },
+ ratedata: {},
},
],
},
@@ -358,17 +363,18 @@ describe( 'system.DeltaProcessor', () =>
{
id: 123,
lastUpdate: 123123123,
- bucket: { foo: 'start_bar' },
+ data: { foo: [ 'start_bar_123' ] },
+ ratedata: {},
rdelta: {
data: [
{
- data: { foo: [ 'second_bar' ] },
+ data: { foo: [ 'second_bar_123' ] },
timestamp: 234,
},
],
ratedata: [
{
- data: { foo: [ 'first_bar' ] },
+ data: { foo: [ 'first_bar_123' ] },
timestamp: 123,
},
],
@@ -377,19 +383,20 @@ describe( 'system.DeltaProcessor', () =>
{
id: 234,
lastUpdate: 123123123,
- bucket: { foo: 'start_bar' },
+ data: { foo: [ 'start_bar_234' ] },
+ ratedata: {},
rdelta: {
data: [
{
- data: { foo: [ 'first_bar' ] },
+ data: { foo: [ 'first_bar_234' ] },
timestamp: 123,
},
{
- data: { foo: [ 'second_bar' ] },
+ data: { foo: [ 'second_bar_234' ] },
timestamp: 234,
},
{
- data: { foo: [ 'third_bar' ] },
+ data: { foo: [ 'third_bar_234' ] },
timestamp: 345,
},
],
@@ -398,15 +405,16 @@ describe( 'system.DeltaProcessor', () =>
{
id: 345,
lastUpdate: 123123123,
- bucket: { foo: 'start_bar' },
+ data: { foo: [ 'start_bar_345' ] },
+ ratedata: {},
rdelta: {
ratedata: [
{
- data: { foo: [ 'first_bar' ] },
+ data: { foo: [ 'first_bar_345' ] },
timestamp: 123,
},
{
- data: { foo: [ 'second_bar' ] },
+ data: { foo: [ 'second_bar_345' ] },
timestamp: 234,
},
],
@@ -415,60 +423,73 @@ describe( 'system.DeltaProcessor', () =>
],
expected: [
{
- delta: { foo: [ 'first_bar' ] },
- bucket: { foo: [ 'first_bar' ] },
- doc_id: 123,
+ doc_id: 123,
+ delta: { foo: [ 'first_bar_123' ] },
+ bucket: { foo: [ 'start_bar_123' ] },
+ ratedata: { foo: [ 'first_bar_123' ] },
},
{
- delta: { foo: [ 'second_bar' ] },
- bucket: { foo: [ 'second_bar' ] },
- doc_id: 123,
+ doc_id: 123,
+ delta: { foo: [ 'second_bar_123' ] },
+ bucket: { foo: [ 'second_bar_123' ] },
+ ratedata: { foo: [ 'first_bar_123' ] },
},
{
- delta: { foo: [ 'first_bar' ] },
- bucket: { foo: [ 'first_bar' ] },
- doc_id: 234,
+ doc_id: 234,
+ delta: { foo: [ 'first_bar_234' ] },
+ bucket: { foo: [ 'first_bar_234' ] },
+ ratedata: {},
},
{
- delta: { foo: [ 'second_bar' ] },
- bucket: { foo: [ 'second_bar' ] },
- doc_id: 234,
+ doc_id: 234,
+ delta: { foo: [ 'second_bar_234' ] },
+ bucket: { foo: [ 'second_bar_234' ] },
+ ratedata: {},
},
{
- delta: { foo: [ 'third_bar' ] },
- bucket: { foo: [ 'third_bar' ] },
- doc_id: 234,
+ doc_id: 234,
+ delta: { foo: [ 'third_bar_234' ] },
+ bucket: { foo: [ 'third_bar_234' ] },
+ ratedata: {},
},
{
- delta: { foo: [ 'first_bar' ] },
- bucket: { foo: [ 'first_bar' ] },
- doc_id: 345,
+ doc_id: 345,
+ delta: { foo: [ 'first_bar_345' ] },
+ bucket: { foo: [ 'start_bar_345' ] },
+ ratedata: { foo: [ 'first_bar_345' ] },
},
{
- delta: { foo: [ 'second_bar' ] },
- bucket: { foo: [ 'second_bar' ] },
- doc_id: 345,
+ doc_id: 345,
+ delta: { foo: [ 'second_bar_345' ] },
+ bucket: { foo: [ 'start_bar_345' ] },
+ ratedata: { foo: [ 'second_bar_345' ] },
},
],
},
- ] ).forEach( ( { given, expected, label } ) => it( label, () =>
+ ] ).forEach( ( { label, given, expected } ) => it( label, () =>
{
let published: any = [];
const dao = createMockDeltaDao();
const publisher = createMockDeltaPublisher();
const emitter = new EventEmitter();
- dao.getUnprocessedDocuments = (): Promise<Record<string, any>[]> =>
+ dao.getUnprocessedDocuments = (): Promise<DeltaDocument[]> =>
{
return Promise.resolve( given );
}
- publisher.publish = ( delta, bucket, doc_id ): Promise<void> =>
+ publisher.publish = (
+ doc_id,
+ delta,
+ bucket,
+ ratedata,
+ ): Promise<void> =>
{
published.push( {
- delta: delta.data,
- bucket: bucket,
- doc_id: doc_id,
+ doc_id: doc_id,
+ delta: delta.data,
+ bucket: bucket,
+ ratedata: ratedata,
} );
return Promise.resolve();
@@ -479,6 +500,203 @@ describe( 'system.DeltaProcessor', () =>
.then( _ => expect( published ).to.deep.equal( expected ) );
} ) );
} );
+
+
+ describe( 'Error handling', () =>
+ {
+ it( 'Marks document in error state and continues', () =>
+ {
+ let published: any = [];
+ let error_flag_set = false;
+ const dao = createMockDeltaDao();
+ const publisher = createMockDeltaPublisher();
+ const emitter = new EventEmitter();
+ const doc = <DeltaDocument[]>[ {
+ id: <DocumentId>123,
+ lastUpdate: <UnixTimestamp>123123123,
+ data: { foo: [ 'start_bar' ] },
+ ratedata: {},
+ rdelta: {
+ data: [
+ {
+ data: { foo: [ 'first_bar' ] },
+ timestamp: <UnixTimestamp>123123,
+ type: 'data',
+ }
+ ],
+ ratedata: [],
+ },
+ },
+ {
+ id: <DocumentId>234,
+ lastUpdate: <UnixTimestamp>123123123,
+ data: { foo: [ 'start_bar' ] },
+ ratedata: {},
+ rdelta: {
+ data: [
+ {
+ data: { foo: [ 'first_bar' ] },
+ timestamp: <UnixTimestamp>123123,
+ type: 'data',
+ }
+ ],
+ ratedata: [],
+ },
+ } ];
+
+ const expected_published = [
+ {
+ doc_id: 123,
+ delta: { foo: [ 'first_bar' ] },
+ bucket: { foo: [ 'first_bar' ] },
+ ratedata: {},
+ },
+ {
+ doc_id: 234,
+ delta: { foo: [ 'first_bar' ] },
+ bucket: { foo: [ 'first_bar' ] },
+ ratedata: {},
+ }
+ ];
+
+ const expected_error = 'Uh oh';
+
+ dao.getUnprocessedDocuments = (): Promise<DeltaDocument[]> =>
+ Promise.resolve( doc );
+
+ dao.markDocumentAsProcessed = ( _doc_id, _ts ): Promise<void> =>
+ Promise.reject( new Error( expected_error ) );
+
+ dao.setErrorFlag = (): Promise<void> =>
+ {
+ error_flag_set = true;
+ return Promise.resolve();
+ }
+
+ publisher.publish = (
+ doc_id,
+ delta,
+ bucket,
+ ratedata,
+ ): Promise<void> =>
+ {
+ published.push( {
+ doc_id: doc_id,
+ delta: delta.data,
+ bucket: bucket,
+ ratedata: ratedata,
+ } );
+
+ return Promise.resolve();
+ }
+
+ // Prevent node from converting an error event into an error
+ emitter.on( 'error', () => {} );
+
+ return expect( new Sut( dao, publisher, emitter ).process() )
+ .to.eventually.deep.equal( undefined )
+ .then( _ =>
+ {
+ expect( error_flag_set ).to.be.true;
+ expect( published ).to.deep.equal( expected_published );
+ } );
+ } );
+ } );
+
+
+ describe( 'Error handling', () =>
+ {
+ it( 'Failure to set document error state further processing', () =>
+ {
+ let published: any = [];
+ let caught_error = '';
+ const dao = createMockDeltaDao();
+ const publisher = createMockDeltaPublisher();
+ const emitter = new EventEmitter();
+ const doc = <DeltaDocument[]>[ {
+ id: <DocumentId>123,
+ lastUpdate: <UnixTimestamp>123123123,
+ data: { foo: [ 'start_bar' ] },
+ ratedata: {},
+ rdelta: {
+ data: [
+ {
+ data: { foo: [ 'first_bar' ] },
+ timestamp: <UnixTimestamp>123123,
+ type: 'data',
+ }
+ ],
+ ratedata: [],
+ },
+ },
+ {
+ id: <DocumentId>234,
+ lastUpdate: <UnixTimestamp>123123123,
+ data: { foo: [ 'start_bar' ] },
+ ratedata: {},
+ rdelta: {
+ data: [
+ {
+ data: { foo: [ 'first_bar' ] },
+ timestamp: <UnixTimestamp>123123,
+ type: 'data',
+ }
+ ],
+ ratedata: [],
+ },
+ } ];
+
+ // Only one is published
+ const expected_published = [ {
+ doc_id: 123,
+ delta: { foo: [ 'first_bar' ] },
+ bucket: { foo: [ 'first_bar' ] },
+ ratedata: {},
+ } ];
+
+ const expected_error = 'Uh oh';
+
+ dao.getUnprocessedDocuments = (): Promise<DeltaDocument[]> =>
+ Promise.resolve( doc );
+
+ dao.markDocumentAsProcessed = ( _doc_id, _ts ): Promise<void> =>
+ Promise.reject( new Error( 'Couldn\'t mark document' ) );
+
+ dao.setErrorFlag = (): Promise<void> =>
+ Promise.reject( new Error( expected_error ) );
+
+ publisher.publish = (
+ doc_id,
+ delta,
+ bucket,
+ ratedata,
+ ): Promise<void> =>
+ {
+ published.push( {
+ doc_id: doc_id,
+ delta: delta.data,
+ bucket: bucket,
+ ratedata: ratedata,
+ } );
+
+ return Promise.resolve();
+ }
+
+ // Prevent node from converting an error event into an error
+ emitter.on( 'error', () => {} );
+
+ return expect(
+ new Sut( dao, publisher, emitter ).process()
+ .catch( e => { caught_error = e.message } )
+ )
+ .to.eventually.deep.equal( undefined )
+ .then( _ =>
+ {
+ expect( caught_error ).to.equal( expected_error );
+ expect( published ).to.deep.equal( expected_published );
+ } );
+ } );
+ } );
} );
diff --git a/test/system/DeltaPublisherTest.ts b/test/system/DeltaPublisherTest.ts
index 40663d0..fcb788c 100644
--- a/test/system/DeltaPublisherTest.ts
+++ b/test/system/DeltaPublisherTest.ts
@@ -19,13 +19,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import { AmqpConnection } from '../../src/system/amqp/AmqpConnection';
+import { Delta, DeltaResult, DeltaType } from '../../src/bucket/delta';
import { DeltaPublisher as Sut } from '../../src/system/DeltaPublisher';
-import { AmqpConfig } from '../../src/system/AmqpPublisher';
+import { DocumentId } from '../../src/document/Document';
+import { Duplex } from 'stream';
import { EventEmitter } from "events";
+import { hasContext } from '../../src/error/ContextError';
+import { AmqpError } from '../../src/error/AmqpError';
+import { Channel } from 'amqplib';
+import {
+ createAvroEncoder,
+ AvroEncoderCtr,
+ AvroSchema,
+} from '../../src/system/avro/AvroFactory';
import { expect, use as chai_use } from 'chai';
chai_use( require( 'chai-as-promised' ) );
+const sinon = require( 'sinon' );
describe( 'server.DeltaPublisher', () =>
{
@@ -33,24 +45,96 @@ describe( 'server.DeltaPublisher', () =>
{
it( 'sends a message', () =>
{
- const conf = createMockConf();
- const emitter = new EventEmitter();
+ let publish_called = false;
+ const delta = createMockDelta();
+ const bucket = createMockBucketData();
+ const ratedata = createMockBucketData();
+ const emitter = new EventEmitter();
+ const conn = createMockAmqpConnection();
+ conn.getAmqpChannel = () =>
+ {
+ return <Channel>{
+ publish: ( _: any, __: any, buf: any, ___: any ) =>
+ {
+ expect( buf instanceof Buffer ).to.be.true;
- console.log( new Sut( conf, emitter, ts_ctr ) );
- expect( true ).to.be.true
+ publish_called = true;
+
+ return true;
+ }
+ };
+ };
+
+ const sut = new Sut( emitter, ts_ctr, createAvroEncoder, conn );
+
+ return expect(
+ sut.publish( <DocumentId>123, delta, bucket, ratedata )
+ ).to.eventually.deep.equal( undefined )
+ .then( _ =>
+ {
+ expect( publish_called ).to.be.true;
+ } );
} );
- } );
- describe( '#sendMessage', () =>
- {
- it( 'sends a message', () =>
+ ( <[string, () => Channel | undefined, Error, string ][]>[
+ [
+ 'Throws an error when publishing was unsuccessful',
+ () =>
+ {
+ return <Channel>{
+ publish: ( _: any, __: any, _buf: any, ___: any ) =>
+ {
+ return false;
+ }
+ };
+ },
+ Error,
+ 'Delta publish failed'
+ ],
+ [
+ 'Throws an error when no amqp channel is found',
+ () =>
+ {
+ return undefined;
+ },
+ AmqpError,
+ 'Error sending message: No channel'
+ ]
+ ] ).forEach( ( [ label, getChannelF, error_type, err_msg ] ) =>
+ it( label, () =>
{
- const conf = createMockConf();
- const emitter = new EventEmitter();
+ const delta = createMockDelta();
+ const bucket = createMockBucketData();
+ const ratedata = createMockBucketData();
+ const emitter = new EventEmitter();
+ const conn = createMockAmqpConnection();
+ const doc_id = <DocumentId>123;
+ const expected = {
+ doc_id: doc_id,
+ delta_type: delta.type,
+ delta_ts: delta.timestamp
+ }
- console.log( new Sut( conf, emitter, ts_ctr ) );
- expect( true ).to.be.true
- } );
+ conn.getAmqpChannel = getChannelF;
+
+ const result = new Sut( emitter, ts_ctr, createAvroEncoder, conn )
+ .publish( doc_id, delta, bucket, ratedata );
+
+ return Promise.all( [
+ expect( result ).to.eventually.be.rejectedWith(
+ error_type, err_msg
+ ),
+ result.catch( e =>
+ {
+ if ( !hasContext( e ) )
+ {
+ return expect.fail();
+ }
+
+ return expect( e.context ).to.deep.equal( expected );
+ } )
+ ] );
+ } ) );
} );
describe( '#avroEncode parses', () =>
@@ -137,32 +221,26 @@ describe( 'server.DeltaPublisher', () =>
{
it( label, () =>
{
- let errorCalled = false;
+ const emitter = createMockEventEmitter();
+ const conn = createMockAmqpConnection();
+ const data = createMockData( delta_data );
+ const sut = new Sut(
+ emitter,
+ ts_ctr,
+ createAvroEncoder,
+ conn,
+ );
- const emitter = <EventEmitter>{
- emit( _event_id, _err )
+ sut.avroEncode( data )
+ .then( b =>
{
- errorCalled = true;
-
- console.log( 'server.DeltaPublisher.Error' + _err );
- }
- }
-
- const conf = createMockConf();
- const data = createMockData( delta_data );
- const sut = new Sut( conf, emitter, ts_ctr );
- const buffer = sut.avroEncode( data );
-
- if ( valid )
- {
- expect( typeof(buffer) ).to.equal( 'object' );
- }
- else
- {
- expect( buffer ).to.equal( null );
- }
-
- expect( valid ).to.equal( !errorCalled );
+ expect( typeof(b) ).to.equal( 'object' );
+ expect( valid ).to.be.true;
+ } )
+ .catch( _ =>
+ {
+ expect( valid ).to.be.false;
+ } );
} );
} );
} );
@@ -301,9 +379,16 @@ describe( 'server.DeltaPublisher', () =>
{
it( label, () =>
{
- const emitter = <EventEmitter>{}
- const conf = createMockConf();
- const sut = new Sut( conf, emitter, ts_ctr );
+ const encoded = 'FooBar';
+ const emitter = createMockEventEmitter();
+ const conn = createMockAmqpConnection();
+ const avroEncoderCtr = createMockEncoder( encoded );
+ const sut = new Sut(
+ emitter,
+ ts_ctr,
+ avroEncoderCtr,
+ conn,
+ );
const actual = sut.setDataTypes( delta_data );
expect( actual ).to.deep.equal( expected );
@@ -312,14 +397,39 @@ describe( 'server.DeltaPublisher', () =>
} );
} );
+
function ts_ctr(): UnixTimestamp
{
return <UnixTimestamp>Math.floor( new Date().getTime() / 1000 );
}
-function createMockConf(): AmqpConfig
+
+function createMockEncoder( mock_encoded_data: string ): AvroEncoderCtr
+{
+ return ( _schema: AvroSchema ) =>
+ {
+ const mock = sinon.mock( Duplex );
+
+ mock.on = ( _: string, __: any ) => {};
+ mock.end = ( _: any ) => { return mock_encoded_data; };
+
+ return mock;
+ };
+}
+
+
+function createMockEventEmitter(): EventEmitter
+{
+ return <EventEmitter>{};
+}
+
+
+function createMockAmqpConnection(): AmqpConnection
{
- return <AmqpConfig>{};
+ return <AmqpConnection>{
+ connect: () => {},
+ getExchangeName: () => { 'Foo' },
+ };
}
@@ -339,11 +449,8 @@ function createMockData( delta_data: any ): any
modified: 1573856916,
top_visited_step: '2',
},
- session: {
- entity_name: 'Foobar',
- entity_id: 123123 ,
- },
- data: null,
+ data: null,
+ ratedata: null,
delta: {
Data: {
bucket: delta_data,
@@ -356,4 +463,22 @@ function createMockData( delta_data: any ): any
},
},
};
+}
+
+
+function createMockBucketData(): Record<string, any>
+{
+ return {
+ foo: [ 'bar', 'baz' ]
+ }
+}
+
+
+function createMockDelta(): Delta<any>
+{
+ return <Delta<any>>{
+ type: <DeltaType>'data',
+ timestamp: <UnixTimestamp>123123123,
+ data: <DeltaResult<any>>{},
+ }
} \ No newline at end of file
diff --git a/test/system/EventLoggerTest.ts b/test/system/EventLoggerTest.ts
deleted file mode 100644
index b3d5f0f..0000000
--- a/test/system/EventLoggerTest.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * Event logger test
- *
- * Copyright (C) 2010-2019 R-T Specialty, LLC.
- *
- * This file is part of the Liza Data Collection Framework.
- *
- * liza is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import { EventLogger as Sut } from '../../src/system/EventLogger';
-import { EventEmitter } from "events";
-import { expect } from 'chai';
-
-const sinon = require( 'sinon' );
-
-declare interface MockConsole extends Console {
- getLevel(): string,
-}
-
-describe( 'system.EventLogger captures and logs events', () =>
-{
- [
- {
- event_id: 'document-processed',
- console_level: 'log',
- },
- {
- event_id: 'delta-publish',
- console_level: 'log',
- },
- {
- event_id: 'amqp-conn-error',
- console_level: 'warn',
- },
- {
- event_id: 'amqp-reconnect',
- console_level: 'warn',
- },
- {
- event_id: 'amqp-reconnect-fail',
- console_level: 'error',
- },
- {
- event_id: 'avro-err',
- console_level: 'error',
- },
- {
- event_id: 'dao-err',
- console_level: 'error',
- },
- {
- event_id: 'publish-err',
- console_level: 'error',
- },
- ].forEach( ( { event_id, console_level } ) =>
- {
- it( event_id + ' triggers console output level: ' + console_level, () =>
- {
- const emitter = new EventEmitter();
- const con = createMockConsole();
- const env = 'test';
-
- new Sut( con, env, emitter, ts_ctr );
-
- emitter.emit( event_id );
-
- expect( con.getLevel() ).to.equal( console_level );
- } );
- } );
-} );
-
-
-function ts_ctr(): UnixTimestamp
-{
- return <UnixTimestamp>Math.floor( new Date().getTime() / 1000 );
-}
-
-
-function createMockConsole(): MockConsole
-{
- const mock = sinon.mock( console );
-
- mock.level = '';
- mock.info = ( _str: string ) => { mock.level = 'info'; };
- mock.log = ( _str: string ) => { mock.level = 'log'; };
- mock.warn = ( _str: string ) => { mock.level = 'warn'; };
- mock.error = ( _str: string ) => { mock.level = 'error'; };
- mock.getLevel = () => mock.level;
-
- return mock;
-} \ No newline at end of file
diff --git a/test/system/EventMediatorTest.ts b/test/system/EventMediatorTest.ts
new file mode 100644
index 0000000..581437c
--- /dev/null
+++ b/test/system/EventMediatorTest.ts
@@ -0,0 +1,139 @@
+/**
+ * Event logger test
+ *
+ * Copyright (C) 2010-2019 R-T Specialty, LLC.
+ *
+ * This file is part of the Liza Data Collection Framework.
+ *
+ * liza is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import { EventMediator as Sut } from '../../src/system/EventMediator';
+import { context } from '../../src/error/ContextError';
+import { EventEmitter } from "events";
+import { expect } from 'chai';
+import { PsrLogger } from '../../src/system/PsrLogger';
+
+
+describe( 'system.EventLogger captures and logs events', () =>
+{
+ it( 'document-processed triggers log#notice', () =>
+ {
+ let method_called = false;
+
+ const event_id = 'document-processed';
+ const emitter = new EventEmitter();
+ const log = createMockLogger();
+
+ log.notice = ( _str: string ) => { method_called = true; };
+
+ new Sut( log, emitter );
+
+ emitter.emit( event_id );
+
+ expect( method_called ).to.be.true;
+ } );
+
+ it( 'delta-publish triggers log#notice', () =>
+ {
+ let method_called = false;
+
+ const event_id = 'delta-publish';
+ const emitter = new EventEmitter();
+ const log = createMockLogger();
+
+ log.notice = ( _str: string ) => { method_called = true; };
+
+ new Sut( log, emitter );
+
+ emitter.emit( event_id );
+
+ expect( method_called ).to.be.true;
+ } );
+
+ it( 'amqp-conn-error triggers log#warning', () =>
+ {
+ let method_called = false;
+
+ const event_id = 'amqp-conn-error';
+ const emitter = new EventEmitter();
+ const log = createMockLogger();
+
+ log.warning = ( _str: string ) => { method_called = true; };
+
+ new Sut( log, emitter );
+
+ emitter.emit( event_id );
+
+ expect( method_called ).to.be.true;
+ } );
+
+ it( 'amqp-reconnect triggers log#warning', () =>
+ {
+ let method_called = false;
+
+ const event_id = 'amqp-reconnect';
+ const emitter = new EventEmitter();
+ const log = createMockLogger();
+
+ log.warning = ( _str: string ) => { method_called = true; };
+
+ new Sut( log, emitter );
+
+ emitter.emit( event_id );
+
+ expect( method_called ).to.be.true;
+ } );
+
+ it( 'context is retrieved from error', () =>
+ {
+ let method_called = false;
+
+ const event_id = 'error';
+ const err_msg = 'Foo';
+ const emitter = new EventEmitter();
+ const log = createMockLogger();
+ const err_context = { bar: 'baz' };
+
+ log.error = ( str: string, context: any ) =>
+ {
+ method_called = true;
+
+ expect( str ).to.equal( err_msg );
+ expect( context ).to.equal( err_context );
+ };
+
+ new Sut( log, emitter );
+
+ emitter.emit( event_id, context( new Error( err_msg ), err_context ) );
+
+ expect( method_called ).to.be.true;
+ } );
+} );
+
+
+function createMockLogger(): PsrLogger
+{
+ return <PsrLogger>{
+ debug( _msg: string | object, _context: object ){},
+ info( _msg: string | object, _context: object ){},
+ notice( _msg: string | object, _context: object ){ console.log( 'asdasd msg: ', _msg ); },
+ warning( _msg: string | object, _context: object ){},
+ error( _msg: string | object, _context: object ){},
+ critical( _msg: string | object, _context: object ){},
+ alert( _msg: string | object, _context: object ){},
+ emergency( _msg: string | object, _context: object ){},
+ log( _level: any, _msg: string | object, _context: object ){},
+ };
+} \ No newline at end of file
diff --git a/test/system/MetricsCollectorTest.ts b/test/system/MetricsCollectorTest.ts
index 07867a8..eafc77d 100644
--- a/test/system/MetricsCollectorTest.ts
+++ b/test/system/MetricsCollectorTest.ts
@@ -19,13 +19,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import { PrometheusFactory } from '../../src/system/PrometheusFactory';
+import {
+ PrometheusFactory,
+ PrometheusConfig,
+} from '../../src/system/PrometheusFactory';
import { Histogram, Pushgateway, Counter, Gauge } from 'prom-client';
import { EventEmitter } from 'events';
import { expect } from 'chai';
import {
MetricsCollector as Sut,
- PrometheusConfig,
MetricTimer,
} from '../../src/system/MetricsCollector';
@@ -35,8 +37,8 @@ describe( 'system.MetricsCollector captures events and pushes metrics', () =>
{
it( 'process-complete event is hooked', () =>
{
- let histogram_called = false;
- let counter_called = false;
+ let histogram_called = false;
+ let counter_called = false;
const emitter = new EventEmitter();
const conf = createMockConfig();
@@ -46,18 +48,20 @@ describe( 'system.MetricsCollector captures events and pushes metrics', () =>
counter_cb: () => { counter_called = true },
} );
- new Sut( factory, conf, emitter, timer );
+ const sut = new Sut( factory, conf, emitter, timer );
emitter.emit( 'delta-process-end' );
expect( histogram_called ).to.be.true;
expect( counter_called ).to.be.true;
+
+ sut.stop();
} );
it( 'process-error event is hooked', () =>
{
- let counter_called = false;
+ let counter_called = false;
const emitter = new EventEmitter();
const conf = createMockConfig();
@@ -66,11 +70,13 @@ describe( 'system.MetricsCollector captures events and pushes metrics', () =>
counter_cb: () => { counter_called = true },
} );
- new Sut( factory, conf, emitter, timer );
+ const sut = new Sut( factory, conf, emitter, timer );
emitter.emit( 'delta-process-error' );
expect( counter_called ).to.be.true;
+
+ sut.stop();
} );
@@ -80,7 +86,7 @@ describe( 'system.MetricsCollector captures events and pushes metrics', () =>
const uid = 'foo';
const start_time_ns = 1234;
const end_time_ns = 5678;
- const expected_ms = ( end_time_ns - start_time_ns ) / 1000;
+ const expected_ms = ( end_time_ns - start_time_ns ) / 1000000;
const emitter = new EventEmitter();
const conf = createMockConfig();
const timer = createMockTimer( start_time_ns, end_time_ns );
@@ -88,12 +94,14 @@ describe( 'system.MetricsCollector captures events and pushes metrics', () =>
histogram_cb: ( n: number ) => { actual_ms = n },
} );
- new Sut( factory, conf, emitter, timer );
+ const sut = new Sut( factory, conf, emitter, timer );
emitter.emit( 'delta-process-start', uid );
emitter.emit( 'delta-process-end', uid );
expect( actual_ms ).to.be.equal( expected_ms );
+
+ sut.stop();
} );
} );
diff --git a/test/system/StandardLoggerTest.ts b/test/system/StandardLoggerTest.ts
new file mode 100644
index 0000000..918bfd1
--- /dev/null
+++ b/test/system/StandardLoggerTest.ts
@@ -0,0 +1,178 @@
+/**
+ * Event logger test
+ *
+ * Copyright (C) 2010-2019 R-T Specialty, LLC.
+ *
+ * This file is part of the Liza Data Collection Framework.
+ *
+ * liza is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import { StandardLogger as Sut } from '../../src/system/StandardLogger';
+import { LogLevel } from '../../src/system/PsrLogger';
+import { expect } from 'chai';
+
+const sinon = require( 'sinon' );
+
+declare interface MockConsole extends Console {
+ getLevel(): string,
+ getStr(): string,
+}
+
+describe( 'system.EventLogger captures and logs events', () =>
+{
+ it( 'debug triggers console output level: info', () =>
+ {
+ const con = createMockConsole();
+ const env = 'test';
+ const sut = new Sut( con, ts_ctr, env );
+
+ sut.debug( 'Foo' );
+
+ expect( con.getLevel() ).to.equal( 'info' );
+ } );
+
+ it( 'info triggers console output level: info', () =>
+ {
+ const con = createMockConsole();
+ const env = 'test';
+ const sut = new Sut( con, ts_ctr, env );
+
+ sut.info( 'Foo' );
+
+ expect( con.getLevel() ).to.equal( 'info' );
+ } );
+
+ it( 'notice triggers console output level: log', () =>
+ {
+ const con = createMockConsole();
+ const env = 'test';
+ const sut = new Sut( con, ts_ctr, env );
+
+ sut.notice( 'Foo' );
+
+ expect( con.getLevel() ).to.equal( 'log' );
+ } );
+
+ it( 'warning triggers console output level: warn', () =>
+ {
+ const con = createMockConsole();
+ const env = 'test';
+ const sut = new Sut( con, ts_ctr, env );
+
+ sut.warning( 'Foo' );
+
+ expect( con.getLevel() ).to.equal( 'warn' );
+ } );
+
+ it( 'error triggers console output level: error', () =>
+ {
+ const con = createMockConsole();
+ const env = 'test';
+ const sut = new Sut( con, ts_ctr, env );
+
+ sut.error( 'Foo' );
+
+ expect( con.getLevel() ).to.equal( 'error' );
+ } );
+
+ it( 'critical triggers console output level: error', () =>
+ {
+ const con = createMockConsole();
+ const env = 'test';
+ const sut = new Sut( con, ts_ctr, env );
+
+ sut.critical( 'Foo' );
+
+ expect( con.getLevel() ).to.equal( 'error' );
+ } );
+
+ it( 'alert triggers console output level: error', () =>
+ {
+ const con = createMockConsole();
+ const env = 'test';
+ const sut = new Sut( con, ts_ctr, env );
+
+ sut.alert( 'Foo' );
+
+ expect( con.getLevel() ).to.equal( 'error' );
+ } );
+
+ it( 'emergency triggers console output level: error', () =>
+ {
+ const con = createMockConsole();
+ const env = 'test';
+ const sut = new Sut( con, ts_ctr, env );
+
+ sut.emergency( 'Foo' );
+
+ expect( con.getLevel() ).to.equal( 'error' );
+ } );
+
+ it( 'log triggers corresponding log level', () =>
+ {
+ const con = createMockConsole();
+ const env = 'test';
+ const sut = new Sut( con, ts_ctr, env );
+
+ sut.log( LogLevel.ERROR, 'Foo' );
+
+ expect( con.getLevel() ).to.equal( 'error' );
+ } );
+
+ it( 'Context is included in structured output', () =>
+ {
+ const con = createMockConsole();
+ const env = 'test';
+ const sut = new Sut( con, ts_ctr, env );
+ const context = { bar: 'baz' };
+ const expected_output = {
+ message: 'Foo',
+ timestamp: 123123,
+ service: 'quote-server',
+ env: 'test',
+ severity: 'NOTICE',
+ context: {
+ bar: 'baz',
+ },
+ };
+
+ sut.notice( 'Foo', context );
+
+ expect( con.getStr() ).to.deep.equal( expected_output );
+ } );
+} );
+
+
+function ts_ctr(): UnixTimestamp
+{
+ return <UnixTimestamp>123123;
+}
+
+
+function createMockConsole(): MockConsole
+{
+ const mock = sinon.mock( console );
+
+ mock.lvl = '';
+ mock.str = '';
+ mock.info = ( str: string ) => { mock.str = str; mock.lvl = 'info'; };
+ mock.log = ( str: string ) => { mock.str = str; mock.lvl = 'log'; };
+ mock.warn = ( str: string ) => { mock.str = str; mock.lvl = 'warn'; };
+ mock.error = ( str: string ) => { mock.str = str; mock.lvl = 'error'; };
+ mock.getLevel = () => mock.lvl;
+ mock.getStr = () => mock.str;
+
+ return mock;
+}