genlayer 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/index.js +30856 -24164
- package/esbuild.config.dev +1 -0
- package/esbuild.config.prod +1 -0
- package/package.json +3 -1
- package/src/commands/general/init.ts +3 -3
- package/src/commands/general/start.ts +3 -3
- package/src/lib/clients/system.ts +1 -45
- package/src/lib/config/simulator.ts +1 -6
- package/src/lib/services/simulator.ts +29 -26
- package/tests/actions/init.test.ts +75 -1
- package/tests/actions/start.test.ts +14 -0
- package/tests/libs/system.test.ts +1 -76
- package/tests/services/simulator.test.ts +152 -49
|
@@ -8,8 +8,6 @@ import {
|
|
|
8
8
|
executeCommand,
|
|
9
9
|
openUrl,
|
|
10
10
|
checkCommand,
|
|
11
|
-
stopDockerContainer,
|
|
12
|
-
removeDockerContainer, listDockerContainers,
|
|
13
11
|
} from "../../src/lib/clients/system";
|
|
14
12
|
import {
|
|
15
13
|
DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX,
|
|
@@ -18,14 +16,13 @@ import {
|
|
|
18
16
|
import {
|
|
19
17
|
STARTING_TIMEOUT_ATTEMPTS,
|
|
20
18
|
DEFAULT_RUN_SIMULATOR_COMMAND,
|
|
21
|
-
DEFAULT_RUN_DOCKER_COMMAND,
|
|
22
|
-
DEFAULT_PULL_OLLAMA_COMMAND
|
|
23
19
|
} from "../../src/lib/config/simulator";
|
|
24
20
|
import { rpcClient } from "../../src/lib/clients/jsonRpcClient";
|
|
25
21
|
import * as semver from "semver";
|
|
26
|
-
import
|
|
27
|
-
|
|
22
|
+
import Docker from "dockerode";
|
|
23
|
+
import {VersionRequiredError} from "../../src/lib/errors/versionRequired";
|
|
28
24
|
|
|
25
|
+
vi.mock("dockerode");
|
|
29
26
|
vi.mock("fs");
|
|
30
27
|
vi.mock("path");
|
|
31
28
|
vi.mock("dotenv");
|
|
@@ -139,17 +136,6 @@ describe("SimulatorService - Basic Tests", () => {
|
|
|
139
136
|
expect(result).toEqual({ initialized: false, errorCode: "ERROR", errorMessage: nonRetryableError.message });
|
|
140
137
|
});
|
|
141
138
|
|
|
142
|
-
test("should execute the correct pull command based on simulator location", async () => {
|
|
143
|
-
const expectedCommand = DEFAULT_PULL_OLLAMA_COMMAND("/mock/home/genlayer-simulator");
|
|
144
|
-
vi.mocked(executeCommand).mockResolvedValueOnce({
|
|
145
|
-
stdout: "success",
|
|
146
|
-
stderr: "",
|
|
147
|
-
});
|
|
148
|
-
const result = await simulatorService.pullOllamaModel();
|
|
149
|
-
expect(result).toBe(true);
|
|
150
|
-
expect(executeCommand).toHaveBeenCalledWith(expectedCommand);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
139
|
test("should execute the correct run simulator command based on simulator location", async () => {
|
|
154
140
|
(executeCommand as Mock).mockResolvedValue({
|
|
155
141
|
stdout: "Simulator started",
|
|
@@ -190,6 +176,30 @@ describe("SimulatorService - Basic Tests", () => {
|
|
|
190
176
|
expect(result).toBe(mockResponse);
|
|
191
177
|
});
|
|
192
178
|
|
|
179
|
+
test("should return node missing version", async () => {
|
|
180
|
+
const unexpectedError = new VersionRequiredError('node', VERSION_REQUIREMENTS.node);
|
|
181
|
+
vi.spyOn(simulatorService, "checkVersion")
|
|
182
|
+
.mockRejectedValueOnce(unexpectedError)
|
|
183
|
+
.mockResolvedValueOnce();
|
|
184
|
+
|
|
185
|
+
await expect(simulatorService.checkVersionRequirements()).resolves.toStrictEqual({
|
|
186
|
+
"docker": "",
|
|
187
|
+
"node": VERSION_REQUIREMENTS.node
|
|
188
|
+
})
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("should return docker missing version", async () => {
|
|
192
|
+
const unexpectedError = new VersionRequiredError('node', VERSION_REQUIREMENTS.docker);
|
|
193
|
+
vi.spyOn(simulatorService, "checkVersion")
|
|
194
|
+
.mockResolvedValueOnce()
|
|
195
|
+
.mockRejectedValueOnce(unexpectedError)
|
|
196
|
+
|
|
197
|
+
await expect(simulatorService.checkVersionRequirements()).resolves.toStrictEqual({
|
|
198
|
+
"docker": VERSION_REQUIREMENTS.docker,
|
|
199
|
+
"node": ""
|
|
200
|
+
})
|
|
201
|
+
});
|
|
202
|
+
|
|
193
203
|
test("should throw an unexpected error when checking node version requirements", async () => {
|
|
194
204
|
const unexpectedError = new Error("Unexpected error (node)");
|
|
195
205
|
vi.spyOn(simulatorService, "checkVersion").mockRejectedValueOnce(unexpectedError);
|
|
@@ -210,31 +220,6 @@ describe("SimulatorService - Basic Tests", () => {
|
|
|
210
220
|
expect(requirementsInstalled.git).toBe(false);
|
|
211
221
|
});
|
|
212
222
|
|
|
213
|
-
test("should throw an unexpected error when checking docker installation requirement", async () => {
|
|
214
|
-
vi.mocked(checkCommand)
|
|
215
|
-
.mockResolvedValueOnce(undefined)
|
|
216
|
-
.mockRejectedValueOnce(new Error("Unexpected docker error"));
|
|
217
|
-
await expect(simulatorService.checkInstallRequirements()).rejects.toThrow("Unexpected docker error");
|
|
218
|
-
const requirementsInstalled = { git: false, docker: false };
|
|
219
|
-
expect(requirementsInstalled.docker).toBe(false);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
test("should stop and remove Docker containers with the specified prefix", async () => {
|
|
223
|
-
const mockContainers = [
|
|
224
|
-
DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX + "1",
|
|
225
|
-
DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX + "2"
|
|
226
|
-
];
|
|
227
|
-
vi.mocked(listDockerContainers).mockResolvedValue(mockContainers);
|
|
228
|
-
vi.mocked(stopDockerContainer).mockResolvedValue(undefined);
|
|
229
|
-
vi.mocked(removeDockerContainer).mockResolvedValue(undefined);
|
|
230
|
-
const result = await simulatorService.resetDockerContainers();
|
|
231
|
-
expect(result).toBe(true);
|
|
232
|
-
expect(stopDockerContainer).toHaveBeenCalledWith(DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX + "1");
|
|
233
|
-
expect(stopDockerContainer).toHaveBeenCalledWith(DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX + "2");
|
|
234
|
-
expect(removeDockerContainer).toHaveBeenCalledWith(DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX + "1");
|
|
235
|
-
expect(removeDockerContainer).toHaveBeenCalledWith(DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX + "2");
|
|
236
|
-
});
|
|
237
|
-
|
|
238
223
|
test("should retry when response is not 'OK' and reach sleep path", async () => {
|
|
239
224
|
vi.mocked(rpcClient.request).mockResolvedValue({ result: { status: "NOT_OK" } });
|
|
240
225
|
const result = await simulatorService.waitForSimulatorToBeReady(1);
|
|
@@ -261,14 +246,9 @@ describe("SimulatorService - Basic Tests", () => {
|
|
|
261
246
|
test("should call executeCommand if docker ps command fails", async () => {
|
|
262
247
|
vi.mocked(checkCommand)
|
|
263
248
|
.mockResolvedValueOnce(undefined)
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
vi.mocked(executeCommand).mockResolvedValueOnce({
|
|
267
|
-
stdout: '',
|
|
268
|
-
stderr: ''
|
|
269
|
-
});
|
|
249
|
+
|
|
250
|
+
|
|
270
251
|
const result = await simulatorService.checkInstallRequirements();
|
|
271
|
-
expect(executeCommand).toHaveBeenCalledWith(DEFAULT_RUN_DOCKER_COMMAND);
|
|
272
252
|
expect(result.docker).toBe(true);
|
|
273
253
|
expect(result.git).toBe(true);
|
|
274
254
|
});
|
|
@@ -302,3 +282,126 @@ describe("SimulatorService - Basic Tests", () => {
|
|
|
302
282
|
});
|
|
303
283
|
|
|
304
284
|
});
|
|
285
|
+
describe("SimulatorService - Docker Tests", () => {
|
|
286
|
+
let mockExec: Mock;
|
|
287
|
+
let mockGetContainer: Mock;
|
|
288
|
+
let mockListContainers: Mock;
|
|
289
|
+
let mockListImages: Mock;
|
|
290
|
+
let mockGetImage: Mock;
|
|
291
|
+
let mockPing: Mock;
|
|
292
|
+
|
|
293
|
+
beforeEach(() => {
|
|
294
|
+
vi.clearAllMocks();
|
|
295
|
+
mockExec = vi.fn().mockResolvedValueOnce({});
|
|
296
|
+
mockGetContainer = vi.mocked(Docker.prototype.getContainer);
|
|
297
|
+
mockListContainers = vi.mocked(Docker.prototype.listContainers);
|
|
298
|
+
mockListImages = vi.mocked(Docker.prototype.listImages);
|
|
299
|
+
mockGetImage = vi.mocked(Docker.prototype.getImage);
|
|
300
|
+
mockPing = vi.mocked(Docker.prototype.ping);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test("should pull the Ollama model", async () => {
|
|
304
|
+
mockGetContainer.mockReturnValueOnce({exec: mockExec} as unknown as Docker.Container);
|
|
305
|
+
|
|
306
|
+
const result = await simulatorService.pullOllamaModel();
|
|
307
|
+
|
|
308
|
+
expect(result).toBe(true);
|
|
309
|
+
expect(mockGetContainer).toHaveBeenCalledWith("ollama");
|
|
310
|
+
expect(mockExec).toHaveBeenCalledWith({
|
|
311
|
+
Cmd: ["ollama", "pull", "llama3"],
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
test("should stop and remove Docker containers with the specified prefix", async () => {
|
|
316
|
+
const mockContainers = [
|
|
317
|
+
{
|
|
318
|
+
Id: "container1",
|
|
319
|
+
Names: [`${DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX}container1`],
|
|
320
|
+
State: "running",
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
Id: "container2",
|
|
324
|
+
Names: [`${DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX}container2`],
|
|
325
|
+
State: "exited",
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
Id: "container3",
|
|
329
|
+
Names: ["/unrelated-container"],
|
|
330
|
+
State: "running",
|
|
331
|
+
},
|
|
332
|
+
];
|
|
333
|
+
|
|
334
|
+
mockListContainers.mockResolvedValue(mockContainers);
|
|
335
|
+
|
|
336
|
+
const mockStop = vi.fn().mockResolvedValue(undefined);
|
|
337
|
+
const mockRemove = vi.fn().mockResolvedValue(undefined);
|
|
338
|
+
mockGetContainer.mockImplementation(() => ({
|
|
339
|
+
stop: mockStop,
|
|
340
|
+
remove: mockRemove,
|
|
341
|
+
} as unknown as Docker.Container));
|
|
342
|
+
|
|
343
|
+
const result = await simulatorService.resetDockerContainers();
|
|
344
|
+
|
|
345
|
+
expect(result).toBe(true);
|
|
346
|
+
expect(mockListContainers).toHaveBeenCalledWith({ all: true });
|
|
347
|
+
|
|
348
|
+
// Ensure only the relevant containers were stopped and removed
|
|
349
|
+
expect(mockGetContainer).toHaveBeenCalledWith("container1");
|
|
350
|
+
expect(mockGetContainer).toHaveBeenCalledWith("container2");
|
|
351
|
+
expect(mockGetContainer).not.toHaveBeenCalledWith("container3");
|
|
352
|
+
|
|
353
|
+
expect(mockStop).toHaveBeenCalledTimes(1);
|
|
354
|
+
expect(mockRemove).toHaveBeenCalledTimes(2);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
test("should remove Docker images with the specified prefix", async () => {
|
|
358
|
+
const mockImages = [
|
|
359
|
+
{
|
|
360
|
+
Id: "image1",
|
|
361
|
+
RepoTags: [`${DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX}image1:latest`],
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
Id: "image2",
|
|
365
|
+
RepoTags: [`${DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX}image2:latest`],
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
Id: "image3",
|
|
369
|
+
RepoTags: ["unrelated-image:latest"],
|
|
370
|
+
},
|
|
371
|
+
];
|
|
372
|
+
|
|
373
|
+
mockListImages.mockResolvedValue(mockImages);
|
|
374
|
+
|
|
375
|
+
const mockRemove = vi.fn().mockResolvedValue(undefined);
|
|
376
|
+
mockGetImage.mockImplementation(() => ({
|
|
377
|
+
remove: mockRemove,
|
|
378
|
+
} as unknown as Docker.Image));
|
|
379
|
+
|
|
380
|
+
const result = await simulatorService.resetDockerImages();
|
|
381
|
+
|
|
382
|
+
expect(result).toBe(true);
|
|
383
|
+
expect(mockListImages).toHaveBeenCalled();
|
|
384
|
+
expect(mockGetImage).toHaveBeenCalledWith("image1");
|
|
385
|
+
expect(mockGetImage).toHaveBeenCalledWith("image2");
|
|
386
|
+
expect(mockGetImage).not.toHaveBeenCalledWith("image3");
|
|
387
|
+
expect(mockRemove).toHaveBeenCalledTimes(2);
|
|
388
|
+
expect(mockRemove).toHaveBeenCalledWith({ force: true });
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test("should execute command when docker is installed but is not available", async () => {
|
|
392
|
+
vi.mocked(checkCommand)
|
|
393
|
+
.mockResolvedValueOnce(undefined)
|
|
394
|
+
|
|
395
|
+
mockPing.mockRejectedValueOnce("");
|
|
396
|
+
await simulatorService.checkInstallRequirements();
|
|
397
|
+
expect(executeCommand).toHaveBeenCalledTimes(1);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
test("should throw an unexpected error when checking docker installation requirement", async () => {
|
|
401
|
+
vi.mocked(checkCommand)
|
|
402
|
+
.mockResolvedValueOnce(undefined)
|
|
403
|
+
.mockRejectedValue(undefined);
|
|
404
|
+
mockPing.mockRejectedValueOnce("Unexpected docker error");
|
|
405
|
+
await expect(simulatorService.checkInstallRequirements()).rejects.toThrow("Unexpected docker error");
|
|
406
|
+
});
|
|
407
|
+
});
|