Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Gerwitz <gerwitzm@lovullo.com>2017-01-30 00:06:08 -0500
committerMike Gerwitz <gerwitzm@lovullo.com>2017-01-30 00:29:25 -0500
commit0dcbd3220250ab889472d92433b24470d8a5e051 (patch)
tree4790c92d9ebfbab6009766c27b6dada7b8e7b4a5
parent28d74d70685e0824b5895979d7603587c87b651b (diff)
downloadliza-0dcbd3220250ab889472d92433b24470d8a5e051.tar.gz
liza-0dcbd3220250ab889472d92433b24470d8a5e051.tar.bz2
liza-0dcbd3220250ab889472d92433b24470d8a5e051.zip
DataValidator: accept classification results
* src/validate/DataValidator.js (validate): New `classes' parameter. API BC break from previous commits. (populateStore, updateFailures): Generalize methods. * test/validate/DataValidatorTest.js: Add associated test. Refactor existing tests to adhere to new API/expectations. DEV-2206
-rw-r--r--src/validate/DataValidator.js65
-rw-r--r--test/validate/DataValidatorTest.js74
2 files changed, 102 insertions, 37 deletions
diff --git a/src/validate/DataValidator.js b/src/validate/DataValidator.js
index fa56ec6..2d613f5 100644
--- a/src/validate/DataValidator.js
+++ b/src/validate/DataValidator.js
@@ -56,10 +56,10 @@ module.exports = Class( 'DataValidator',
'private _factory': null,
/**
- * Bucket diff store
- * @type {Store}
+ * Various layers of the diff store
+ * @type {Object}
*/
- 'private _store_factory': null,
+ 'private _stores': {},
/**
@@ -96,7 +96,7 @@ module.exports = Class( 'DataValidator',
*/
'private _createStores': function( store_factory )
{
- this._bucket_store = store_factory();
+ this._stores = store_factory();
},
@@ -112,24 +112,28 @@ module.exports = Class( 'DataValidator',
* @return {Promise} accepts with unspecified value once field monitor
* has completed its update
*/
- 'public validate'( diff, validatef )
+ 'public validate'( diff, classes, validatef )
{
const _self = this;
let failures = {};
- _self._bucket_validator.validate( diff, ( name, value, i ) =>
+ if ( diff !== undefined )
{
- diff[ name ][ i ] = undefined;
+ _self._bucket_validator.validate( diff, ( name, value, i ) =>
+ {
+ diff[ name ][ i ] = undefined;
- ( failures[ name ] = failures[ name ] || {} )[ i ] =
- _self._factory.createFieldFailure( name, i, value );
- }, true );
+ ( failures[ name ] = failures[ name ] || {} )[ i ] =
+ _self._factory.createFieldFailure( name, i, value );
+ }, true );
- validatef && validatef( diff, failures );
+ validatef && validatef( diff, failures );
+ }
// XXX: this assumes that the above is synchronous
- return this.updateFailures( diff, failures );
+ return this._populateStore( classes, this._stores.cstore, 'indexes' )
+ .then( () => this.updateFailures( diff, failures ) );
},
@@ -146,36 +150,39 @@ module.exports = Class( 'DataValidator',
*/
'public updateFailures'( diff, failures )
{
- const _self = this;
-
- return this._populateStore( diff ).then( () =>
- {
- return _self._field_monitor.update(
- _self._bucket_store, failures
- );
- } );
+ return this._populateStore( diff, this._stores.bstore ).then( () =>
+ this._field_monitor.update(
+ this._stores.store, failures
+ )
+ );
},
/**
- * Populate store with diff
+ * Populate store with data
*
* This effectively converts a basic array into a `Store`. This is
* surprisingly performant on v8. If the stores mix in traits, there
* may be a slight performance hit for trait-overridden methods.
*
- * @param {Object} diff bucket diff
+ * @param {Object} data data to map onto store
*
* @return {Promise} when all items have been added to the store
*/
- 'private _populateStore'( diff )
+ 'private _populateStore'( data, store, subkey )
{
- var bstore = this._bucket_store;
+ if ( data === undefined )
+ {
+ return Promise.resolve( [] );
+ }
- return Promise.all(
- Object.keys( diff ).map(
- key => bstore.add( key, diff[ key ] )
- )
- );
+ const mapf = ( subkey !== undefined )
+ ? key => store.add( key, data[ key ][ subkey ] )
+ : key => store.add( key, data[ key ] );
+
+ return store.clear()
+ .then( () => Promise.all(
+ Object.keys( data ).map( mapf )
+ ) );
},
} );
diff --git a/test/validate/DataValidatorTest.js b/test/validate/DataValidatorTest.js
index 62478ee..f01eb0f 100644
--- a/test/validate/DataValidatorTest.js
+++ b/test/validate/DataValidatorTest.js
@@ -56,7 +56,11 @@ describe( 'DataValidator', () =>
const vmonitor = ValidStateMonitor();
const dep_factory = createMockDependencyFactory();
- const getStore = createStubStore();
+
+ const getStore = createStubStore();
+ const { bstore } = getStore();
+
+ const mock_bstore = sinon.mock( bstore );
const mock_vmonitor = sinon.mock( vmonitor );
const mock_dep_factory = sinon.mock( dep_factory );
@@ -68,9 +72,10 @@ describe( 'DataValidator', () =>
foo: { 1: expected_failure }
};
+ // call to actual validator
mock_vmonitor.expects( 'update' )
.once()
- .withExactArgs( getStore(), expected_failures )
+ .withExactArgs( getStore().store, expected_failures )
.returns( Promise.resolve( undefined ) );
mock_dep_factory.expects( 'createFieldFailure' )
@@ -78,6 +83,11 @@ describe( 'DataValidator', () =>
.withExactArgs( 'foo', 1, expected_value )
.returns( expected_failure );
+ // clears previous diffs
+ mock_bstore.expects( 'clear' )
+ .once()
+ .returns( Promise.resolve( bstore ) );
+
return Sut( bvalidator, vmonitor, dep_factory, getStore )
.validate( diff )
.then( () =>
@@ -86,12 +96,54 @@ describe( 'DataValidator', () =>
mock_dep_factory.verify();
// cleared on call to err in above mock validator
- return expect( getStore().get( 'foo' ) )
+ return expect( getStore().bstore.get( 'foo' ) )
.to.eventually.deep.equal( [ 'a', undefined, 'c' ] );
} );
} );
+ it( 'merges classification changes with diff', () =>
+ {
+ // SUT will only care about the indexes
+ const classes = {
+ first: { indexes: [], is: false },
+ second: { indexes: [ 0, 1 ], is: true },
+ };
+
+ const bvalidator = createMockBucketValidator();
+ const vmonitor = ValidStateMonitor();
+ const dep_factory = createMockDependencyFactory();
+
+ const getStore = createStubStore();
+ const { cstore } = getStore();
+
+ const mock_cstore = sinon.mock( cstore );
+
+ // clears previous diffs
+ mock_cstore.expects( 'clear' )
+ .once()
+ .returns( Promise.resolve( cstore ) );
+
+ return Sut( bvalidator, vmonitor, dep_factory, getStore )
+ .validate( {}, classes )
+ .then( () =>
+ {
+ // clear should have been called
+ mock_cstore.verify();
+
+ // keep in mind that we are using MemoryStore for this
+ // test (whereas a real implementation would probably be
+ // using a DiffStore)
+ return Promise.all(
+ Object.keys( classes ).map( key =>
+ expect( cstore.get( key ) )
+ .to.eventually.deep.equal( classes[ key ].indexes )
+ )
+ );
+ } );
+ } );
+
+
it( 'considers failures from external validator', () =>
{
const expected_failure = {};
@@ -130,7 +182,7 @@ describe( 'DataValidator', () =>
sinon.mock( vmonitor )
.expects( 'update' )
.once()
- .withExactArgs( getStore(), expected_failures )
+ .withExactArgs( getStore().store, expected_failures )
.returns( Promise.resolve( undefined ) );
sinon.mock( dep_factory )
@@ -138,13 +190,13 @@ describe( 'DataValidator', () =>
.returns( expected_failure );
return Sut( bvalidator, vmonitor, dep_factory, getStore )
- .validate( diff, validatef );
+ .validate( diff, {}, validatef );
} );
it( 'rejects if field monitor update rejects', () =>
{
- const bvalidator = createMockBucketValidator( ( x, y, z ) => {} );
+ const bvalidator = createMockBucketValidator();
const vmonitor = ValidStateMonitor();
const dep_factory = createMockDependencyFactory();
@@ -166,6 +218,8 @@ describe( 'DataValidator', () =>
function createMockBucketValidator( validatef )
{
+ validatef = validatef || ( ( x, y, z ) => {} );
+
return BucketDataValidator.extend(
{
'override public validate': validatef,
@@ -186,7 +240,11 @@ function createMockDependencyFactory( map )
function createStubStore()
{
- const store = MemoryStore();
+ const stores = {
+ store: MemoryStore(),
+ bstore: MemoryStore(),
+ cstore: MemoryStore(),
+ };
- return () => store;
+ return () => stores;
}