Skip to content

Commit f7571a8

Browse files
feat(benchmarks): replace regex with ts (#149)
Co-authored-by: Nico Serrano <nnicosp@hotmail.com>
1 parent 47a2f32 commit f7571a8

17 files changed

Lines changed: 426 additions & 385 deletions

File tree

Lines changed: 46 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,119 +1,59 @@
1-
import { beforeAll, describe, expect, it } from "vitest";
2-
3-
import { resolve } from "node:path";
4-
5-
import type { Entry } from "./types.js";
6-
7-
import {
8-
extractEtherscanUrls,
9-
findProtocolConstantsFiles,
10-
hasEtherscanExample,
11-
hasSolUrl,
12-
hasSolUrlWithLineNumber,
13-
parseConstantsFile,
14-
} from "./utils.js";
1+
import { describe, expect, it } from "vitest";
2+
3+
import { readdirSync } from "node:fs";
4+
import { join, resolve } from "node:path";
5+
6+
import { FLUIDKEY_CONFIG } from "../fluidkey/constants.js";
7+
import { HINKAL_CONFIG } from "../hinkal/constants.js";
8+
import { INTMAX_CONFIG } from "../intmax/constants.js";
9+
import { PRIVACY_POOLS_CONFIG } from "../privacy-pools/constants.js";
10+
import { RAILGUN_CONFIG } from "../railgun/constants.js";
11+
import { TORNADO_CASH_CONFIG } from "../tornado-cash/constants.js";
12+
13+
const PROTOCOL_CONFIGS = [
14+
{ name: "fluidkey", config: FLUIDKEY_CONFIG },
15+
{ name: "hinkal", config: HINKAL_CONFIG },
16+
{ name: "intmax", config: INTMAX_CONFIG },
17+
{ name: "privacy-pools", config: PRIVACY_POOLS_CONFIG },
18+
{ name: "railgun", config: RAILGUN_CONFIG },
19+
{ name: "tornado-cash", config: TORNADO_CASH_CONFIG },
20+
];
21+
22+
/** Directories excluded from protocol config checks */
23+
const EXCLUDED_DIRS = new Set(["__tests__", "utils", "monero"]);
1524

1625
describe("constants.ts files", () => {
17-
let files: Entry[] = [];
18-
19-
beforeAll(() => {
20-
const srcDir = resolve(__dirname, "..");
21-
22-
const filePaths = findProtocolConstantsFiles(srcDir);
23-
24-
files = filePaths.map((filePath) => ({
25-
filePath,
26-
...parseConstantsFile(filePath),
27-
}));
28-
});
29-
30-
it("should have at least one contract address", () => {
31-
files
32-
.filter(({ filePath }) => !filePath.includes("monero"))
33-
.forEach(({ filePath, addresses }) => {
34-
expect(
35-
addresses.length,
36-
`${filePath} must have at least one contract address (Address-typed constant)`,
37-
).toBeGreaterThanOrEqual(1);
38-
});
39-
});
40-
41-
it("should have at least two events array", () => {
42-
files
43-
.filter(({ filePath }) => !filePath.includes("monero"))
44-
.forEach(({ filePath, events }) => {
45-
expect(
46-
events.length,
47-
`${filePath} must have at least two events arrays (array with parseAbiItem calls)`,
48-
).toBeGreaterThanOrEqual(2);
49-
});
50-
});
51-
52-
it("should have a URL to a .sol source file for each contract address", () => {
53-
files.forEach(({ filePath, addresses }) => {
54-
addresses.forEach(({ name, comment }) => {
55-
expect(hasSolUrl(comment), `JSDoc for ${name} in ${filePath} must have a URL ending in .sol`).toBe(true);
56-
});
26+
it("should have a config entry for every protocol directory with a constants.ts file", () => {
27+
const srcDirectory = resolve(__dirname, "..");
28+
const allDirectories = readdirSync(srcDirectory, { withFileTypes: true })
29+
.filter((entry) => entry.isDirectory() && !EXCLUDED_DIRS.has(entry.name))
30+
.map((entry) => entry.name);
31+
32+
const protocolDirectories = allDirectories.filter((directory) => {
33+
const protocolDirectoryPath = join(srcDirectory, directory);
34+
const files = readdirSync(protocolDirectoryPath);
35+
return files.includes("constants.ts");
5736
});
58-
});
5937

60-
it("should have a URL to a .sol source file with line reference for each events array indicating the function that emits the events", () => {
61-
files.forEach(({ filePath, events }) => {
62-
events.forEach(({ name, comment }) => {
63-
expect(
64-
hasSolUrlWithLineNumber(comment),
65-
`JSDoc for ${name} in ${filePath} must have a URL to a .sol file with a line reference (e.g., #L123 or start=30)`,
66-
).toBe(true);
67-
});
68-
});
69-
});
38+
const configuredNames = new Set(PROTOCOL_CONFIGS.map(({ name }) => name));
39+
const missing = protocolDirectories.filter((directory) => !configuredNames.has(directory));
7040

71-
it("should have a Emits: section describing all events for each events array", () => {
72-
files.forEach(({ filePath, events }) => {
73-
events.forEach(({ name, arrayEventCount, emitsEventCount }) => {
74-
expect(
75-
emitsEventCount,
76-
`JSDoc for ${name} in ${filePath} must describe all ${arrayEventCount} event(s) in the Emits: section`,
77-
).toBe(arrayEventCount);
78-
});
79-
});
41+
expect(missing, `Missing PROTOCOL_CONFIGS entries for: ${missing.join(", ")}`).toHaveLength(0);
8042
});
8143

82-
it("should have an Example: section with an etherscan transaction URL for each events array", () => {
83-
files.forEach(({ filePath, events }) => {
84-
events.forEach(({ name, comment }) => {
85-
expect(
86-
hasEtherscanExample(comment),
87-
`JSDoc for ${name} in ${filePath} must contain an etherscan.io/tx/0x123... example URL`,
88-
).toBe(true);
89-
});
44+
it("should have at least two distinct event arrays per protocol", () => {
45+
PROTOCOL_CONFIGS.forEach(({ name, config }) => {
46+
const uniqueEventArrays = new Set(config.operations.map(({ events }) => events));
47+
expect(uniqueEventArrays.size, `${name} must have at least two distinct event arrays`).toBeGreaterThanOrEqual(2);
9048
});
9149
});
9250

93-
it("should not repeat etherscan URL examples across events arrays", () => {
94-
const allUrls: string[] = [];
95-
const urlToLocations: Record<string, string[] | undefined> = {};
96-
97-
files.forEach(({ filePath, events }) => {
98-
events.forEach(({ name, comment }) => {
99-
const urls = extractEtherscanUrls(comment);
100-
urls.forEach((url) => {
101-
allUrls.push(url);
102-
if (!urlToLocations[url]) {
103-
urlToLocations[url] = [];
104-
}
105-
urlToLocations[url].push(`${filePath} (${name})`);
106-
});
107-
});
108-
});
109-
110-
const duplicates = Object.entries(urlToLocations)
111-
.filter(([, locations]) => locations && locations.length > 1)
112-
.map(([url, locations]) => `${url} found in: ${locations?.join(", ")}`);
51+
it("should not repeat example transaction URLs across operations", () => {
52+
const allExampleTxUrls = PROTOCOL_CONFIGS.flatMap(({ config }) =>
53+
config.operations.map(({ exampleTxUrl }) => exampleTxUrl),
54+
);
55+
const uniqueExampleTxUrls = new Set(allExampleTxUrls);
11356

114-
expect(
115-
duplicates,
116-
`Etherscan URLs must not be repeated across events arrays:\n${duplicates.join("\n")}`,
117-
).toHaveLength(0);
57+
expect(uniqueExampleTxUrls.size, "Duplicate example transaction URLs found").toBe(allExampleTxUrls.length);
11858
});
11959
});

gas-benchmarks/src/__tests__/types.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

gas-benchmarks/src/__tests__/utils.ts

Lines changed: 0 additions & 110 deletions
This file was deleted.

0 commit comments

Comments
 (0)