diff --git a/packages/@aws-cdk/cloudformation-diff/lib/diff/util.ts b/packages/@aws-cdk/cloudformation-diff/lib/diff/util.ts index 763afbecaf79e..f4c452499ee09 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/diff/util.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/diff/util.ts @@ -23,7 +23,8 @@ export function deepEqual(lvalue: any, rvalue: any): boolean { } // allows a numeric 10 and a literal "10" to be equivalent; // this is consistent with CloudFormation. - if (((typeof lvalue === 'string') || (typeof rvalue === 'string')) && (parseFloat(lvalue) === parseFloat(rvalue))) { + if ((typeof lvalue === 'string' || typeof rvalue === 'string') && + safeParseFloat(lvalue) === safeParseFloat(rvalue)) { return true; } if (typeof lvalue !== typeof rvalue) { return false; } @@ -132,3 +133,20 @@ export function unionOf(lv: string[] | Set, rv: string[] | Set): } return new Array(...result); } + +/** + * A parseFloat implementation that does the right thing for + * strings like '0.0.0' + * (for which JavaScript's parseFloat() returns 0). + */ +function safeParseFloat(str: string): number { + const ret = parseFloat(str); + if (ret === 0) { + // if the str is exactly '0', that's OK; + // but parseFloat() also returns 0 for things like '0.0'; + // in this case, return NaN, so we'll fall back to string comparison + return str === '0' ? ret : NaN; + } else { + return ret; + } +} diff --git a/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts b/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts index 8110922a41790..bde05ef09056e 100644 --- a/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts +++ b/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts @@ -375,6 +375,34 @@ test('adding and removing quotes from a numeric property causes no changes', () expect(differences.resources.differenceCount).toBe(0); }); +test('versions are correctly detected as not numbers', () => { + const currentTemplate = { + Resources: { + ImageBuilderComponent: { + Type: 'AWS::ImageBuilder::Component', + Properties: { + Platform: 'Linux', + Version: '0.0.1', + }, + }, + }, + }; + const newTemplate = { + Resources: { + ImageBuilderComponent: { + Type: 'AWS::ImageBuilder::Component', + Properties: { + Platform: 'Linux', + Version: '0.0.2', + }, + }, + }, + }; + + const differences = diffTemplate(currentTemplate, newTemplate); + expect(differences.resources.differenceCount).toBe(1); +}); + test('single element arrays are equivalent to the single element in DependsOn expressions', () => { // GIVEN const currentTemplate = {