Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(iotevents): support comparison operators #19329

Merged
merged 9 commits into from
Apr 8, 2022
12 changes: 6 additions & 6 deletions packages/@aws-cdk/aws-iotevents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,20 @@ const coldState = new iotevents.State({
stateName: 'cold',
});

// transit to coldState when temperature is 10
// transit to coldState when temperature is less than 15
warmState.transitionTo(coldState, {
eventName: 'to_coldState', // optional property, default by combining the names of the States
when: iotevents.Expression.eq(
when: iotevents.Expression.lt(
iotevents.Expression.inputAttribute(input, 'payload.temperature'),
iotevents.Expression.fromString('10'),
iotevents.Expression.fromString('15'),
),
executing: [new actions.LambdaInvokeAction(func)], // optional
});
// transit to warmState when temperature is 20
// transit to warmState when temperature is greater than or equal to 15
coldState.transitionTo(warmState, {
when: iotevents.Expression.eq(
when: iotevents.Expression.gte(
iotevents.Expression.inputAttribute(input, 'payload.temperature'),
iotevents.Expression.fromString('20'),
iotevents.Expression.fromString('15'),
),
});

Expand Down
44 changes: 43 additions & 1 deletion packages/@aws-cdk/aws-iotevents/lib/expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,55 @@ export abstract class Expression {
return new BinaryOperationExpression(left, '==', right);
}

/**
* Create a expression for the Not Equal operator.
*/
public static neq(left: Expression, right: Expression): Expression {
return new BinaryOperationExpression(left, '!=', right);
}

/**
* Create a expression for the Less Than operator.
*/
public static lt(left: Expression, right: Expression): Expression {
return new BinaryOperationExpression(left, '<', right);
}

/**
* Create a expression for the Less Than Or Equal operator.
*/
public static lte(left: Expression, right: Expression): Expression {
return new BinaryOperationExpression(left, '<=', right);
}

/**
* Create a expression for the Greater Than operator.
*/
public static gt(left: Expression, right: Expression): Expression {
return new BinaryOperationExpression(left, '>', right);
}

/**
* Create a expression for the Greater Than Or Equal operator.
*/
public static gte(left: Expression, right: Expression): Expression {
return new BinaryOperationExpression(left, '>=', right);
}

/**
* Create a expression for the AND operator.
*/
public static and(left: Expression, right: Expression): Expression {
return new BinaryOperationExpression(left, '&&', right);
}

/**
* Create a expression for the OR operator.
*/
public static or(left: Expression, right: Expression): Expression {
return new BinaryOperationExpression(left, '||', right);
}

constructor() {
}

Expand Down Expand Up @@ -70,6 +112,6 @@ class BinaryOperationExpression extends Expression {
}

public evaluate() {
return `${this.left.evaluate()} ${this.operator} ${this.right.evaluate()}`;
return `(${this.left.evaluate()} ${this.operator} ${this.right.evaluate()})`;
yamatatsu marked this conversation as resolved.
Show resolved Hide resolved
}
}
114 changes: 18 additions & 96 deletions packages/@aws-cdk/aws-iotevents/test/detector-model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ test('can set states with transitions', () => {
TransitionEvents: [{
EventName: 'firstState_to_secondState',
NextState: 'secondState',
Condition: '$input.test-input.payload.temperature == 12',
Condition: '($input.test-input.payload.temperature == 12)',
}],
},
},
Expand All @@ -356,12 +356,12 @@ test('can set states with transitions', () => {
{
EventName: 'secondToFirst',
NextState: 'firstState',
Condition: '$input.test-input.payload.temperature == 21',
Condition: '($input.test-input.payload.temperature == 21)',
},
{
EventName: 'secondState_to_thirdState',
NextState: 'thirdState',
Condition: '$input.test-input.payload.temperature == 23',
Condition: '($input.test-input.payload.temperature == 23)',
},
],
},
Expand Down Expand Up @@ -498,14 +498,26 @@ test('cannot create transitions that transit to duprecated target state', () =>
});

describe('Expression', () => {
test('currentInput', () => {
const E = iotevents.Expression;
test.each([
['currentInput', (_input: iotevents.IInput) => E.currentInput(_input), 'currentInput("test-input")'],
['inputAttribute', (_input: iotevents.IInput) => E.inputAttribute(_input, 'json.path'), '$input.test-input.json.path'],
yamatatsu marked this conversation as resolved.
Show resolved Hide resolved
['eq', () => E.eq(E.fromString('"aaa"'), E.fromString('"bbb"')), '("aaa" == "bbb")'],
['neq', () => E.neq(E.fromString('"aaa"'), E.fromString('"bbb"')), '("aaa" != "bbb")'],
['lt', () => E.lt(E.fromString('5'), E.fromString('2')), '(5 < 2)'],
['lte', () => E.lte(E.fromString('5'), E.fromString('2')), '(5 <= 2)'],
['gt', () => E.gt(E.fromString('5'), E.fromString('2')), '(5 > 2)'],
['gte', () => E.gte(E.fromString('5'), E.fromString('2')), '(5 >= 2)'],
['and', () => E.and(E.fromString('true'), E.fromString('false')), '(true && false)'],
['or', () => E.or(E.fromString('true'), E.fromString('false')), '(true || false)'],
])('%s', (_, getExpression, expectedCondition) => {
// WHEN
new iotevents.DetectorModel(stack, 'MyDetectorModel', {
initialState: new iotevents.State({
stateName: 'test-state',
onEnter: [{
eventName: 'test-eventName',
condition: iotevents.Expression.currentInput(input),
condition: getExpression(input),
}],
}),
});
Expand All @@ -517,97 +529,7 @@ describe('Expression', () => {
Match.objectLike({
OnEnter: {
Events: [Match.objectLike({
Condition: 'currentInput("test-input")',
})],
},
}),
],
},
});
});

test('inputAttribute', () => {
// WHEN
new iotevents.DetectorModel(stack, 'MyDetectorModel', {
initialState: new iotevents.State({
stateName: 'test-state',
onEnter: [{
eventName: 'test-eventName',
condition: iotevents.Expression.inputAttribute(input, 'json.path'),
}],
}),
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', {
DetectorModelDefinition: {
States: [
Match.objectLike({
OnEnter: {
Events: [Match.objectLike({
Condition: '$input.test-input.json.path',
})],
},
}),
],
},
});
});

test('eq', () => {
// WHEN
new iotevents.DetectorModel(stack, 'MyDetectorModel', {
initialState: new iotevents.State({
stateName: 'test-state',
onEnter: [{
eventName: 'test-eventName',
condition: iotevents.Expression.eq(
iotevents.Expression.fromString('"aaa"'),
iotevents.Expression.fromString('"bbb"'),
),
}],
}),
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', {
DetectorModelDefinition: {
States: [
Match.objectLike({
OnEnter: {
Events: [Match.objectLike({
Condition: '"aaa" == "bbb"',
})],
},
}),
],
},
});
});

test('eq', () => {
// WHEN
new iotevents.DetectorModel(stack, 'MyDetectorModel', {
initialState: new iotevents.State({
stateName: 'test-state',
onEnter: [{
eventName: 'test-eventName',
condition: iotevents.Expression.and(
iotevents.Expression.fromString('true'),
iotevents.Expression.fromString('false'),
),
}],
}),
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', {
DetectorModelDefinition: {
States: [
Match.objectLike({
OnEnter: {
Events: [Match.objectLike({
Condition: 'true && false',
Condition: expectedCondition,
})],
},
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@
"Fn::Join": [
"",
[
"currentInput(\"",
"(currentInput(\"",
{
"Ref": "MyInput08947B23"
},
"\") && $input.",
"\") && ($input.",
{
"Ref": "MyInput08947B23"
},
".payload.temperature == 31.5"
".payload.temperature == 31.5))"
]
]
},
Expand All @@ -70,11 +70,11 @@
"Fn::Join": [
"",
[
"$input.",
"($input.",
{
"Ref": "MyInput08947B23"
},
".payload.temperature == 31.7"
".payload.temperature == 31.7)"
]
]
},
Expand All @@ -89,11 +89,11 @@
"Fn::Join": [
"",
[
"$input.",
"($input.",
{
"Ref": "MyInput08947B23"
},
".payload.temperature == 31.6"
".payload.temperature == 31.6)"
]
]
},
Expand All @@ -106,11 +106,11 @@
"Fn::Join": [
"",
[
"$input.",
"($input.",
{
"Ref": "MyInput08947B23"
},
".payload.temperature == 12"
".payload.temperature == 12)"
]
]
},
Expand All @@ -129,11 +129,11 @@
"Fn::Join": [
"",
[
"$input.",
"($input.",
{
"Ref": "MyInput08947B23"
},
".payload.temperature == 21"
".payload.temperature == 21)"
]
]
},
Expand Down