From 642580f9d0af33af182fd29fe2dc37a9c6e72efb Mon Sep 17 00:00:00 2001 From: Albert Cheng Date: Thu, 7 Dec 2023 16:47:27 -0800 Subject: [PATCH 1/3] tsv drive letter inconsistency & regression unit test --- eng/tools/typespec-validation/src/utils.ts | 6 +- .../test/npm-prefix.test.ts | 67 +++++++++++++++++++ .../typespec-validation/test/tsv-test-host.ts | 2 + .../typespec-validation/test/util.test.ts | 4 +- 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 eng/tools/typespec-validation/test/npm-prefix.test.ts diff --git a/eng/tools/typespec-validation/src/utils.ts b/eng/tools/typespec-validation/src/utils.ts index 862bf7cf2d2a..1ce8c6ab2a35 100644 --- a/eng/tools/typespec-validation/src/utils.ts +++ b/eng/tools/typespec-validation/src/utils.ts @@ -23,5 +23,9 @@ export async function checkFileExists(file: string) { } export function normalizePath(folder: string) { - return path.resolve(folder).split(path.sep).join("/"); + return path + .resolve(folder) + .split(path.sep) + .join("/") + .replace(/^[a-zA-Z]:/g, ""); } diff --git a/eng/tools/typespec-validation/test/npm-prefix.test.ts b/eng/tools/typespec-validation/test/npm-prefix.test.ts new file mode 100644 index 000000000000..3f3148c692c7 --- /dev/null +++ b/eng/tools/typespec-validation/test/npm-prefix.test.ts @@ -0,0 +1,67 @@ +import { NpmPrefixRule } from "../src/rules/npm-prefix.js"; +import { IGitOperation, TsvTestHost } from "./tsv-test-host.js"; +import { strict as assert } from "node:assert"; + +describe("npm-prefix", function () { + it("should succeed if node returns inconsistent drive letter capitalization", async function () { + let host = new TsvTestHost(); + host.runCmd = async (cmd: string, _cwd: string): Promise<[Error | null, string, string]> => { + if (cmd.includes("npm prefix")) { + return [null, "C:\\Git\\azure-rest-api-specs", ""]; + } else { + return [null, "", ""]; + } + }; + host.gitOperation = (_folder: string): IGitOperation => { + return { + status: () => { + return Promise.resolve({ + modified: [], + isClean: () => true, + }); + }, + diff: () => { + return Promise.resolve(""); + }, + revparse: () => { + return Promise.resolve("c:/Git/azure-rest-api-specs"); + }, + }; + }; + + const result = await new NpmPrefixRule().execute(host, TsvTestHost.folder); + + assert(result.success); + }); + + it("should fail if npm prefix mismatch", async function () { + let host = new TsvTestHost(); + host.runCmd = async (cmd: string, _cwd: string): Promise<[Error | null, string, string]> => { + if (cmd.includes("npm prefix")) { + return [null, "/Git/azure-rest-api-specs/specification/foo", ""]; + } else { + return [null, "", ""]; + } + }; + host.gitOperation = (_folder: string): IGitOperation => { + return { + status: () => { + return Promise.resolve({ + modified: [], + isClean: () => true, + }); + }, + diff: () => { + return Promise.resolve(""); + }, + revparse: () => { + return Promise.resolve("/Git/azure-rest-api-specs"); + }, + }; + }; + + const result = await new NpmPrefixRule().execute(host, TsvTestHost.folder); + + assert(!result.success); + }); +}); diff --git a/eng/tools/typespec-validation/test/tsv-test-host.ts b/eng/tools/typespec-validation/test/tsv-test-host.ts index 049c1d2c025f..3bde65fcb5ea 100644 --- a/eng/tools/typespec-validation/test/tsv-test-host.ts +++ b/eng/tools/typespec-validation/test/tsv-test-host.ts @@ -1,6 +1,8 @@ import { IGitOperation, TsvHost } from "../src/tsv-host.js"; import { normalizePath } from "../src/utils.js"; +export { IGitOperation } from "../src/tsv-host.js"; + export class TsvTestHost implements TsvHost { static get folder() { return "specification/foo/Foo"; diff --git a/eng/tools/typespec-validation/test/util.test.ts b/eng/tools/typespec-validation/test/util.test.ts index ff63c25cbac4..48c95727ed87 100644 --- a/eng/tools/typespec-validation/test/util.test.ts +++ b/eng/tools/typespec-validation/test/util.test.ts @@ -12,13 +12,13 @@ describe("normalize", function () { it("should succeed if /foo/bar/ is normalized", async function () { let host = new TsvTestHost(); - const result = host.normalizePath("/foo/bar/").replace(/^[a-zA-Z]:/g, ""); + const result = host.normalizePath("/foo/bar/"); assert(result === "/foo/bar"); }); it("should succeed if /foo/bar is normalized", async function () { let host = new TsvTestHost(); - const result = host.normalizePath("/foo/bar").replace(/^[a-zA-Z]:/g, ""); + const result = host.normalizePath("/foo/bar"); assert(result === "/foo/bar"); }); }); From 8ec715857707aa6b5f32d1d1444945384e54d33b Mon Sep 17 00:00:00 2001 From: Albert Date: Thu, 7 Dec 2023 17:58:53 -0800 Subject: [PATCH 2/3] update test suite for linux --- eng/tools/typespec-validation/src/utils.ts | 2 +- eng/tools/typespec-validation/test/npm-prefix.test.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/eng/tools/typespec-validation/src/utils.ts b/eng/tools/typespec-validation/src/utils.ts index 1ce8c6ab2a35..e27d235bd37b 100644 --- a/eng/tools/typespec-validation/src/utils.ts +++ b/eng/tools/typespec-validation/src/utils.ts @@ -27,5 +27,5 @@ export function normalizePath(folder: string) { .resolve(folder) .split(path.sep) .join("/") - .replace(/^[a-zA-Z]:/g, ""); + .replace(/[a-zA-Z]:/g, ""); } diff --git a/eng/tools/typespec-validation/test/npm-prefix.test.ts b/eng/tools/typespec-validation/test/npm-prefix.test.ts index 3f3148c692c7..787a2f63bec9 100644 --- a/eng/tools/typespec-validation/test/npm-prefix.test.ts +++ b/eng/tools/typespec-validation/test/npm-prefix.test.ts @@ -1,13 +1,14 @@ import { NpmPrefixRule } from "../src/rules/npm-prefix.js"; import { IGitOperation, TsvTestHost } from "./tsv-test-host.js"; import { strict as assert } from "node:assert"; +import path from "path"; describe("npm-prefix", function () { it("should succeed if node returns inconsistent drive letter capitalization", async function () { let host = new TsvTestHost(); host.runCmd = async (cmd: string, _cwd: string): Promise<[Error | null, string, string]> => { if (cmd.includes("npm prefix")) { - return [null, "C:\\Git\\azure-rest-api-specs", ""]; + return [null, `C:${path.sep}Git${path.sep}azure-rest-api-specs`, ""]; } else { return [null, "", ""]; } From 3a0d49ec990df55ad85892bb0c940ebca6e20adf Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Thu, 14 Dec 2023 08:29:46 +0000 Subject: [PATCH 3/3] Normalize drive letter, add PlatformPath to tests --- eng/tools/typespec-validation/src/utils.ts | 6 ++--- .../test/npm-prefix.test.ts | 2 +- .../typespec-validation/test/tsv-test-host.ts | 9 ++++++- .../typespec-validation/test/util.test.ts | 27 +++++++++++-------- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/eng/tools/typespec-validation/src/utils.ts b/eng/tools/typespec-validation/src/utils.ts index e27d235bd37b..9675a63882e3 100644 --- a/eng/tools/typespec-validation/src/utils.ts +++ b/eng/tools/typespec-validation/src/utils.ts @@ -1,6 +1,6 @@ import { access } from "fs/promises"; import { exec } from "child_process"; -import path from "path"; +import defaultPath, { PlatformPath } from "path"; export async function runCmd(cmd: string, cwd: string) { console.log(`run command:${cmd}`); @@ -22,10 +22,10 @@ export async function checkFileExists(file: string) { .catch(() => false); } -export function normalizePath(folder: string) { +export function normalizePath(folder: string, path: PlatformPath = defaultPath) { return path .resolve(folder) .split(path.sep) .join("/") - .replace(/[a-zA-Z]:/g, ""); + .replace(/^([a-z]):/, (_match, driveLetter) => driveLetter.toUpperCase() + ":"); } diff --git a/eng/tools/typespec-validation/test/npm-prefix.test.ts b/eng/tools/typespec-validation/test/npm-prefix.test.ts index 787a2f63bec9..4808151d7236 100644 --- a/eng/tools/typespec-validation/test/npm-prefix.test.ts +++ b/eng/tools/typespec-validation/test/npm-prefix.test.ts @@ -5,7 +5,7 @@ import path from "path"; describe("npm-prefix", function () { it("should succeed if node returns inconsistent drive letter capitalization", async function () { - let host = new TsvTestHost(); + let host = new TsvTestHost(path.win32); host.runCmd = async (cmd: string, _cwd: string): Promise<[Error | null, string, string]> => { if (cmd.includes("npm prefix")) { return [null, `C:${path.sep}Git${path.sep}azure-rest-api-specs`, ""]; diff --git a/eng/tools/typespec-validation/test/tsv-test-host.ts b/eng/tools/typespec-validation/test/tsv-test-host.ts index 3bde65fcb5ea..3e846e5856b5 100644 --- a/eng/tools/typespec-validation/test/tsv-test-host.ts +++ b/eng/tools/typespec-validation/test/tsv-test-host.ts @@ -1,9 +1,16 @@ import { IGitOperation, TsvHost } from "../src/tsv-host.js"; import { normalizePath } from "../src/utils.js"; +import defaultPath, { PlatformPath } from "path"; export { IGitOperation } from "../src/tsv-host.js"; export class TsvTestHost implements TsvHost { + path: PlatformPath; + + constructor(path: PlatformPath = defaultPath) { + this.path = path; + } + static get folder() { return "specification/foo/Foo"; } @@ -38,7 +45,7 @@ export class TsvTestHost implements TsvHost { } normalizePath(folder: string): string { - return normalizePath(folder); + return normalizePath(folder, this.path); } async readTspConfig(_folder: string): Promise { diff --git a/eng/tools/typespec-validation/test/util.test.ts b/eng/tools/typespec-validation/test/util.test.ts index 48c95727ed87..3afb4c7c8183 100644 --- a/eng/tools/typespec-validation/test/util.test.ts +++ b/eng/tools/typespec-validation/test/util.test.ts @@ -1,24 +1,29 @@ -import { TsvTestHost } from "./tsv-test-host.js"; +import { normalizePath } from "../src/utils.js"; import { strict as assert } from "node:assert"; import process from "process"; +import path from "path"; describe("normalize", function () { it("should succeed if normalized . and normalized cwd matches", async function () { - let host = new TsvTestHost(); - const dotResult = host.normalizePath("."); - const cwdResult = host.normalizePath(process.cwd()); + const dotResult = normalizePath("."); + const cwdResult = normalizePath(process.cwd()); assert(dotResult === cwdResult); }); it("should succeed if /foo/bar/ is normalized", async function () { - let host = new TsvTestHost(); - const result = host.normalizePath("/foo/bar/"); - assert(result === "/foo/bar"); + const result = normalizePath("/foo/bar/", path.posix); + assert.equal(result, "/foo/bar"); }); - it("should succeed if /foo/bar is normalized", async function () { - let host = new TsvTestHost(); - const result = host.normalizePath("/foo/bar"); - assert(result === "/foo/bar"); + it("should normalize windows drive letter", async function () { + const lowerResult = normalizePath("c:\\foo\\bar", path.win32); + const upperResult = normalizePath("C:\\foo\\bar", path.win32); + assert.equal(lowerResult, upperResult); + }); + + it("should distinguish different windows drive letters", async function () { + const lowerResult = normalizePath("c:\\foo\\bar", path.win32); + const upperResult = normalizePath("d:\\foo\\bar", path.win32); + assert.notEqual(lowerResult, upperResult); }); });