diff --git a/Cargo.lock b/Cargo.lock index 89a16ce8e05..e750e4a9f7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -131,9 +131,9 @@ checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "6c6b2562119bf28c3439f7f02db99faf0aa1a8cdfe5772a2ee155d32227239f0" dependencies = [ "libc", ] @@ -378,13 +378,13 @@ checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.2.16", "windows-sys 0.48.0", ] @@ -396,9 +396,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", "miniz_oxide", @@ -554,9 +554,9 @@ checksum = "2c785eefb63ebd0e33416dfcb8d6da0bf27ce752843a45632a67bf10d4d4b5c4" [[package]] name = "insta" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa511b2e298cd49b1856746f6bb73e17036bcd66b25f5e92cdcdbec9bd75686" +checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc" dependencies = [ "console", "lazy_static", diff --git a/docs/docs/02-concepts/05-simulator.md b/docs/docs/02-concepts/05-simulator.md index f03312360de..1c028dca775 100644 --- a/docs/docs/02-concepts/05-simulator.md +++ b/docs/docs/02-concepts/05-simulator.md @@ -94,6 +94,34 @@ const response = await fn.invoke("hello!"); console.log(response); ``` +### Interacting with the simulation across processes + +The simulator also exposes an HTTP server that can be used to interact with the +simulated application from other processes. To get the URL of the simulator's +HTTP server, access `sim.url` after the simulator has started. + +```typescript +declare const sim: testing.Simulator; + +// ...after the simulator has started + +const url = sim.url; +console.log(url); + +const handleId = sim.getResourceConfig("root/Default/cloud.Bucket").attrs.handle; +console.log(handleId); +``` + +In another process, a client can be generated to interact with the simulator. Internally it will behave the same as the resource client, but it will use HTTP requests to communicate with the simulator. + +```typescript +import { cloud, testing } from '@winglang/sdk'; + +const bucket = testing.makeSimulatorClient("WING_SIMULATOR_URL", "HANDLE_ID") as cloud.IBucketClient; +const response = await bucket.get("my-key"); +console.log(response); +``` + ### Debugging Finally, when you want to understand how Wing resources are working, you may diff --git a/docs/docs/04-standard-library/02-ex/redis.md b/docs/docs/04-standard-library/02-ex/redis.md index 3e2931a868a..ed06856a79e 100644 --- a/docs/docs/04-standard-library/02-ex/redis.md +++ b/docs/docs/04-standard-library/02-ex/redis.md @@ -36,7 +36,6 @@ new ex.Redis(); | get | Get value at given key. | | hget | Returns the value associated with field in the hash stored at key. | | hset | Sets the specified field to respective value in the hash stored at key. | -| rawClient | Get raw redis client (currently IoRedis). | | sadd | Add the specified members to the set stored at key. | | set | Set key value pair. | | smembers | Returns all the members of the set value stored at key. | @@ -132,14 +131,6 @@ value to set at field in key. --- -##### `rawClient` - -```wing -inflight rawClient(): any -``` - -Get raw redis client (currently IoRedis). - ##### `sadd` ```wing @@ -263,7 +254,6 @@ new ex.RedisClientBase(); | get | Get value at given key. | | hget | Returns the value associated with field in the hash stored at key. | | hset | Sets the specified field to respective value in the hash stored at key. | -| rawClient | Get raw redis client (currently IoRedis). | | sadd | Add the specified members to the set stored at key. | | set | Set key value pair. | | smembers | Returns all the members of the set value stored at key. | @@ -345,14 +335,6 @@ Sets the specified field to respective value in the hash stored at key. --- -##### `rawClient` - -```wing -rawClient(): any -``` - -Get raw redis client (currently IoRedis). - ##### `sadd` ```wing diff --git a/examples/tests/sdk_tests/bucket/delete.test.w b/examples/tests/sdk_tests/bucket/delete.test.w index 9572072f123..e8324b13f16 100644 --- a/examples/tests/sdk_tests/bucket/delete.test.w +++ b/examples/tests/sdk_tests/bucket/delete.test.w @@ -9,7 +9,7 @@ test "delete" { try { block(); } catch actual { - assert(actual == expected); + assert(actual.contains(expected)); error = true; } assert(error); @@ -34,4 +34,4 @@ test "delete" { b.delete("file2.txt"); assert(!b.exists("file2.txt")); -} \ No newline at end of file +} diff --git a/examples/tests/sdk_tests/bucket/metadata.test.w b/examples/tests/sdk_tests/bucket/metadata.test.w index 3584614b0ec..6bb88233bfd 100644 --- a/examples/tests/sdk_tests/bucket/metadata.test.w +++ b/examples/tests/sdk_tests/bucket/metadata.test.w @@ -5,13 +5,14 @@ let b = new cloud.Bucket(); test "metadata" { b.put("test1.txt", "Foo"); - assert(b.metadata("test1.txt").size == 3); - assert(b.metadata("test1.txt").contentType == "application/octet-stream"); - assert(b.metadata("test1.txt").lastModified.year >= 2023); + let metadata = b.metadata("test1.txt"); + assert(metadata.size == 3); + assert(metadata.contentType == "application/octet-stream"); + assert(metadata.lastModified.year >= 2023); try { b.metadata("no-such-file.txt").lastModified; } catch e { - assert(e == "Object does not exist (key=no-such-file.txt)."); + assert(e.contains("Object does not exist (key=no-such-file.txt).")); } } diff --git a/examples/tests/sdk_tests/bucket/public_url.test.w b/examples/tests/sdk_tests/bucket/public_url.test.w index 94d8d8d240d..3d151dbe528 100644 --- a/examples/tests/sdk_tests/bucket/public_url.test.w +++ b/examples/tests/sdk_tests/bucket/public_url.test.w @@ -11,7 +11,7 @@ test "publicUrl" { try { block(); } catch actual { - assert(actual == expected); + assert(actual.contains(expected)); error = true; } assert(error); @@ -33,4 +33,4 @@ test "publicUrl" { assertThrows(BUCKET_NOT_PUBLIC_ERROR, () => { privateBucket.publicUrl("file2.txt"); }); -} \ No newline at end of file +} diff --git a/examples/tests/sdk_tests/queue/push.test.w b/examples/tests/sdk_tests/queue/push.test.w index e6837594ea7..ed80133ed0a 100644 --- a/examples/tests/sdk_tests/queue/push.test.w +++ b/examples/tests/sdk_tests/queue/push.test.w @@ -17,14 +17,14 @@ new std.Test(inflight () => { q.push(""); assert(false); } catch e { - assert(e == "Empty messages are not allowed"); + assert(e.contains("Empty messages are not allowed")); } try { q.push("Foo", ""); assert(false); } catch e { - assert(e == "Empty messages are not allowed"); + assert(e.contains("Empty messages are not allowed")); } q.push("Foo"); @@ -47,4 +47,4 @@ new std.Test(inflight () => { assert(util.waitUntil((): bool => { return q.approxSize() == 3; })); -}, { timeout: 3m }) as "push"; \ No newline at end of file +}, { timeout: 3m }) as "push"; diff --git a/examples/tests/sdk_tests/schedule/on_tick.test.w b/examples/tests/sdk_tests/schedule/on_tick.test.w index dc682bd5412..00b27d8c13f 100644 --- a/examples/tests/sdk_tests/schedule/on_tick.test.w +++ b/examples/tests/sdk_tests/schedule/on_tick.test.w @@ -7,27 +7,23 @@ let from_rate = new cloud.Schedule( rate: 1m ) as "from_rate"; let c1 = new cloud.Counter() as "c1"; let c2 = new cloud.Counter() as "c2"; - from_cron.onTick(inflight () => { - c1.inc(); + c1.inc(); }); from_rate.onTick(inflight () => { - c2.inc(); + c2.inc(); }); - -// std.Test is used setting the timeout property new std.Test(inflight () => { - // counters start at zero - assert(c1.peek() == 0); - assert(c2.peek() == 0); - - // wait at least one minute - util.sleep(1.1m); + // counters may have been incremented before the test starts + let c1val = c1.peek(); + let c2val = c2.peek(); - // check that both counters have been incremented - assert(c1.peek() >= 1); - assert(c2.peek() >= 1); + // wait at least one minute + util.sleep(1.1m); -}, std.TestProps { timeout: 2m }) as "on tick is called both for rate and cron schedules"; + // check that both counters have been incremented + assert(c1.peek() >= c1val + 1); + assert(c2.peek() >= c2val + 1); +},timeout: 2m) as "on tick is called both for rate and cron schedules"; diff --git a/examples/tests/sdk_tests/table/get.test.w b/examples/tests/sdk_tests/table/get.test.w index fe880c281aa..b2b554479ad 100644 --- a/examples/tests/sdk_tests/table/get.test.w +++ b/examples/tests/sdk_tests/table/get.test.w @@ -20,7 +20,7 @@ test "get" { try { block(); } catch actual { - assert(actual == expected); + assert(actual.contains(expected)); error = true; } assert(error); diff --git a/examples/tests/valid/redis.test.w b/examples/tests/valid/redis.test.w index 93f8378eeff..a8d355a24a2 100644 --- a/examples/tests/valid/redis.test.w +++ b/examples/tests/valid/redis.test.w @@ -18,12 +18,6 @@ queue.setConsumer(inflight (message: str) => { }, timeout: 3s); test "testing Redis" { - // Using raw client - let connection = r.rawClient(); - connection.set("wing", "does redis"); - let value = connection.get("wing"); - assert(value == "does redis"); - // Using API r2.set("wing", "does redis again"); let value2 = r2.get("wing"); diff --git a/libs/wingsdk/.projen/deps.json b/libs/wingsdk/.projen/deps.json index 5c7159ccc78..cd5947ee388 100644 --- a/libs/wingsdk/.projen/deps.json +++ b/libs/wingsdk/.projen/deps.json @@ -295,6 +295,10 @@ "name": "safe-stable-stringify", "type": "bundled" }, + { + "name": "undici", + "type": "bundled" + }, { "name": "uuid", "type": "bundled" diff --git a/libs/wingsdk/.projen/tasks.json b/libs/wingsdk/.projen/tasks.json index 9b02644fc00..acb844e229e 100644 --- a/libs/wingsdk/.projen/tasks.json +++ b/libs/wingsdk/.projen/tasks.json @@ -480,7 +480,7 @@ "exec": "pnpm i --no-frozen-lockfile" }, { - "exec": "pnpm update @cdktf/provider-aws @types/aws-lambda @types/express @types/fs-extra @types/mime-types @types/node @types/uuid @typescript-eslint/eslint-plugin @typescript-eslint/parser @vitest/coverage-v8 @winglang/jsii-docgen aws-sdk-client-mock aws-sdk-client-mock-jest bump-pack cdktf-cli constructs eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint-plugin-sort-exports eslint fs-extra jsii-diff jsii-pacmak jsii-rosetta jsii nanoid npm-check-updates prettier projen standard-version ts-node typescript vitest wing-api-checker @aws-sdk/client-cloudwatch-logs @aws-sdk/client-dynamodb @aws-sdk/client-elasticache @aws-sdk/client-lambda @aws-sdk/client-s3 @aws-sdk/client-secrets-manager @aws-sdk/client-sns @aws-sdk/client-sqs @aws-sdk/is-array-buffer @aws-sdk/s3-request-presigner @aws-sdk/types @aws-sdk/util-buffer-from @aws-sdk/util-dynamodb @aws-sdk/util-stream-node @aws-sdk/util-utf8-node @azure/core-paging @azure/identity @azure/storage-blob @types/aws-lambda aws-cdk-lib cdktf cron-parser esbuild-wasm express ioredis jsonschema mime-types nanoid safe-stable-stringify uuid yaml constructs constructs" + "exec": "pnpm update @cdktf/provider-aws @types/aws-lambda @types/express @types/fs-extra @types/mime-types @types/node @types/uuid @typescript-eslint/eslint-plugin @typescript-eslint/parser @vitest/coverage-v8 @winglang/jsii-docgen aws-sdk-client-mock aws-sdk-client-mock-jest bump-pack cdktf-cli constructs eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint-plugin-sort-exports eslint fs-extra jsii-diff jsii-pacmak jsii-rosetta jsii nanoid npm-check-updates prettier projen standard-version ts-node typescript vitest wing-api-checker @aws-sdk/client-cloudwatch-logs @aws-sdk/client-dynamodb @aws-sdk/client-elasticache @aws-sdk/client-lambda @aws-sdk/client-s3 @aws-sdk/client-secrets-manager @aws-sdk/client-sns @aws-sdk/client-sqs @aws-sdk/is-array-buffer @aws-sdk/s3-request-presigner @aws-sdk/types @aws-sdk/util-buffer-from @aws-sdk/util-dynamodb @aws-sdk/util-stream-node @aws-sdk/util-utf8-node @azure/core-paging @azure/identity @azure/storage-blob @types/aws-lambda aws-cdk-lib cdktf cron-parser esbuild-wasm express ioredis jsonschema mime-types nanoid safe-stable-stringify undici uuid yaml constructs constructs" }, { "exec": "pnpm exec projen" diff --git a/libs/wingsdk/.projenrc.ts b/libs/wingsdk/.projenrc.ts index ccfe1890f30..eb8758cb08a 100644 --- a/libs/wingsdk/.projenrc.ts +++ b/libs/wingsdk/.projenrc.ts @@ -78,6 +78,7 @@ const project = new cdk.JsiiProject({ // simulator dependencies "express", "uuid", + "undici", // using version 3 because starting from version 4, it no longer works with CommonJS. "nanoid@^3.3.6", "cron-parser", diff --git a/libs/wingsdk/package.json b/libs/wingsdk/package.json index 8af63262534..5d32c9f6de8 100644 --- a/libs/wingsdk/package.json +++ b/libs/wingsdk/package.json @@ -109,6 +109,7 @@ "mime-types": "^2.1.35", "nanoid": "^3.3.6", "safe-stable-stringify": "^2.4.3", + "undici": "^5.26.3", "uuid": "^8.3.2", "yaml": "^2.3.2" }, @@ -142,6 +143,7 @@ "mime-types", "nanoid", "safe-stable-stringify", + "undici", "uuid", "yaml" ], diff --git a/libs/wingsdk/src/ex/redis.ts b/libs/wingsdk/src/ex/redis.ts index d516ea481b0..da39bd001a3 100644 --- a/libs/wingsdk/src/ex/redis.ts +++ b/libs/wingsdk/src/ex/redis.ts @@ -32,7 +32,6 @@ export abstract class Redis extends Resource { /** @internal */ public _getInflightOps(): string[] { return [ - RedisInflightMethods.RAW_CLIENT, RedisInflightMethods.URL, RedisInflightMethods.SET, RedisInflightMethods.GET, @@ -49,12 +48,6 @@ export abstract class Redis extends Resource { * Inflight interface for `Redis`. */ export interface IRedisClient { - /** - * Get raw redis client (currently IoRedis). - * @inflight - */ - rawClient(): Promise; - /** * Get url of redis server. * @inflight @@ -126,8 +119,6 @@ export interface IRedisClient { * @internal */ export enum RedisInflightMethods { - /** `Redis.rawClient` */ - RAW_CLIENT = "rawClient", /** `Redis.url` */ URL = "url", /** `Redis.set` */ @@ -150,7 +141,10 @@ export enum RedisInflightMethods { * Base class for `Redis` Client. */ export abstract class RedisClientBase implements IRedisClient { - public abstract rawClient(): Promise; + /** + * Get raw redis client (currently IoRedis). + */ + protected abstract rawClient(): Promise; public abstract url(): Promise; public async set(key: string, value: string): Promise { diff --git a/libs/wingsdk/src/shared/bundling.ts b/libs/wingsdk/src/shared/bundling.ts index 468a261104b..ecf0ebaf7da 100644 --- a/libs/wingsdk/src/shared/bundling.ts +++ b/libs/wingsdk/src/shared/bundling.ts @@ -10,6 +10,8 @@ export interface Bundle { hash: string; } +const SDK_PATH = normalPath(join(__dirname, "..", "..")); + /** * Bundles a javascript entrypoint into a single file. * @param entrypoint The javascript entrypoint @@ -29,6 +31,9 @@ export function createBundle(entrypoint: string, outputDir?: string): Bundle { nodePaths: process.env.WING_NODE_MODULES ? [normalPath(process.env.WING_NODE_MODULES as string)] : undefined, + alias: { + "@winglang/sdk": SDK_PATH, + }, minify: false, platform: "node", target: "node18", diff --git a/libs/wingsdk/src/simulator/client.ts b/libs/wingsdk/src/simulator/client.ts new file mode 100644 index 00000000000..0f5f93ed7ad --- /dev/null +++ b/libs/wingsdk/src/simulator/client.ts @@ -0,0 +1,92 @@ +import { fetch, Agent } from "undici"; +import type { + SimulatorServerRequest, + SimulatorServerResponse, +} from "./simulator"; +import { Datetime } from "../std"; + +// TODO: more robust serialization scheme + +export function serializeValue(input: any): string { + return JSON.stringify(input, (_key, value) => { + if (value instanceof Datetime) { + return { + $kind: "datetime", + day: value.dayOfMonth, + hour: value.hours, + min: value.min, + month: value.month, + sec: value.sec, + year: value.year, + ms: value.ms, + tz: value.timezone, + }; + } + return value; + }); +} + +export function deserializeValue(input: string): any { + return JSON.parse(input, (_key, value) => { + // assumption: Wing APIs don't distinguish between null and undefined, so we can swap them + if (value === null) { + return undefined; + } + if (value.$kind === "datetime") { + return Datetime.fromComponents({ + day: value.day, + hour: value.hour, + min: value.min, + month: value.month, + sec: value.sec, + year: value.year, + ms: value.ms, + tz: value.tz, + }); + } + return value; + }); +} + +export function makeSimulatorClient(url: string, handle: string) { + return new Proxy( + {}, + { + get: function (_target, method, _receiver) { + return async function (...args: any[]) { + const body: SimulatorServerRequest = { + handle, + method: method as string, + args, + }; + let resp; + try { + resp = await fetch(url + "/v1/call", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + dispatcher: new Agent({ + keepAliveTimeout: 15 * 60 * 1000, + keepAliveMaxTimeout: 15 * 60 * 1000, + headersTimeout: 15 * 60 * 1000, + bodyTimeout: 15 * 60 * 1000, + }), + }); + } catch (e) { + console.error(e); + throw e; + } + + let parsed: SimulatorServerResponse = deserializeValue( + await resp.text() + ); + + if (parsed.error) { + throw new Error(parsed.error); + } + return parsed.result; + }; + }, + } + ); +} diff --git a/libs/wingsdk/src/simulator/index.ts b/libs/wingsdk/src/simulator/index.ts index ec92e67c9b6..b78ccbbdf55 100644 --- a/libs/wingsdk/src/simulator/index.ts +++ b/libs/wingsdk/src/simulator/index.ts @@ -1,3 +1,4 @@ +export * from "./client"; export * from "./simulator"; export * from "./testing"; export * from "./tree"; diff --git a/libs/wingsdk/src/simulator/simulator.ts b/libs/wingsdk/src/simulator/simulator.ts index a214dfb480a..9cdac2be128 100644 --- a/libs/wingsdk/src/simulator/simulator.ts +++ b/libs/wingsdk/src/simulator/simulator.ts @@ -1,5 +1,12 @@ import { existsSync } from "fs"; +import { Server } from "http"; +import { AddressInfo } from "net"; import { join } from "path"; +import { + deserializeValue, + makeSimulatorClient, + serializeValue, +} from "./client"; import { Tree } from "./tree"; import { SDK_VERSION } from "../constants"; import { ConstructTree, TREE_FILE_PATH } from "../core"; @@ -11,6 +18,8 @@ import { isToken } from "../target-sim/tokens"; const START_ATTEMPT_COUNT = 10; +const LOCALHOST_ADDRESS = "127.0.0.1"; + /** * Props for `Simulator`. */ @@ -77,6 +86,11 @@ export interface ISimulatorContext { */ readonly resourcePath: string; + /** + * The url that the simulator server is listening on. + */ + readonly serverUrl: string; + /** * Find a resource simulation by its handle. Throws if the handle isn't valid. */ @@ -127,6 +141,8 @@ export class Simulator { private readonly _traceSubscribers: Array; private _tree: Tree; private _connections: ConnectionData[]; + private _serverUrl: string | undefined; + private _server: Server | undefined; constructor(props: SimulatorProps) { this.simdir = props.simfile; @@ -203,6 +219,8 @@ export class Simulator { ...this._config.resources, ]; + await this.startServer(); + while (true) { const next = initQueue.shift(); if (!next) { @@ -231,6 +249,69 @@ export class Simulator { this._running = true; } + /** + * Start a server that allows any resource to be accessed via HTTP. + */ + public async startServer(): Promise { + // import lazily to reduce SDK import time (20ms or so) + const express = await import("express").then((m) => m.default); + const app = express(); + app.use(express.json()); + + app.post("/v1/call", async (req, res, next) => { + try { + let request: SimulatorServerRequest = deserializeValue( + JSON.stringify(req.body) + ); + + const { handle, method, args } = request; + const resource = this._handles.find(handle); + + try { + const result = await (resource as any)[method](...args); + res + .status(200) + .json( + JSON.parse(serializeValue({ result })) as SimulatorServerResponse + ); + } catch (err) { + if (err instanceof Error) { + res.status(500).json({ + error: err.stack ?? err.message, + } as SimulatorServerResponse); + } else { + res.status(500).json({ error: err } as SimulatorServerResponse); + } + } + } catch (err) { + return next(err); + } + }); + + const addrInfo: AddressInfo = await new Promise((resolve, reject) => { + this._server = app.listen(0, LOCALHOST_ADDRESS, () => { + const addr = this._server?.address(); + if (addr && typeof addr === "object" && (addr as any).port) { + resolve(addr); + } else { + reject(new Error("No address found")); + } + }); + }); + + this._serverUrl = `http://${addrInfo.address}:${addrInfo.port}`; + } + + /** + * The URL that the simulator server is listening on. + */ + public get url(): string { + if (!this._serverUrl) { + throw new Error("Simulator server is not running."); + } + return this._serverUrl; + } + /** * Stop the simulation and clean up all resources. */ @@ -265,6 +346,9 @@ export class Simulator { this._addTrace(event); } + this._server!.close(); + this._server!.closeAllConnections(); + this._handles.reset(); this._running = false; } @@ -299,28 +383,28 @@ export class Simulator { } /** - * Get a simulated resource instance. + * Get a resource client. * @returns the resource */ public getResource(path: string): any { - const handle = this.tryGetResource(path); - if (!handle) { + const client = this.tryGetResource(path); + if (!client) { throw new Error(`Resource "${path}" not found.`); } - return handle; + return client; } /** - * Get a simulated resource instance. + * Get a resource client. * @returns The resource of undefined if not found */ public tryGetResource(path: string): any | undefined { - const handle = this.tryGetResourceConfig(path)?.attrs.handle; + const handle: string = this.tryGetResourceConfig(path)?.attrs.handle; if (!handle) { return undefined; } - return this._handles.find(handle); + return makeSimulatorClient(this.url, handle); } /** @@ -422,9 +506,14 @@ export class Simulator { } private createContext(resourceConfig: BaseResourceSchema): ISimulatorContext { + const serverUrl = this._serverUrl; + if (!serverUrl) { + throw new Error("Simulator server is not running."); + } return { simdir: this.simdir, resourcePath: resourceConfig.path, + serverUrl, findInstance: (handle: string) => { return this._handles.find(handle); }, @@ -653,3 +742,27 @@ export interface ConnectionData { /** A name for the connection. */ readonly name: string; } + +/** + * Internal schema for requests to the simulator server's /call endpoint. + * Subject to breaking changes. + */ +export interface SimulatorServerRequest { + /** The resource handle (an ID unique among resources in the simulation). */ + readonly handle: string; + /** The method to call on the resource. */ + readonly method: string; + /** The arguments to the method. */ + readonly args: any[]; +} + +/** + * Internal schema for responses from the simulator server's /call endpoint. + * Subject to breaking changes. + */ +export interface SimulatorServerResponse { + /** The result of the method call. */ + readonly result?: any; + /** The error that occurred during the method call. */ + readonly error?: any; +} diff --git a/libs/wingsdk/src/target-sim/function.inflight.ts b/libs/wingsdk/src/target-sim/function.inflight.ts index 53b55a152fc..bb93b5cc935 100644 --- a/libs/wingsdk/src/target-sim/function.inflight.ts +++ b/libs/wingsdk/src/target-sim/function.inflight.ts @@ -42,7 +42,10 @@ export class Function implements IFunctionClient, ISimulatorResourceInstance { activity: async () => { const sb = new Sandbox(this.filename, { context: { $simulator: this.context }, - env: this.env, + env: { + ...this.env, + WING_SIMULATOR_URL: this.context.serverUrl, + }, timeout: this.timeout, log: (_level, message) => { this.context.addTrace({ diff --git a/libs/wingsdk/src/target-sim/redis.inflight.ts b/libs/wingsdk/src/target-sim/redis.inflight.ts index 199a8c7dd76..e3d8c755e29 100644 --- a/libs/wingsdk/src/target-sim/redis.inflight.ts +++ b/libs/wingsdk/src/target-sim/redis.inflight.ts @@ -55,7 +55,7 @@ export class Redis await runCommand("docker", ["rm", "-f", `${this.containerName}`]); } - public async rawClient(): Promise { + protected async rawClient(): Promise { if (this.connection) { return this.connection; } diff --git a/libs/wingsdk/src/target-sim/service.inflight.ts b/libs/wingsdk/src/target-sim/service.inflight.ts index bb2b3a15332..e6f02fa1167 100644 --- a/libs/wingsdk/src/target-sim/service.inflight.ts +++ b/libs/wingsdk/src/target-sim/service.inflight.ts @@ -22,7 +22,10 @@ export class Service implements IServiceClient, ISimulatorResourceInstance { this.entrypoint = resolve(context.simdir, props.sourceCodeFile); this.autoStart = props.autoStart; this.sandbox = new Sandbox(this.entrypoint, { - env: props.environmentVariables, + env: { + ...props.environmentVariables, + WING_SIMULATOR_URL: context.serverUrl, + }, context: { $simulator: this.context }, log: (_level, message) => { this.context.addTrace({ diff --git a/libs/wingsdk/src/target-sim/util.ts b/libs/wingsdk/src/target-sim/util.ts index 0965e3dc02c..3398d5dcd9a 100644 --- a/libs/wingsdk/src/target-sim/util.ts +++ b/libs/wingsdk/src/target-sim/util.ts @@ -43,13 +43,20 @@ export function bindSimulatorResource( export function makeSimulatorJsClient(filename: string, resource: Resource) { const type = basename(filename).split(".")[0]; const env = makeEnvVarName(type, resource); - return `(function(env) { - let handle = process.env[env]; + + // return an object where calling any method will make a request to the simulator server + return `(function() { + const handle = process.env.${env}; if (!handle) { - throw new Error("Missing environment variable: " + env); + throw new Error("Missing environment variable: ${env}"); + } + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error("Missing environment variable: WING_SIMULATOR_URL"); } - return $simulator.findInstance(handle); -})("${env}")`; + + return require("@winglang/sdk").simulator.makeSimulatorClient(simulatorUrl, handle); +})()`; } // helper function to convert duration to a cron string diff --git a/libs/wingsdk/src/target-tf-aws/redis.inflight.ts b/libs/wingsdk/src/target-tf-aws/redis.inflight.ts index fc1e4061d2f..6e2e9b752aa 100644 --- a/libs/wingsdk/src/target-tf-aws/redis.inflight.ts +++ b/libs/wingsdk/src/target-tf-aws/redis.inflight.ts @@ -48,7 +48,7 @@ export class RedisClient extends RedisClientBase { return cacheNode.Endpoint.Address!; } - public async rawClient(): Promise { + protected async rawClient(): Promise { if (!this.clusterId) { throw new Error("No cluster id provided"); } diff --git a/libs/wingsdk/test/simulator/__snapshots__/simulator.test.ts.snap b/libs/wingsdk/test/simulator/__snapshots__/simulator.test.ts.snap index c635ef446a0..5efebe83114 100644 --- a/libs/wingsdk/test/simulator/__snapshots__/simulator.test.ts.snap +++ b/libs/wingsdk/test/simulator/__snapshots__/simulator.test.ts.snap @@ -87,7 +87,6 @@ exports[`run all tests > single test 1`] = ` { "data": { "message": "Invoke (payload=\\"\\").", - "result": undefined, "status": "success", }, "sourcePath": "root/test/Handler", @@ -118,7 +117,6 @@ exports[`run single test > happy path 1`] = ` { "data": { "message": "Invoke (payload=\\"\\").", - "result": undefined, "status": "success", }, "sourcePath": "root/test/Handler", @@ -157,7 +155,7 @@ exports[`run single test > test failure 1`] = ` }, { "data": { - "error": [Error: test failed], + "error": {}, "message": "Invoke (payload=\\"\\").", "status": "failure", }, diff --git a/libs/wingsdk/test/simulator/simulator.test.ts b/libs/wingsdk/test/simulator/simulator.test.ts index 7ae3bd0afcb..6d46903516c 100644 --- a/libs/wingsdk/test/simulator/simulator.test.ts +++ b/libs/wingsdk/test/simulator/simulator.test.ts @@ -1,9 +1,9 @@ import { Construct } from "constructs"; import { test, expect, describe } from "vitest"; -import { Bucket, ITestRunnerClient, TestResult } from "../../src/cloud"; +import { Bucket } from "../../src/cloud"; import { InflightBindings } from "../../src/core"; import { Testing } from "../../src/simulator"; -import { Test } from "../../src/std"; +import { ITestRunnerClient, Test, TestResult } from "../../src/std"; import { SimApp } from "../sim-app"; describe("run single test", () => { diff --git a/libs/wingsdk/test/target-sim/__snapshots__/bucket.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/bucket.test.ts.snap index 5e0b9ad89cb..8e39678bdfb 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/bucket.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/bucket.test.ts.snap @@ -1,6 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`bucket on event creates 3 topics, and sends the right event and key in the event handlers 1`] = ` +exports[`bucket on event creates 3 topics, and sends the right event and key in the event handlers 1`] = ` [ "wingsdk.cloud.TestRunner created.", "wingsdk.cloud.Topic created.", @@ -575,7 +575,6 @@ exports[`update an object in bucket 1`] = ` "Invoke (payload=\\"greeting.txt\\").", "Subscriber error: TypeError: this.handler.handle is not a function", "Put (key=greeting.txt).", - "Put (key=greeting.txt).", "wingsdk.sim.EventMapping deleted.", "wingsdk.cloud.Function deleted.", "wingsdk.cloud.Bucket deleted.", diff --git a/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap index ff8aee06aee..380304cb7fd 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap @@ -18,20 +18,30 @@ return class Handler { } }; })())({ -counter: (function(env) { - let handle = process.env[env]; +counter: (function() { + const handle = process.env.COUNTER_HANDLE_4ecd8d46; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: COUNTER_HANDLE_4ecd8d46\\"); } - return $simulator.findInstance(handle); -})(\\"COUNTER_HANDLE_4ecd8d46\\"), -bucket: (function(env) { - let handle = process.env[env]; + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); + } + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})(), +bucket: (function() { + const handle = process.env.BUCKET_HANDLE_5f2a41c8; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: BUCKET_HANDLE_5f2a41c8\\"); } - return $simulator.findInstance(handle); -})(\\"BUCKET_HANDLE_5f2a41c8\\") + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); + } + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})() }), args: {} })).handle(event); };", "connections.json": { diff --git a/libs/wingsdk/test/target-sim/__snapshots__/function.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/function.test.ts.snap index 88895a88d58..dd000b0faab 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/function.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/function.test.ts.snap @@ -628,7 +628,7 @@ return class Handler { } async handle() { - return fetch; + return typeof fetch; } }; @@ -648,7 +648,7 @@ return class Handler { async handle() { const c = require(\\"crypto\\"); - return c.createHash; + return typeof c.createHash; } }; diff --git a/libs/wingsdk/test/target-sim/__snapshots__/immutable-capture.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/immutable-capture.test.ts.snap index f4967452ddd..0338841f29e 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/immutable-capture.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/immutable-capture.test.ts.snap @@ -126,19 +126,29 @@ if (!(await this.my_buckets[1].get(\\"foo\\") === \\"bar\\")) { throw new Error( } }; })())({ -my_buckets: [(function(env) { - let handle = process.env[env]; +my_buckets: [(function() { + const handle = process.env.BUCKET_HANDLE_4fecd6d0; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: BUCKET_HANDLE_4fecd6d0\\"); } - return $simulator.findInstance(handle); -})(\\"BUCKET_HANDLE_4fecd6d0\\"),(function(env) { - let handle = process.env[env]; + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); + } + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})(),(function() { + const handle = process.env.BUCKET_HANDLE_300e8055; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: BUCKET_HANDLE_300e8055\\"); + } + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); } - return $simulator.findInstance(handle); -})(\\"BUCKET_HANDLE_300e8055\\")] + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})()] })).handle(event); };", "connections.json": { @@ -1032,19 +1042,29 @@ if (!(await foo.get(\\"hello.txt\\") === \\"world\\")) { throw new Error(\`asser } }; })())({ -my_map: new Map([[\\"foo\\",(function(env) { - let handle = process.env[env]; +my_map: new Map([[\\"foo\\",(function() { + const handle = process.env.BUCKET_HANDLE_4fecd6d0; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: BUCKET_HANDLE_4fecd6d0\\"); + } + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); } - return $simulator.findInstance(handle); -})(\\"BUCKET_HANDLE_4fecd6d0\\")],[\\"bar\\",(function(env) { - let handle = process.env[env]; + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})()],[\\"bar\\",(function() { + const handle = process.env.BUCKET_HANDLE_300e8055; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: BUCKET_HANDLE_300e8055\\"); + } + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); } - return $simulator.findInstance(handle); -})(\\"BUCKET_HANDLE_300e8055\\")]]) + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})()]]) })).handle(event); };", "connections.json": { @@ -1835,37 +1855,62 @@ if (!(await bar.get(\\"foo\\") === \\"bar\\")) { throw new Error(\`assertion fai } }; })())({ -my_struct: {\\"bucky\\": (function(env) { - let handle = process.env[env]; +my_struct: {\\"bucky\\": (function() { + const handle = process.env.BUCKET_HANDLE_4fecd6d0; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: BUCKET_HANDLE_4fecd6d0\\"); + } + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); } - return $simulator.findInstance(handle); -})(\\"BUCKET_HANDLE_4fecd6d0\\"),\\"mapy\\": new Map([[\\"foo\\",(function(env) { - let handle = process.env[env]; + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})(),\\"mapy\\": new Map([[\\"foo\\",(function() { + const handle = process.env.BUCKET_HANDLE_300e8055; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: BUCKET_HANDLE_300e8055\\"); + } + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); } - return $simulator.findInstance(handle); -})(\\"BUCKET_HANDLE_300e8055\\")],[\\"bar\\",(function(env) { - let handle = process.env[env]; + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})()],[\\"bar\\",(function() { + const handle = process.env.BUCKET_HANDLE_0120daf4; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: BUCKET_HANDLE_0120daf4\\"); } - return $simulator.findInstance(handle); -})(\\"BUCKET_HANDLE_0120daf4\\")]]),\\"arry\\": {\\"boom\\": [(function(env) { - let handle = process.env[env]; + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); + } + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})()]]),\\"arry\\": {\\"boom\\": [(function() { + const handle = process.env.BUCKET_HANDLE_ea7944ef; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: BUCKET_HANDLE_ea7944ef\\"); } - return $simulator.findInstance(handle); -})(\\"BUCKET_HANDLE_ea7944ef\\"),(function(env) { - let handle = process.env[env]; + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); + } + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})(),(function() { + const handle = process.env.BUCKET_HANDLE_1d7ab674; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: BUCKET_HANDLE_1d7ab674\\"); } - return $simulator.findInstance(handle); -})(\\"BUCKET_HANDLE_1d7ab674\\")],},} + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); + } + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})()],},} })).handle(event); };", "connections.json": { diff --git a/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap index 2a44d4d5a81..f84af896ca9 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap @@ -800,7 +800,7 @@ exports[`queue batch size of 2, purge the queue 2`] = ` } `; -exports[`queue with one subscriber, batch size of 5 1`] = ` +exports[`queue with one subscriber, batch size of 5, should get processed in two batches 1`] = ` { ".wing/function_c8ab799f.js": "\\"use strict\\"; exports.handler = async function(event) { @@ -812,22 +812,22 @@ return class Handler { } } async handle() { - await this.queue.push(\\"A\\"); - await this.queue.push(\\"B\\"); - await this.queue.push(\\"C\\"); - await this.queue.push(\\"D\\"); - await this.queue.push(\\"E\\"); - await this.queue.push(\\"F\\"); + await this.queue.push(\\"A\\", \\"B\\", \\"C\\", \\"D\\", \\"E\\", \\"F\\"); } }; })())({ -queue: (function(env) { - let handle = process.env[env]; +queue: (function() { + const handle = process.env.QUEUE_HANDLE_54fcf4cd; if (!handle) { - throw new Error(\\"Missing environment variable: \\" + env); + throw new Error(\\"Missing environment variable: QUEUE_HANDLE_54fcf4cd\\"); } - return $simulator.findInstance(handle); -})(\\"QUEUE_HANDLE_54fcf4cd\\") + const simulatorUrl = process.env.WING_SIMULATOR_URL; + if (!simulatorUrl) { + throw new Error(\\"Missing environment variable: WING_SIMULATOR_URL\\"); + } + + return require(\\"@winglang/sdk\\").simulator.makeSimulatorClient(simulatorUrl, handle); +})() })).handle(event); };", ".wing/my_queue-setconsumer-e645076f_c8ddc1ce.js": "\\"use strict\\"; diff --git a/libs/wingsdk/test/target-sim/bucket.test.ts b/libs/wingsdk/test/target-sim/bucket.test.ts index 29053341e45..f42acb07e83 100644 --- a/libs/wingsdk/test/target-sim/bucket.test.ts +++ b/libs/wingsdk/test/target-sim/bucket.test.ts @@ -47,25 +47,14 @@ test("update an object in bucket", async () => { const VALUE = JSON.stringify({ msg: "Hello world!" }); // WHEN - // @ts-expect-error - private method - const notifyListeners = vi.spyOn(client, "notifyListeners"); - await client.put(KEY, VALUE); - expect(notifyListeners).toBeCalledWith(cloud.BucketEventType.CREATE, KEY); - - await client.put(KEY, JSON.stringify({ msg: "another msg" })); - expect(notifyListeners).toBeCalledWith(cloud.BucketEventType.UPDATE, KEY); - expect(Object.keys((client as any).topicHandlers)).toMatchObject([ - BucketEventType.CREATE, - ]); // THEN await s.stop(); - expect(notifyListeners).toBeCalledTimes(2); expect(listMessages(s)).toMatchSnapshot(); }); -test("bucket on event creates 3 topics, and sends the right event and key in the event handlers ", async () => { +test("bucket on event creates 3 topics, and sends the right event and key in the event handlers", async () => { // GIVEN const app = new SimApp(); const bucket = cloud.Bucket._newBucket(app, "my_bucket"); @@ -73,9 +62,9 @@ test("bucket on event creates 3 topics, and sends the right event and key in the const testInflight = Testing.makeHandler( app, "inflight_test", - `async handle(key, event) { await this.bucket.put(key, event); }`, + `async handle(key, event) { await this.logBucket.put(key, event); }`, { - bucket: { + logBucket: { obj: logBucket, ops: [cloud.BucketInflightMethods.PUT], }, @@ -88,12 +77,6 @@ test("bucket on event creates 3 topics, and sends the right event and key in the const client = s.getResource("/my_bucket") as cloud.IBucketClient; const logClient = s.getResource("/log_bucket") as cloud.IBucketClient; - expect(Object.keys((client as any).topicHandlers)).toMatchObject([ - BucketEventType.CREATE, - BucketEventType.UPDATE, - BucketEventType.DELETE, - ]); - // THEN await client.put("a", "1"); expect(await logClient.get("a")).toBe(BucketEventType.CREATE); @@ -167,8 +150,6 @@ test("put and get Json object from bucket", async () => { const VALUE = { msg: "Hello world!" }; // WHEN - - const notifyListeners = vi.spyOn(client as any, "notifyListeners"); await client.putJson(KEY, VALUE as any); const response = await client.getJson("greeting.json"); @@ -178,7 +159,6 @@ test("put and get Json object from bucket", async () => { expect(response).toEqual(VALUE); expect(listMessages(s)).toMatchSnapshot(); expect(app.snapshot()).toMatchSnapshot(); - expect(notifyListeners).toBeCalledWith(cloud.BucketEventType.CREATE, KEY); }); test("put multiple objects and list all from bucket", async () => { @@ -351,20 +331,9 @@ test("removing a key will call onDelete method", async () => { await client.put(fileName, JSON.stringify({ msg: "Hello world!" })); // delete file - //@ts-expect-error - const notifyListeners = vi.spyOn(client, "notifyListeners"); const response = await client.delete(fileName); - - expect(Object.keys((client as any).topicHandlers)).toMatchObject([ - BucketEventType.DELETE, - ]); - await s.stop(); - expect(notifyListeners).toBeCalledWith( - cloud.BucketEventType.DELETE, - fileName - ); expect(response).toEqual(undefined); expect(listMessages(s)).toMatchSnapshot(); }); @@ -529,8 +498,7 @@ test("can add file in preflight", async () => { }); test("Given a non public bucket when reaching to a key public url it should throw an error", async () => { - //GIVEN - let error; + // GIVEN const app = new SimApp(); cloud.Bucket._newBucket(app, "my_bucket"); @@ -539,23 +507,15 @@ test("Given a non public bucket when reaching to a key public url it should thro const KEY = "KEY"; - // WHEN - try { - await client.publicUrl(KEY); - } catch (err) { - error = err; - } - // THEN - expect(error?.message).toBe( - "Cannot provide public url for a non-public bucket" + await expect(() => client.publicUrl(KEY)).rejects.toThrowError( + /Cannot provide public url for a non-public bucket/ ); await s.stop(); }); test("Given a public bucket when reaching to a non existent key, public url it should throw an error", async () => { - //GIVEN - let error; + // GIVEN const app = new SimApp(); cloud.Bucket._newBucket(app, "my_bucket", { public: true }); @@ -564,21 +524,14 @@ test("Given a public bucket when reaching to a non existent key, public url it s const KEY = "KEY"; - // WHEN - try { - await client.publicUrl(KEY); - } catch (err) { - error = err; - } - - expect(error?.message).toBe( - "Cannot provide public url for an non-existent key (key=KEY)" - ); // THEN + await expect(() => client.publicUrl(KEY)).rejects.toThrowError( + /Cannot provide public url for an non-existent key/ + ); await s.stop(); }); -test("Given a public bucket, when giving one of its keys, we should get it's public url", async () => { +test("Given a public bucket, when giving one of its keys, we should get its public url", async () => { // GIVEN const app = new SimApp(); cloud.Bucket._newBucket(app, "my_bucket", { public: true }); @@ -595,8 +548,8 @@ test("Given a public bucket, when giving one of its keys, we should get it's pub // THEN await s.stop(); - const filePath = `${client.fileDir}/${KEY}`; - expect(response).toEqual(url.pathToFileURL(filePath).href); + // file paths are different on windows and linux + expect(response.endsWith("KEY")).toBe(true); }); test("check if an object exists in the bucket", async () => { diff --git a/libs/wingsdk/test/target-sim/file-counter.test.ts b/libs/wingsdk/test/target-sim/file-counter.test.ts index ba5e41a68b4..59b48c35032 100644 --- a/libs/wingsdk/test/target-sim/file-counter.test.ts +++ b/libs/wingsdk/test/target-sim/file-counter.test.ts @@ -6,64 +6,68 @@ import { Testing } from "../../src/simulator"; import { IResource, Trace } from "../../src/std"; import { SimApp } from "../sim-app"; -test("can create sequential files in a bucket", async () => { - // GIVEN - class HelloWorld extends Construct { - public readonly processor: IResource; +test( + "can create sequential files in a bucket", + async () => { + // GIVEN + class HelloWorld extends Construct { + public readonly processor: IResource; - constructor(scope: Construct, id: string) { - super(scope, id); + constructor(scope: Construct, id: string) { + super(scope, id); - const counter = cloud.Counter._newCounter(this, "Counter", { - initial: 1000, - }); - const bucket = cloud.Bucket._newBucket(this, "Bucket"); - const queue = cloud.Queue._newQueue(this, "Queue"); - const processor = Testing.makeHandler( - this, - "Processor", - `async handle(event) { + const counter = cloud.Counter._newCounter(this, "Counter", { + initial: 1000, + }); + const bucket = cloud.Bucket._newBucket(this, "Bucket"); + const queue = cloud.Queue._newQueue(this, "Queue"); + const processor = Testing.makeHandler( + this, + "Processor", + `async handle(event) { let next = await this.counter.inc(); let key = "file-" + next + ".txt"; await this.bucket.put(key, event); }`, - { - counter: { - obj: counter, - ops: [cloud.CounterInflightMethods.INC], - }, - bucket: { - obj: bucket, - ops: [cloud.BucketInflightMethods.PUT], - }, - } - ); - this.processor = queue.setConsumer(processor); + { + counter: { + obj: counter, + ops: [cloud.CounterInflightMethods.INC], + }, + bucket: { + obj: bucket, + ops: [cloud.BucketInflightMethods.PUT], + }, + } + ); + this.processor = queue.setConsumer(processor); + } } - } - const app = new SimApp(); - const helloWorld = new HelloWorld(app, "HelloWorld"); + const app = new SimApp(); + const helloWorld = new HelloWorld(app, "HelloWorld"); - const s = await app.startSimulator(); + const s = await app.startSimulator(); - const pusher = s.getResource("/HelloWorld/Queue") as cloud.IQueueClient; + const pusher = s.getResource("/HelloWorld/Queue") as cloud.IQueueClient; - // WHEN - const traceCheck = (trace: Trace) => - trace.sourcePath === helloWorld.processor.node.path && - trace.data.status === "success"; + // WHEN + const traceCheck = (trace: Trace) => + trace.sourcePath === helloWorld.processor.node.path && + trace.data.status === "success"; - await pusher.push("kachow!"); - await waitUntilTraceCount(s, 1, traceCheck); - await pusher.push("zoom!"); - await waitUntilTraceCount(s, 2, traceCheck); + await pusher.push("kachow!"); + await waitUntilTraceCount(s, 1, traceCheck); + await pusher.push("zoom!"); + await waitUntilTraceCount(s, 2, traceCheck); - // THEN - const bucket = s.getResource("/HelloWorld/Bucket") as cloud.IBucketClient; - await expect(bucket.get("file-1000.txt")).resolves.toEqual("kachow!"); - await expect(bucket.get("file-1001.txt")).resolves.toEqual("zoom!"); - await s.stop(); + // THEN + const bucket = s.getResource("/HelloWorld/Bucket") as cloud.IBucketClient; + await expect(bucket.get("file-1000.txt")).resolves.toEqual("kachow!"); + await expect(bucket.get("file-1001.txt")).resolves.toEqual("zoom!"); + await s.stop(); - expect(app.snapshot()).toMatchSnapshot(); -}); + expect(app.snapshot()).toMatchSnapshot(); + }, + { timeout: 20000 } +); diff --git a/libs/wingsdk/test/target-sim/function.test.ts b/libs/wingsdk/test/target-sim/function.test.ts index fef87446d21..2468d26d5d2 100644 --- a/libs/wingsdk/test/target-sim/function.test.ts +++ b/libs/wingsdk/test/target-sim/function.test.ts @@ -210,12 +210,12 @@ test("runtime environment tests", async () => { // check that fetch is a function (we can't really make network calls here) const fetchFn = app.newCloudFunction(` - return fetch; + return typeof fetch; `); const cryptoFn = app.newCloudFunction(` const c = require("crypto"); - return c.createHash; + return typeof c.createHash; `); // check that we can import ESM modules @@ -226,9 +226,9 @@ test("runtime environment tests", async () => { // THEN const s = await app.startSimulator(); - expect(await cryptoFn(s)).toBeTypeOf("function"); + expect(await cryptoFn(s)).toEqual("function"); expect(await urlSearchParamsFn(s)).toBe("api"); - expect(await fetchFn(s)).toBeTypeOf("function"); + expect(await fetchFn(s)).toEqual("function"); expect(await esmModulesFn(s)).toHaveLength(21); await s.stop(); diff --git a/libs/wingsdk/test/target-sim/immutable-capture.test.ts b/libs/wingsdk/test/target-sim/immutable-capture.test.ts index dcce10c8a1f..27f5ae13f13 100644 --- a/libs/wingsdk/test/target-sim/immutable-capture.test.ts +++ b/libs/wingsdk/test/target-sim/immutable-capture.test.ts @@ -2,7 +2,7 @@ import { Construct } from "constructs"; import { test, expect } from "vitest"; import { Bucket } from "../../src/cloud"; import { Function, IFunctionClient } from "../../src/cloud/function"; -import { InflightBindings, NodeJsCode } from "../../src/core/inflight"; +import { InflightBindings } from "../../src/core/inflight"; import { Testing } from "../../src/simulator"; import { Duration } from "../../src/std"; import { SimApp } from "../sim-app"; diff --git a/libs/wingsdk/test/target-sim/queue.test.ts b/libs/wingsdk/test/target-sim/queue.test.ts index ee930800981..2644854f2bb 100644 --- a/libs/wingsdk/test/target-sim/queue.test.ts +++ b/libs/wingsdk/test/target-sim/queue.test.ts @@ -111,7 +111,7 @@ test("queue batch size of 2, purge the queue", async () => { expect(app.snapshot()).toMatchSnapshot(); }); -test("queue with one subscriber, batch size of 5", async () => { +test("queue with one subscriber, batch size of 5, should get processed in two batches", async () => { // GIVEN const app = new SimApp(); @@ -125,12 +125,7 @@ test("queue with one subscriber, batch size of 5", async () => { "OnDeployHandler", `\ async handle() { - await this.queue.push("A"); - await this.queue.push("B"); - await this.queue.push("C"); - await this.queue.push("D"); - await this.queue.push("E"); - await this.queue.push("F"); + await this.queue.push("A", "B", "C", "D", "E", "F"); }`, { queue: { diff --git a/libs/wingsdk/test/target-sim/redis.test.ts b/libs/wingsdk/test/target-sim/redis.test.ts index 8b9debff46b..2588bcf2904 100644 --- a/libs/wingsdk/test/target-sim/redis.test.ts +++ b/libs/wingsdk/test/target-sim/redis.test.ts @@ -1,4 +1,4 @@ -import { Redis as IoRedis } from "ioredis"; +// import { Redis as IoRedis } from "ioredis"; import { test, expect } from "vitest"; import * as ex from "../../src/ex"; import { SimApp } from "../sim-app"; @@ -22,21 +22,6 @@ test("create a Redis resource", async () => { expect(app.snapshot()).toMatchSnapshot(); }); -test("access a Redis resource", async () => { - // GIVEN - const app = new SimApp(); - ex.Redis._newRedis(app, "my_redis"); - - // THEN - await app._withSimulator(async (s) => { - const client = s.getResource("/my_redis") as ex.IRedisClient; - expect((await client.url()).startsWith("redis://")).toBeTruthy(); - const redisClient = (await client.rawClient()) as IoRedis; - await redisClient.set("foo", "bar"); - expect(await redisClient.get("foo")).toEqual("bar"); - }); -}); - test("can set and get a value", async () => { // GIVEN const app = new SimApp(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2e07f59a972..f43599b2d7e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1238,6 +1238,9 @@ importers: safe-stable-stringify: specifier: ^2.4.3 version: 2.4.3 + undici: + specifier: ^5.26.3 + version: 5.26.3 uuid: specifier: ^8.3.2 version: 8.3.2 @@ -4887,6 +4890,11 @@ packages: resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} dev: true + /@fastify/busboy@2.0.0: + resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==} + engines: {node: '>=14'} + dev: false + /@floating-ui/core@1.4.1: resolution: {integrity: sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==} dependencies: @@ -13275,7 +13283,7 @@ packages: dependencies: semver: 7.5.4 shelljs: 0.8.5 - typescript: 5.3.0-dev.20231012 + typescript: 5.3.0-dev.20231013 dev: true /dset@3.1.2: @@ -22712,8 +22720,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - /typescript@5.3.0-dev.20231012: - resolution: {integrity: sha512-k/m+QK/2eVsPMAao4I28Cv2Y9WzUKFVhRqvFGZ3CIXc0lrMkw/1pSA+8tp7IMw1ecxoa1myFql1tmCUrMKCbzA==} + /typescript@5.3.0-dev.20231013: + resolution: {integrity: sha512-ZhuwwWpJ9Hec2JJaS0yOJOjkLDu6lm/PXjniirFFcFBArD5HA3K8P31XxPmwonBhk7oznUbhdIDu8LEYha9Kxw==} engines: {node: '>=14.17'} hasBin: true dev: true @@ -22749,6 +22757,13 @@ packages: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} dev: true + /undici@5.26.3: + resolution: {integrity: sha512-H7n2zmKEWgOllKkIUkLvFmsJQj062lSm3uA4EYApG8gLuiOM0/go9bIoC3HVaSnfg4xunowDE2i9p8drkXuvDw==} + engines: {node: '>=14.0'} + dependencies: + '@fastify/busboy': 2.0.0 + dev: false + /unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} engines: {node: '>=4'} diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/delete.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/delete.test.w_compile_tf-aws.md index e25e9e02388..e7c7b05a0e9 100644 --- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/delete.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/delete.test.w_compile_tf-aws.md @@ -18,7 +18,7 @@ module.exports = function({ $b }) { } catch ($error_actual) { const actual = $error_actual.message; - {((cond) => {if (!cond) throw new Error("assertion failed: actual == expected")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(actual,expected)))}; + {((cond) => {if (!cond) throw new Error("assertion failed: actual.contains(expected)")})(actual.includes(expected))}; error = true; } {((cond) => {if (!cond) throw new Error("assertion failed: error")})(error)}; diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/metadata.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/metadata.test.w_compile_tf-aws.md index 27820f5d32f..30db872bae4 100644 --- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/metadata.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/metadata.test.w_compile_tf-aws.md @@ -12,15 +12,16 @@ module.exports = function({ $b }) { } async handle() { (await $b.put("test1.txt","Foo")); - {((cond) => {if (!cond) throw new Error("assertion failed: b.metadata(\"test1.txt\").size == 3")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $b.metadata("test1.txt")).size,3)))}; - {((cond) => {if (!cond) throw new Error("assertion failed: b.metadata(\"test1.txt\").contentType == \"application/octet-stream\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $b.metadata("test1.txt")).contentType,"application/octet-stream")))}; - {((cond) => {if (!cond) throw new Error("assertion failed: b.metadata(\"test1.txt\").lastModified.year >= 2023")})(((await $b.metadata("test1.txt")).lastModified.year >= 2023))}; + const metadata = (await $b.metadata("test1.txt")); + {((cond) => {if (!cond) throw new Error("assertion failed: metadata.size == 3")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(metadata.size,3)))}; + {((cond) => {if (!cond) throw new Error("assertion failed: metadata.contentType == \"application/octet-stream\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(metadata.contentType,"application/octet-stream")))}; + {((cond) => {if (!cond) throw new Error("assertion failed: metadata.lastModified.year >= 2023")})((metadata.lastModified.year >= 2023))}; try { (await $b.metadata("no-such-file.txt")).lastModified; } catch ($error_e) { const e = $error_e.message; - {((cond) => {if (!cond) throw new Error("assertion failed: e == \"Object does not exist (key=no-such-file.txt).\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(e,"Object does not exist (key=no-such-file.txt).")))}; + {((cond) => {if (!cond) throw new Error("assertion failed: e.contains(\"Object does not exist (key=no-such-file.txt).\")")})(e.includes("Object does not exist (key=no-such-file.txt)."))}; } } } diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.test.w_compile_tf-aws.md index 492aaa58a31..1d15d4d8a02 100644 --- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/public_url.test.w_compile_tf-aws.md @@ -18,7 +18,7 @@ module.exports = function({ $http_Util, $privateBucket, $publicBucket, $util_Uti } catch ($error_actual) { const actual = $error_actual.message; - {((cond) => {if (!cond) throw new Error("assertion failed: actual == expected")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(actual,expected)))}; + {((cond) => {if (!cond) throw new Error("assertion failed: actual.contains(expected)")})(actual.includes(expected))}; error = true; } {((cond) => {if (!cond) throw new Error("assertion failed: error")})(error)}; diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/queue/push.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/queue/push.test.w_compile_tf-aws.md index ba2c5a49154..c4ecc0c8587 100644 --- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/queue/push.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/queue/push.test.w_compile_tf-aws.md @@ -18,7 +18,7 @@ module.exports = function({ $q, $std_Duration, $util_Util }) { } catch ($error_e) { const e = $error_e.message; - {((cond) => {if (!cond) throw new Error("assertion failed: e == \"Empty messages are not allowed\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(e,"Empty messages are not allowed")))}; + {((cond) => {if (!cond) throw new Error("assertion failed: e.contains(\"Empty messages are not allowed\")")})(e.includes("Empty messages are not allowed"))}; } try { (await $q.push("Foo","")); @@ -26,7 +26,7 @@ module.exports = function({ $q, $std_Duration, $util_Util }) { } catch ($error_e) { const e = $error_e.message; - {((cond) => {if (!cond) throw new Error("assertion failed: e == \"Empty messages are not allowed\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(e,"Empty messages are not allowed")))}; + {((cond) => {if (!cond) throw new Error("assertion failed: e.contains(\"Empty messages are not allowed\")")})(e.includes("Empty messages are not allowed"))}; } (await $q.push("Foo")); {((cond) => {if (!cond) throw new Error("assertion failed: util.waitUntil((): bool => {\n return q.approxSize() == 1;\n })")})((await $util_Util.waitUntil(async () => { diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/schedule/on_tick.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/schedule/on_tick.test.w_compile_tf-aws.md index 8bafbad135f..e179fcfca09 100644 --- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/schedule/on_tick.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/schedule/on_tick.test.w_compile_tf-aws.md @@ -49,11 +49,11 @@ module.exports = function({ $c1, $c2, $std_Duration, $util_Util }) { return $obj; } async handle() { - {((cond) => {if (!cond) throw new Error("assertion failed: c1.peek() == 0")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $c1.peek()),0)))}; - {((cond) => {if (!cond) throw new Error("assertion failed: c2.peek() == 0")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $c2.peek()),0)))}; + const c1val = (await $c1.peek()); + const c2val = (await $c2.peek()); (await $util_Util.sleep((await $std_Duration.fromSeconds(66)))); - {((cond) => {if (!cond) throw new Error("assertion failed: c1.peek() >= 1")})(((await $c1.peek()) >= 1))}; - {((cond) => {if (!cond) throw new Error("assertion failed: c2.peek() >= 1")})(((await $c2.peek()) >= 1))}; + {((cond) => {if (!cond) throw new Error("assertion failed: c1.peek() >= c1val + 1")})(((await $c1.peek()) >= (c1val + 1)))}; + {((cond) => {if (!cond) throw new Error("assertion failed: c2.peek() >= c2val + 1")})(((await $c2.peek()) >= (c2val + 1)))}; } } return $Closure3; @@ -508,7 +508,7 @@ class $Root extends $stdlib.std.Resource { const c2 = this.node.root.newAbstract("@winglang/sdk.cloud.Counter",this,"c2"); (from_cron.onTick(new $Closure1(this,"$Closure1"))); (from_rate.onTick(new $Closure2(this,"$Closure2"))); - this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"on tick is called both for rate and cron schedules",new $Closure3(this,"$Closure3"),({"timeout": (std.Duration.fromSeconds(120))})); + this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"on tick is called both for rate and cron schedules",new $Closure3(this,"$Closure3"),{ timeout: (std.Duration.fromSeconds(120)) }); } } const $App = $stdlib.core.App.for(process.env.WING_TARGET); diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/table/get.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/table/get.test.w_compile_tf-aws.md index 1417ffc8f1e..646e9724e18 100644 --- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/table/get.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/table/get.test.w_compile_tf-aws.md @@ -23,7 +23,7 @@ module.exports = function({ $table }) { } catch ($error_actual) { const actual = $error_actual.message; - {((cond) => {if (!cond) throw new Error("assertion failed: actual == expected")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(actual,expected)))}; + {((cond) => {if (!cond) throw new Error("assertion failed: actual.contains(expected)")})(actual.includes(expected))}; error = true; } {((cond) => {if (!cond) throw new Error("assertion failed: error")})(error)}; diff --git a/tools/hangar/__snapshots__/test_corpus/valid/redis.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/redis.test.w_compile_tf-aws.md index a6af688d70b..6dc9ca346c8 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/redis.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/redis.test.w_compile_tf-aws.md @@ -30,10 +30,6 @@ module.exports = function({ $queue, $r, $r2, $util_Util }) { return $obj; } async handle() { - const connection = (await $r.rawClient()); - (await connection.set("wing","does redis")); - const value = (await connection.get("wing")); - {((cond) => {if (!cond) throw new Error("assertion failed: value == \"does redis\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(value,"does redis")))}; (await $r2.set("wing","does redis again")); const value2 = (await $r2.get("wing")); {((cond) => {if (!cond) throw new Error("assertion failed: value2 == \"does redis again\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(value2,"does redis again")))}; @@ -623,7 +619,7 @@ class $Root extends $stdlib.std.Resource { _registerBind(host, ops) { if (ops.includes("handle")) { $Closure2._registerBindObject(queue, host, ["push"]); - $Closure2._registerBindObject(r, host, ["get", "rawClient"]); + $Closure2._registerBindObject(r, host, ["get"]); $Closure2._registerBindObject(r2, host, ["get", "set"]); } super._registerBind(host, ops);