Skip to content

Commit

Permalink
Merge branch 'main' into asset_support
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] committed Dec 28, 2022
2 parents 400d4bd + 6975a7e commit 6c76ac3
Show file tree
Hide file tree
Showing 88 changed files with 2,816 additions and 726 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.v2.alpha.md
Expand Up @@ -2,6 +2,13 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [2.57.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.56.1-alpha.0...v2.57.0-alpha.0) (2022-12-27)


### Bug Fixes

* **aws-redshift:** Columns are not dropped on removal from array ([#23011](https://github.com/aws/aws-cdk/issues/23011)) ([2981313](https://github.com/aws/aws-cdk/commit/298131312b513c0e73865e6fff74c189ee99e328)), closes [#22208](https://github.com/aws/aws-cdk/issues/22208)

## [2.56.1-alpha.0](https://github.com/aws/aws-cdk/compare/v2.56.0-alpha.0...v2.56.1-alpha.0) (2022-12-23)

## [2.56.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.55.1-alpha.0...v2.56.0-alpha.0) (2022-12-21)
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.v2.md
Expand Up @@ -2,6 +2,21 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [2.57.0](https://github.com/aws/aws-cdk/compare/v2.56.1...v2.57.0) (2022-12-27)


### Features

* **cfnspec:** cloudformation spec v103.0.0 ([#23452](https://github.com/aws/aws-cdk/issues/23452)) ([e49e57d](https://github.com/aws/aws-cdk/commit/e49e57d3106f62c5d64c428cba73b4107d664cba))
* **lambda:** add support for auto-instrumentation with ADOT Lambda layer ([#23027](https://github.com/aws/aws-cdk/issues/23027)) ([fc70535](https://github.com/aws/aws-cdk/commit/fc70535fe699e72332d5ddb4543308e76a89594a))


### Bug Fixes

* **cfnspec:** v101.0.0 introduced specific types on several types that previously were typed as json ([#23448](https://github.com/aws/aws-cdk/issues/23448)) ([4fbc182](https://github.com/aws/aws-cdk/commit/4fbc1827b8978262da0b5b77b1ee9bc0ecfdcc3e))
* **codedeploy:** referenced Applications are not environment-aware ([#23405](https://github.com/aws/aws-cdk/issues/23405)) ([96242d7](https://github.com/aws/aws-cdk/commit/96242d73c0ae853524a567aece86f8a8a514495c))
* **s3:** buckets with SSE-KMS silently fail to receive logs ([#23385](https://github.com/aws/aws-cdk/issues/23385)) ([1b7a384](https://github.com/aws/aws-cdk/commit/1b7a384c330d168d64c0cd82118e5b5473d08a67))

## [2.56.1](https://github.com/aws/aws-cdk/compare/v2.56.0...v2.56.1) (2022-12-23)


Expand Down
131 changes: 100 additions & 31 deletions packages/@aws-cdk/assertions/lib/match.ts
@@ -1,5 +1,7 @@
import { Matcher, MatchResult } from './matcher';
import { AbsentMatch } from './private/matchers/absent';
import { sortKeyComparator } from './private/sorting';
import { SparseMatrix } from './private/sparse-matrix';
import { getType } from './private/type';

/**
Expand Down Expand Up @@ -196,18 +198,53 @@ class ArrayMatch extends Matcher {
message: `Expected type array but received ${getType(actual)}`,
});
}
if (!this.subsequence && this.pattern.length !== actual.length) {
return new MatchResult(actual).recordFailure({

return this.subsequence ? this.testSubsequence(actual) : this.testFullArray(actual);
}

private testFullArray(actual: Array<any>): MatchResult {
const result = new MatchResult(actual);

let i = 0;
for (; i < this.pattern.length && i < actual.length; i++) {
const patternElement = this.pattern[i];
const matcher = Matcher.isMatcher(patternElement)
? patternElement
: new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects });

const innerResult = matcher.test(actual[i]);
result.compose(`${i}`, innerResult);
}

if (i < this.pattern.length) {
result.recordFailure({
matcher: this,
path: [],
message: `Expected array of length ${this.pattern.length} but received ${actual.length}`,
message: `Not enough elements in array (expecting ${this.pattern.length}, got ${actual.length})`,
path: [`${i}`],
});
}
if (i < actual.length) {
result.recordFailure({
matcher: this,
message: `Too many elements in array (expecting ${this.pattern.length}, got ${actual.length})`,
path: [`${i}`],
});
}

return result;
}

private testSubsequence(actual: Array<any>): MatchResult {
const result = new MatchResult(actual);

// For subsequences, there is a lot of testing and backtracking that happens
// here, keep track of it all so we can report in a sensible amount of
// detail on what we did if the match happens to fail.

let patternIdx = 0;
let actualIdx = 0;
const matches = new SparseMatrix<MatchResult>();

const result = new MatchResult(actual);
while (patternIdx < this.pattern.length && actualIdx < actual.length) {
const patternElement = this.pattern[patternIdx];

Expand All @@ -216,30 +253,59 @@ class ArrayMatch extends Matcher {
: new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects });

const matcherName = matcher.name;
if (this.subsequence && (matcherName == 'absent' || matcherName == 'anyValue')) {
if (matcherName == 'absent' || matcherName == 'anyValue') {
// array subsequence matcher is not compatible with anyValue() or absent() matcher. They don't make sense to be used together.
throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`);
}

const innerResult = matcher.test(actual[actualIdx]);
matches.set(patternIdx, actualIdx, innerResult);

if (!this.subsequence || !innerResult.hasFailed()) {
result.compose(`[${actualIdx}]`, innerResult);
actualIdx++;
if (innerResult.isSuccess) {
result.compose(`${actualIdx}`, innerResult); // Record any captures
patternIdx++;
actualIdx++;
} else {
actualIdx++;
}
}

for (; patternIdx < this.pattern.length; patternIdx++) {
const pattern = this.pattern[patternIdx];
const element = (Matcher.isMatcher(pattern) || typeof pattern === 'object') ? ' ' : ` [${pattern}] `;
result.recordFailure({
matcher: this,
path: [],
message: `Missing element${element}at pattern index ${patternIdx}`,
});
// If we haven't matched all patterns:
// - Report on each one that did match on where it matched (perhaps it was wrong)
// - Report the closest match for the failing one
if (patternIdx < this.pattern.length) {
// Succeeded Pattern Index
for (let spi = 0; spi < patternIdx; spi++) {
const foundMatch = matches.row(spi).find(([, r]) => r.isSuccess);
if (!foundMatch) { continue; } // Should never fail but let's be defensive

const [index] = foundMatch;

result.compose(`${index}`, new MatchResult(actual[index]).recordFailure({
matcher: this,
message: `arrayWith pattern ${spi} matched here`,
path: [],
cost: 0, // This is an informational message so it would be unfair to assign it cost
}));
}

const failedMatches = matches.row(patternIdx);
failedMatches.sort(sortKeyComparator(([i, r]) => [r.failCost, i]));
if (failedMatches.length > 0) {
const [index, innerResult] = failedMatches[0];
result.recordFailure({
matcher: this,
message: `Could not match arrayWith pattern ${patternIdx}. This is the closest match`,
path: [`${index}`],
cost: 0, // Informational message
});
result.compose(`${index}`, innerResult);
} else {
// The previous matcher matched at the end of the pattern and we didn't even get to try anything
result.recordFailure({
matcher: this,
message: `Could not match arrayWith pattern ${patternIdx}. No more elements to try`,
path: [`${actual.length}`],
});
}
}

return result;
Expand Down Expand Up @@ -288,8 +354,8 @@ class ObjectMatch extends Matcher {
if (!(a in this.pattern)) {
result.recordFailure({
matcher: this,
path: [`/${a}`],
message: 'Unexpected key',
path: [a],
message: `Unexpected key ${a}`,
});
}
}
Expand All @@ -299,16 +365,16 @@ class ObjectMatch extends Matcher {
if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) {
result.recordFailure({
matcher: this,
path: [`/${patternKey}`],
message: `Missing key '${patternKey}' among {${Object.keys(actual).join(',')}}`,
path: [patternKey],
message: `Missing key '${patternKey}'`,
});
continue;
}
const matcher = Matcher.isMatcher(patternVal) ?
patternVal :
new LiteralMatch(this.name, patternVal, { partialObjects: this.partial });
const inner = matcher.test(actual[patternKey]);
result.compose(`/${patternKey}`, inner);
result.compose(patternKey, inner);
}

return result;
Expand All @@ -324,35 +390,38 @@ class SerializedJson extends Matcher {
};

public test(actual: any): MatchResult {
const result = new MatchResult(actual);
if (getType(actual) !== 'string') {
result.recordFailure({
return new MatchResult(actual).recordFailure({
matcher: this,
path: [],
message: `Expected JSON as a string but found ${getType(actual)}`,
});
return result;
}
let parsed;
try {
parsed = JSON.parse(actual);
} catch (err) {
if (err instanceof SyntaxError) {
result.recordFailure({
return new MatchResult(actual).recordFailure({
matcher: this,
path: [],
message: `Invalid JSON string: ${actual}`,
});
return result;
} else {
throw err;
}
}

const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern);
const innerResult = matcher.test(parsed);
result.compose(`(${this.name})`, innerResult);
return result;
if (innerResult.hasFailed()) {
innerResult.recordFailure({
matcher: this,
path: [],
message: 'Encoded JSON value does not match',
});
}
return innerResult;
}
}

Expand Down

0 comments on commit 6c76ac3

Please sign in to comment.