Skip to content

Commit c39a877

Browse files
authored
Add dockerfile based tests for azure-sdk-for-js and office-ui-fabric-react (microsoft#31948)
* Add dockerfile based tests * Update tests/cases/docker/README.md Co-Authored-By: Nathan Shively-Sanders <[email protected]> * Combine sanitize functions * Add some debugging instructions to README * Fix listed command order
1 parent 36df28d commit c39a877

File tree

11 files changed

+706
-1
lines changed

11 files changed

+706
-1
lines changed

.dockerignore

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
node_modules
2+
.node_modules
3+
built/*
4+
test-args.txt
5+
~*.docx
6+
\#*\#
7+
.\#*
8+
src/harness/*.js
9+
src/compiler/diagnosticInformationMap.generated.ts
10+
src/compiler/diagnosticMessages.generated.json
11+
src/parser/diagnosticInformationMap.generated.ts
12+
src/parser/diagnosticMessages.generated.json
13+
rwc-report.html
14+
*.swp
15+
build.json
16+
*.actual
17+
*.config
18+
scripts/debug.bat
19+
scripts/run.bat
20+
scripts/word2md.js
21+
scripts/buildProtocol.js
22+
scripts/ior.js
23+
scripts/authors.js
24+
scripts/configurePrerelease.js
25+
scripts/open-user-pr.js
26+
scripts/open-cherry-pick-pr.js
27+
scripts/processDiagnosticMessages.d.ts
28+
scripts/processDiagnosticMessages.js
29+
scripts/produceLKG.js
30+
scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js
31+
scripts/generateLocalizedDiagnosticMessages.js
32+
scripts/*.js.map
33+
scripts/typings/
34+
coverage/
35+
internal/
36+
**/.DS_Store
37+
.settings
38+
**/.vs
39+
.idea
40+
yarn.lock
41+
yarn-error.log
42+
.parallelperf.*
43+
.failed-tests
44+
TEST-results.xml
45+
package-lock.json
46+
tests
47+
.vscode
48+
.git

.npmignore

+2
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ package-lock.json
2929
yarn.lock
3030
CONTRIBUTING.md
3131
TEST-results.xml
32+
.dockerignore
33+
Dockerfile

Dockerfile

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# We use this dockerfile to build a packed tarfile which we import in our `docker` tests
2+
FROM node:current
3+
COPY . /typescript
4+
WORKDIR /typescript
5+
RUN npm install
6+
RUN npm i -g gulp-cli
7+
RUN gulp configure-insiders && gulp LKG && gulp clean && npm pack .

src/harness/runnerbase.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
type TestRunnerKind = CompilerTestKind | FourslashTestKind | "project" | "rwc" | "test262" | "user" | "dt";
1+
type TestRunnerKind = CompilerTestKind | FourslashTestKind | "project" | "rwc" | "test262" | "user" | "dt" | "docker";
22
type CompilerTestKind = "conformance" | "compiler";
33
type FourslashTestKind = "fourslash" | "fourslash-shims" | "fourslash-shims-pp" | "fourslash-server";
44

src/testRunner/externalCompileRunner.ts

+71
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,77 @@ ${stripAbsoluteImportPaths(result.stderr.toString().replace(/\r\n/g, "\n"))}`;
106106
}
107107
}
108108

109+
class DockerfileRunner extends ExternalCompileRunnerBase {
110+
readonly testDir = "tests/cases/docker/";
111+
kind(): TestRunnerKind {
112+
return "docker";
113+
}
114+
initializeTests(): void {
115+
// Read in and evaluate the test list
116+
const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles();
117+
118+
// tslint:disable-next-line:no-this-assignment
119+
const cls = this;
120+
describe(`${this.kind()} code samples`, function(this: Mocha.ISuiteCallbackContext) {
121+
this.timeout(cls.timeout); // 20 minutes
122+
before(() => {
123+
cls.exec("docker", ["build", ".", "-t", "typescript/typescript"], { cwd: Harness.IO.getWorkspaceRoot() }); // cached because workspace is hashed to determine cacheability
124+
});
125+
for (const test of testList) {
126+
const directory = typeof test === "string" ? test : test.file;
127+
const cwd = path.join(Harness.IO.getWorkspaceRoot(), cls.testDir, directory);
128+
it(`should build ${directory} successfully`, () => {
129+
const imageName = `tstest/${directory}`;
130+
cls.exec("docker", ["build", "--no-cache", ".", "-t", imageName], { cwd }); // --no-cache so the latest version of the repos referenced is always fetched
131+
const cp: typeof import("child_process") = require("child_process");
132+
Harness.Baseline.runBaseline(`${cls.kind()}/${directory}.log`, cls.report(cp.spawnSync(`docker`, ["run", imageName], { cwd, timeout: cls.timeout, shell: true })));
133+
});
134+
}
135+
});
136+
}
137+
138+
private timeout = 1_200_000; // 20 minutes;
139+
private exec(command: string, args: string[], options: { cwd: string, timeout?: number }): void {
140+
const cp: typeof import("child_process") = require("child_process");
141+
const stdio = isWorker ? "pipe" : "inherit";
142+
const res = cp.spawnSync(command, args, { timeout: this.timeout, shell: true, stdio, ...options });
143+
if (res.status !== 0) {
144+
throw new Error(`${command} ${args.join(" ")} for ${options.cwd} failed: ${res.stderr && res.stderr.toString()}`);
145+
}
146+
}
147+
report(result: ExecResult) {
148+
// tslint:disable-next-line:no-null-keyword
149+
return result.status === 0 && !result.stdout.length && !result.stderr.length ? null : `Exit Code: ${result.status}
150+
Standard output:
151+
${sanitizeDockerfileOutput(result.stdout.toString())}
152+
153+
154+
Standard error:
155+
${sanitizeDockerfileOutput(result.stderr.toString())}`;
156+
}
157+
}
158+
159+
function sanitizeDockerfileOutput(result: string): string {
160+
return stripAbsoluteImportPaths(sanitizeTimestamps(stripANSIEscapes(normalizeNewlines(result))));
161+
}
162+
163+
function normalizeNewlines(result: string): string {
164+
return result.replace(/\r\n/g, "\n");
165+
}
166+
167+
function stripANSIEscapes(result: string): string {
168+
return result.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "");
169+
}
170+
171+
function sanitizeTimestamps(result: string): string {
172+
return result.replace(/\[\d?\d:\d\d:\d\d (A|P)M\]/g, "[XX:XX:XX XM]")
173+
.replace(/\d+(\.\d+)? seconds?/g, "? seconds")
174+
.replace(/\d+(\.\d+)? minutes?/g, "")
175+
.replace(/\d+(\.\d+)?s/g, "?s")
176+
.replace(/\d+.\d+.\d+-insiders.\d\d\d\d\d\d\d\d/g, "X.X.X-insiders.xxxxxxxx");
177+
}
178+
179+
109180
/**
110181
* Import types and some other error messages use absolute paths in errors as they have no context to be written relative to;
111182
* This is problematic for error baselines, so we grep for them and strip them out.

src/testRunner/runner.ts

+6
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ function createRunner(kind: TestRunnerKind): RunnerBase {
4040
return new UserCodeRunner();
4141
case "dt":
4242
return new DefinitelyTypedRunner();
43+
case "docker":
44+
return new DockerfileRunner();
4345
}
4446
return ts.Debug.fail(`Unknown runner kind ${kind}`);
4547
}
@@ -172,6 +174,9 @@ function handleTestConfig() {
172174
case "dt":
173175
runners.push(new DefinitelyTypedRunner());
174176
break;
177+
case "docker":
178+
runners.push(new DockerfileRunner());
179+
break;
175180
}
176181
}
177182
}
@@ -194,6 +199,7 @@ function handleTestConfig() {
194199
// CRON-only tests
195200
if (process.env.TRAVIS_EVENT_TYPE === "cron") {
196201
runners.push(new UserCodeRunner());
202+
runners.push(new DockerfileRunner());
197203
}
198204
}
199205
if (runUnitTests === undefined) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
Exit Code: 1
2+
Standard output:
3+
4+
5+
Rush Multi-Project Build Tool 5.7.3 - https://rushjs.io
6+
7+
8+
Starting "rush rebuild"
9+
10+
Executing a maximum of 1 simultaneous processes...
11+
12+
[@azure/abort-controller] started
13+
1 of 18: [@azure/abort-controller] completed successfully in ? seconds
14+
[@azure/cosmos] started
15+
2 of 18: [@azure/cosmos] completed successfully in ? seconds
16+
[@azure/event-hubs] started
17+
3 of 18: [@azure/event-hubs] completed successfully in ? seconds
18+
[@azure/service-bus] started
19+
Warning: You have changed the public API signature for this project. Updating review/service-bus.api.md
20+
[@azure/storage-blob] started
21+
5 of 18: [@azure/storage-blob] completed successfully in ? seconds
22+
[@azure/storage-datalake] started
23+
6 of 18: [@azure/storage-datalake] completed successfully in ? seconds
24+
[@azure/storage-file] started
25+
7 of 18: [@azure/storage-file] completed successfully in ? seconds
26+
[@azure/storage-queue] started
27+
8 of 18: [@azure/storage-queue] completed successfully in ? seconds
28+
[@azure/template] started
29+
9 of 18: [@azure/template] completed successfully in ? seconds
30+
[@azure/core-http] started
31+
10 of 18: [@azure/core-http] completed successfully in ? seconds
32+
[@azure/core-paging] started
33+
11 of 18: [@azure/core-paging] completed successfully in ? seconds
34+
[@azure/event-processor-host] started
35+
12 of 18: [@azure/event-processor-host] completed successfully in ? seconds
36+
[testhub] started
37+
13 of 18: [testhub] completed successfully in ? seconds
38+
[@azure/identity] started
39+
14 of 18: [@azure/identity] completed successfully in ? seconds
40+
[@azure/core-amqp] started
41+
[@azure/keyvault-certificates] started
42+
15 of 18: [@azure/keyvault-certificates] completed successfully in ? seconds
43+
[@azure/keyvault-keys] started
44+
16 of 18: [@azure/keyvault-keys] completed successfully in ? seconds
45+
[@azure/keyvault-secrets] started
46+
17 of 18: [@azure/keyvault-secrets] completed successfully in ? seconds
47+
48+
SUCCESS (16)
49+
================================
50+
@azure/abort-controller (? seconds)
51+
@azure/core-http (? seconds)
52+
@azure/core-paging (? seconds)
53+
@azure/cosmos (? seconds)
54+
@azure/event-hubs (? seconds)
55+
@azure/event-processor-host (? seconds)
56+
@azure/identity (? seconds)
57+
@azure/keyvault-certificates (? seconds)
58+
@azure/keyvault-keys (? seconds)
59+
@azure/keyvault-secrets (? seconds)
60+
@azure/storage-blob (? seconds)
61+
@azure/storage-datalake (? seconds)
62+
@azure/storage-file (? seconds)
63+
@azure/storage-queue (? seconds)
64+
@azure/template (? seconds)
65+
testhub (? seconds)
66+
================================
67+
68+
SUCCESS WITH WARNINGS (1)
69+
================================
70+
@azure/service-bus (? seconds)
71+
Warning: You have changed the public API signature for this project. Updating review/service-bus.api.md
72+
================================
73+
74+
FAILURE (1)
75+
================================
76+
@azure/core-amqp (? seconds)
77+
>>> @azure/core-amqp
78+
tsc -p . && rollup -c 2>&1
79+
src/errors.ts(579,20): error TS7053: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'typeof ConditionErrorNameMapper'.
80+
src/errors.ts(600,34): error TS7053: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'typeof SystemErrorConditionMapper'.
81+
src/errors.ts(601,20): error TS7053: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'typeof ConditionErrorNameMapper'.
82+
================================
83+
84+
85+
Error: Project(s) failed to build
86+
rush rebuild - Errors! ( ? seconds)
87+
88+
89+
90+
Standard error:
91+
Your version of Node.js (12.4.0) has not been tested with this release of Rush. The Rush team will not accept issue reports for it. Please consider upgrading Rush or downgrading Node.js.
92+
4 of 18: [@azure/service-bus] completed with warnings in ? seconds
93+
94+
14 of 18: [@azure/core-amqp] failed to build!
95+
[@azure/core-amqp] Returned error code: 2

0 commit comments

Comments
 (0)