Skip to content

Commit 8f037c3

Browse files
committed
proceed with implementation of dependency resolving
1 parent a86b767 commit 8f037c3

3 files changed

Lines changed: 126 additions & 43 deletions

File tree

lib/macro-manager.js

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,43 @@ function State(name, value) {
1414
this.name = name;
1515
this.value = value;
1616
this.providingMacro = null;
17+
this.toBeCalledOnRisingEdge = [];
18+
1719
this.setProvidingMacro = function (macro) {
1820
this.providingMacro = macro;
1921
};
22+
23+
this.registerWaitingMacro = function (waitingDoneCallback) {
24+
this.toBeCalledOnRisingEdge.push(waitingDoneCallback);
25+
};
26+
27+
this.notifyWaitingMacros = function () {
28+
var callback;
29+
while (this.toBeCalledOnRisingEdge.length > 0) {
30+
callback = this.toBeCalledOnRisingEdge.pop();
31+
callback();
32+
}
33+
};
34+
2035
this.ensureIsSet = function (done) {
2136
if (this.value === constants.STATE_NOT_SET) {
37+
this.value = constants.STATE_PENDING_SET;
38+
this.registerWaitingMacro(done);
39+
if (this.providingMacro) {
40+
this.providingMacro.execute(
41+
function () {
42+
stateInstance.notifyWaitingMacros();
43+
}
44+
);
45+
} else {
46+
console.log("Error: state requested but no provider set: " + name);
47+
}
48+
} else if (this.value === constants.STATE_PENDING_SET) {
2249
this.registerWaitingMacro(done);
23-
this.providingMacro(function () {this.notifyWaitingMacros();});
24-
} else if (stateInstance.value === constants.STATE_PENDING_SET) {
25-
// warten
2650
} else {
2751
done();
2852
}
2953
};
30-
31-
this.notifyWaitingMacros = function () {
32-
33-
};
3454
}
3555

3656
function StateManager() {
@@ -55,6 +75,10 @@ function StateManager() {
5575
state.value = stateValue;
5676
};
5777

78+
this.getStateByName = function (name) {
79+
return this.stateByName[name];
80+
};
81+
5882
this.getStateSummary = function () {
5983
var summary = {};
6084
var stateName;
@@ -123,6 +147,15 @@ function registerState(stateName) {
123147
virtualStates.registerState(stateName);
124148
}
125149

150+
function registerStateProvider(stateName) {
151+
virtualStates.registerStateProvider(stateName);
152+
}
153+
154+
function requestStateIsSet(callback, stateName) {
155+
var state = virtualStates.getStateByName(stateName);
156+
state.ensureIsSet(callback);
157+
}
158+
126159
function setStateByName(stateName, newState) {
127160
virtualStates.setStateByName(stateName, newState);
128161
}
@@ -136,7 +169,9 @@ function getDeviceByName(deviceName) {
136169
}
137170

138171
manager = {
172+
registerStateProvider: registerStateProvider,
139173
registerState: registerState,
174+
requestStateIsSet: requestStateIsSet,
140175
setStateByName: setStateByName,
141176
getCatchAllDevice: getCatchAllDevice,
142177
getDeviceByName: getDeviceByName,

lib/macro.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ function Macro(config, macroManager) {
125125

126126
this.registerStates = function () {
127127
if (this.isProvidingState()) {
128-
macroManager.registerState(config.provides);
128+
macroManager.registerStateProvider(config.provides);
129129
}
130130
if (this.isRequiringState()) {
131131
macroManager.registerState(config.requires);
@@ -137,7 +137,11 @@ function Macro(config, macroManager) {
137137

138138
this.execute = function (done) {
139139
this.callersCallback = done;
140-
this.macroClosureChain();
140+
if (this.isRequiringState()) {
141+
macroManager.requestStateIsSet(this.macroClosureChain, config.requires);
142+
} else {
143+
this.macroClosureChain();
144+
}
141145
};
142146

143147
this.macroClosureChain = this.createClosureChain();

test/lib/macro-manager.js

Lines changed: 78 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,6 @@ var CONFIG_DELAYED_HELLO_WORLD = [{
2121
],
2222
}];
2323

24-
var CONFIG_HELLO_STATES = [{
25-
name: 'hello!',
26-
provides: 'hello',
27-
sequence: [
28-
['say', 'hello'],
29-
],
30-
}, {
31-
name: 'world!',
32-
requires: 'hello',
33-
sequence: [
34-
['say', 'world'],
35-
],
36-
}, {
37-
name: 'goodbye!',
38-
resets: 'hello',
39-
sequence: [
40-
['say', 'goodbye'],
41-
],
42-
}, {
43-
name: 'something',
44-
resets: 'world',
45-
sequence: [
46-
['say', 'goodbye'],
47-
],
48-
}];
49-
5024
var CONFIG_HELLO = [
5125
{
5226
name: 'hello',
@@ -350,6 +324,32 @@ describe('macros', function () {
350324
});
351325

352326
describe('state', function () {
327+
var CONFIG_STATES = [{
328+
name: 'hello!',
329+
provides: 'hello',
330+
sequence: [
331+
['say', 'hello'],
332+
],
333+
}, {
334+
name: 'world!',
335+
requires: 'hello',
336+
sequence: [
337+
['say', 'world'],
338+
],
339+
}, {
340+
name: 'goodbye!',
341+
resets: 'hello',
342+
sequence: [
343+
['say', 'goodbye'],
344+
],
345+
}, {
346+
name: 'something',
347+
resets: 'world',
348+
sequence: [
349+
['say', 'goodbye'],
350+
],
351+
}];
352+
353353
describe('set, reset and query', function () {
354354
beforeEach(function () {
355355
resetMockAndFixture();
@@ -361,27 +361,27 @@ describe('macros', function () {
361361
});
362362

363363
it('should deliver current states as key value map', function () {
364-
macros.init(CONFIG_HELLO_STATES);
364+
macros.init(CONFIG_STATES);
365365
assert.deepEqual(macros.getCurrentStates(), { hello: 'clear', world: 'clear' });
366366
});
367367

368368
it('should set state after execution', function () {
369-
macros.init(CONFIG_HELLO_STATES);
369+
macros.init(CONFIG_STATES);
370370
assert.deepEqual(macros.getCurrentStates(),
371371
{ hello: 'clear', world: 'clear' }, 'not called');
372-
macros.execute(CONFIG_HELLO_STATES[0].name);
372+
macros.execute(CONFIG_STATES[0].name);
373373
clock.tick(51);
374374
assert.deepEqual(macros.getCurrentStates(),
375375
{ hello: 'set', world: 'clear' }, 'macro called');
376376
});
377377

378378
it('should reset state after execution', function () {
379-
macros.init(CONFIG_HELLO_STATES);
380-
macros.execute(CONFIG_HELLO_STATES[0].name);
379+
macros.init(CONFIG_STATES);
380+
macros.execute(CONFIG_STATES[0].name);
381381
clock.tick(51);
382382
assert.deepEqual(macros.getCurrentStates(), { hello: 'set', world: 'clear' },
383383
'state set called');
384-
macros.execute(CONFIG_HELLO_STATES[2].name);
384+
macros.execute(CONFIG_STATES[2].name);
385385
clock.tick(51);
386386
assert.deepEqual(macros.getCurrentStates(), { hello: 'clear', world: 'clear' },
387387
'state reset called');
@@ -396,7 +396,30 @@ describe('macros', function () {
396396
});
397397
});
398398

399+
// TODO validation of providers, requesters, resetters and deniers:
400+
// providers and deniers need match!
401+
399402
describe('dependency call', function () {
403+
var CONFIG_MULTI_STATES = [{
404+
name: 'Lamp',
405+
provides: 'light',
406+
sequence: [
407+
['say', 'shiny'],
408+
],
409+
}, {
410+
name: 'he',
411+
requires: 'light',
412+
sequence: [
413+
['say', 'uh'],
414+
],
415+
}, {
416+
name: 'she',
417+
requires: 'light',
418+
sequence: [
419+
['say', 'ah'],
420+
],
421+
}];
422+
400423
beforeEach(function () {
401424
resetMockAndFixture();
402425
clock = sinon.useFakeTimers();
@@ -407,14 +430,35 @@ describe('macros', function () {
407430
});
408431

409432
it.skip('should call macro if state is requested', function () {
410-
macros.init(CONFIG_HELLO_STATES);
411-
macros.execute(CONFIG_HELLO_STATES[1].name);
433+
macros.init(CONFIG_STATES);
434+
macros.execute(CONFIG_STATES[1].name);
412435
clock.tick(51);
413436
assert.deepEqual(deviceMock.operations,
414437
[['say', 'hello'], ['say', 'world']], 'calls are not done as expected');
415438
assert.deepEqual(macros.getCurrentStates(), { hello: true, world: false },
416439
'states are not set as required');
417440
});
441+
442+
it.skip('should call a macro only once, if two triggered macros request it simultaneously',
443+
function () {
444+
macros.init(CONFIG_MULTI_STATES);
445+
macros.execute(CONFIG_MULTI_STATES[1].name);
446+
clock.tick(20);
447+
macros.execute(CONFIG_MULTI_STATES[2].name);
448+
clock.tick(131);
449+
assert.deepEqual(deviceMock.operations,
450+
[['say', 'shiny'], ['say', 'uh'], ['say', 'ah']], 'calls are not done as expected');
451+
assert.deepEqual(macros.getCurrentStates(), { hello: true, world: false },
452+
'states are not set as required');
453+
}
454+
);
455+
456+
it.skip('should call multiple macros if multiple states are requested', function () {
457+
macros.init(CONFIG_MULTI_STATES);
458+
macros.execute(CONFIG_MULTI_STATES[1].name);
459+
clock.tick(51);
460+
// TODO
461+
});
418462
});
419463
});
420464
});

0 commit comments

Comments
 (0)