Skip to content

Commit 232d833

Browse files
committed
add more tests and validation for node data
1 parent fc8e8a0 commit 232d833

File tree

7 files changed

+262
-44
lines changed

7 files changed

+262
-44
lines changed

packages/registrar_client/src/modules/farms.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,17 @@ export class Farms {
1313
this.client = client;
1414
}
1515

16-
async createFarm(farm: Partial<Farm>): Promise<FarmCreationResponse> {
17-
const twinID = farm.twin_id;
18-
if (!twinID) {
19-
throw new Error("TwinID is not found");
16+
async createFarm(farmName: string, dedicated: boolean, twinID: number): Promise<FarmCreationResponse> {
17+
if (twinID <= 0) {
18+
throw new Error("Invalid twinId");
2019
}
21-
const farmName = farm.farm_name;
2220
if (!farmName || farmName.length <= MIN_FARM_NAME_LENGTH || farmName.length >= MAX_FARM_NAME_LENGTH) {
2321
throw new Error(
2422
`Farm name must have minimum ${MIN_FARM_NAME_LENGTH} and maximum ${MAX_FARM_NAME_LENGTH} characters`,
2523
);
2624
}
25+
const farm = { farm_name: farmName, dedicated, twin_id: twinID };
2726
const headers = createAuthHeader(twinID, this.client.privateKey);
28-
2927
try {
3028
const data = await this.client.post<FarmCreationResponse>(this.farmUri, farm, { headers });
3129
return data;

packages/registrar_client/src/modules/nodes.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export class Nodes {
1818
}
1919

2020
async registerNode(node: NodeRegistrationRequest): Promise<NodeRegistrationResponse> {
21+
this._validateNodeData(node);
2122
const headers = createAuthHeader(node.twin_id, this.client.privateKey);
2223
try {
2324
const data = await this.client.post<NodeRegistrationResponse>(this.nodeUri, node, { headers });
@@ -66,4 +67,61 @@ export class Nodes {
6667
throw new Error(`Failed to report node uptime: ${e.response?.status} ${e.response?.statusText}`);
6768
}
6869
}
70+
71+
_validateNodeData(node: NodeRegistrationRequest): void {
72+
if (node.twin_id <= 0) {
73+
throw new Error("Invalid node: twinId");
74+
}
75+
if (node.farm_id <= 0) {
76+
throw new Error("Invalid node: farmId");
77+
}
78+
this._validateResources(node.resources);
79+
this._validateLocation(node.location);
80+
node.interfaces.forEach(iface => {
81+
this._validateIp(iface.ips);
82+
this._validateMac(iface.mac);
83+
});
84+
}
85+
86+
_validateResources(resources: any): void {
87+
["cru", "hru", "mru", "sru"].forEach(key => {
88+
if (resources[key] < 0) {
89+
throw new Error(`Invalid resources: ${key}`);
90+
}
91+
});
92+
}
93+
94+
_validateLocation(location: any): void {
95+
["city", "country", "latitude", "longitude"].forEach(key => {
96+
if (location[key].length === 0) {
97+
throw new Error(`Invalid location: ${key}`);
98+
}
99+
});
100+
}
101+
102+
_validateIp(ip: string): void {
103+
const parts = ip.split(".");
104+
if (parts.length !== 4) {
105+
throw new Error("Invalid interfaces: ips");
106+
}
107+
parts.forEach(part => {
108+
const num = parseInt(part);
109+
if (isNaN(num) || num < 0 || num > 255) {
110+
throw new Error("Invalid interfaces: ips");
111+
}
112+
});
113+
}
114+
115+
_validateMac(mac: string): void {
116+
const parts = mac.split(":");
117+
if (parts.length !== 6) {
118+
throw new Error("Invalid interfaces: mac");
119+
}
120+
parts.forEach(part => {
121+
const num = parseInt(part, 16);
122+
if (isNaN(num) || num < 0 || num > 255) {
123+
throw new Error("Invalid interfaces: mac");
124+
}
125+
});
126+
}
69127
}

packages/registrar_client/tests/integration_tests/account.spec.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { describe, test, expect } from "@jest/globals";
22
import tweetnacl from "tweetnacl";
33
import base64 from "base64-js";
44
import { RegistrarClient } from "../../src/client/client";
5-
import { UpdateAccountRequest } from "../../src/modules/account/types";
5+
import { UpdateAccountRequest } from "../../src/types/account";
66

77
describe("test account module", () => {
88
const keyPair = tweetnacl.sign.keyPair();
99
const publicKey = base64.fromByteArray(keyPair.publicKey);
1010
const privateKey = base64.fromByteArray(keyPair.secretKey);
1111

12-
const client = new RegistrarClient({ baseURL: "http://registrar:8080/v1", privateKey: privateKey });
12+
const client = new RegistrarClient({ baseURL: "http://localhost:8080/v1", privateKey: privateKey });
1313

1414
let twinID = 1;
1515
test("create account", async () => {
@@ -20,6 +20,10 @@ describe("test account module", () => {
2020
}
2121
});
2222

23+
test("create account with same private key", async () => {
24+
await expect(client.accounts.createAccount({})).rejects.toThrowError("Failed to create account: 409 Conflict");
25+
});
26+
2327
test("get account by public key", async () => {
2428
const account = await client.accounts.getAccountByPublicKey(publicKey);
2529
expect(account).not.toBeNull();

packages/registrar_client/tests/integration_tests/farm.spec.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ describe("test farm module", () => {
77
const keyPair = tweetnacl.sign.keyPair();
88
const privateKey = base64.fromByteArray(keyPair.secretKey);
99

10-
const client = new RegistrarClient({ baseURL: "http://registrar:8080/v1", privateKey: privateKey });
10+
const client = new RegistrarClient({ baseURL: "http://localhost:8080/v1", privateKey: privateKey });
1111

1212
let twinID = 1;
1313
let farmID = 1;
@@ -18,11 +18,50 @@ describe("test farm module", () => {
1818
twinID = account!.twin_id;
1919

2020
const farmName = `test-${Date.now()}`;
21-
const res = await client.farms.createFarm({ twin_id: twinID, farm_name: farmName });
21+
const res = await client.farms.createFarm(farmName, false, twinID);
2222
expect(res).not.toBeNull();
2323

2424
farmID = res!.farm_id;
2525
});
26+
27+
test("create farm with invalid farm name", async () => {
28+
const farmName = "";
29+
await expect(client.farms.createFarm(farmName, false, twinID)).rejects.toThrowError(
30+
"Farm name must have minimum 1 and maximum 40 characters",
31+
);
32+
33+
const farmName2 = "a".repeat(41);
34+
await expect(client.farms.createFarm(farmName2, false, twinID)).rejects.toThrowError(
35+
"Farm name must have minimum 1 and maximum 40 characters",
36+
);
37+
});
38+
39+
test("create farm with invalid twin id", async () => {
40+
await expect(client.farms.createFarm("test", false, 0)).rejects.toThrowError("Invalid twinId");
41+
await expect(client.farms.createFarm("test", false, -1)).rejects.toThrowError("Invalid twinId");
42+
});
43+
44+
test("create farm with non-existing twin id", async () => {
45+
await expect(client.farms.createFarm("test",false, twinID+1)).rejects.toThrowError(
46+
"Failed to create farm: 404 Not Found",
47+
);
48+
});
49+
50+
test("create farm with existing farm name with same twinId", async () => {
51+
const farmName = `test-${Date.now()}`;
52+
await client.farms.createFarm(farmName, false, twinID);
53+
await expect(client.farms.createFarm(farmName, true, twinID)).rejects.toThrowError(
54+
"Failed to create farm: 409 Conflict",
55+
);
56+
});
57+
58+
test("create farm with existing farm name with different twinId", async () => {
59+
const farmName = `test-${Date.now()}`;
60+
await client.farms.createFarm(farmName, false, twinID);
61+
await expect(client.farms.createFarm(farmName, false, twinID - 1)).rejects.toThrowError(
62+
"Failed to create farm: 401 Unauthorized",
63+
);
64+
});
2665

2766
test("list farms without filters", async () => {
2867
const farms = await client.farms.listFarms({});

packages/registrar_client/tests/integration_tests/node.spec.ts

Lines changed: 82 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, test, expect } from "@jest/globals";
2-
import { NodeRegistrationRequest, UptimeReportRequest, NodesFilter } from "../../src/modules/node/types";
2+
import { NodeRegistrationRequest, UptimeReportRequest, NodesFilter } from "../../src/types/node";
33
import { RegistrarClient } from "../../src/client/client";
44
import tweetnacl from "tweetnacl";
55
import base64 from "base64-js";
@@ -8,52 +8,104 @@ describe("test node module", () => {
88
const keyPair = tweetnacl.sign.keyPair();
99
const privateKey = base64.fromByteArray(keyPair.secretKey);
1010

11-
const client = new RegistrarClient({ baseURL: "http://registrar:8080/v1", privateKey: privateKey });
11+
const client = new RegistrarClient({ baseURL: "http://localhost:8080/v1", privateKey: privateKey });
1212

1313
let twinID = 1;
1414
let nodeID = 1;
1515
let farmID = 1;
16+
const dummyNode: Partial<NodeRegistrationRequest> = {
17+
interfaces: [
18+
{
19+
name: "eth0",
20+
mac: "00:1A:2B:3C:4D:5E",
21+
ips: "10.0.0.1",
22+
},
23+
],
24+
location: {
25+
city: "Amsterdam",
26+
country: "Netherlands",
27+
latitude: "52.3676",
28+
longitude: "4.9041",
29+
},
30+
resources: {
31+
cru: 4,
32+
hru: 1000000,
33+
mru: 8192,
34+
sru: 512000,
35+
},
36+
secure_boot: true,
37+
serial_number: "SN-123456789",
38+
virtualized: true,
39+
};
1640

1741
test("create node", async () => {
1842
const account = await client.accounts.createAccount({});
1943
expect(account).not.toBeNull();
2044
twinID = account!.twin_id;
2145

22-
const farm = await client.farms.createFarm({ twin_id: twinID, farm_name: `test-${Date.now()}` });
46+
const farm = await client.farms.createFarm(`test-${Date.now()}`, false, twinID);
2347
expect(farm).not.toBeNull();
2448
farmID = farm!.farm_id;
25-
const dummyNode: NodeRegistrationRequest = {
26-
twin_id: twinID,
27-
farm_id: farmID,
28-
interfaces: [
29-
{
30-
name: "eth0",
31-
mac: "00:1A:2B:3C:4D:5E",
32-
ips: "10.0.0.1",
33-
},
34-
],
35-
location: {
36-
city: "Amsterdam",
37-
country: "Netherlands",
38-
latitude: "52.3676",
39-
longitude: "4.9041",
40-
},
41-
resources: {
42-
cru: 4,
43-
hru: 1000000,
44-
mru: 8192,
45-
sru: 512000,
46-
},
47-
secure_boot: true,
48-
serial_number: "SN-123456789",
49-
virtualized: true,
50-
};
51-
const res = await client.nodes.registerNode(dummyNode);
49+
50+
dummyNode.twin_id = twinID;
51+
dummyNode.farm_id = farmID;
52+
const res = await client.nodes.registerNode(dummyNode as NodeRegistrationRequest);
5253
expect(res).not.toBeNull();
5354

5455
nodeID = res!.node_id;
5556
});
5657

58+
test("create node with duplicate twin id", async () => {
59+
dummyNode.twin_id = twinID;
60+
expect(client.nodes.registerNode(dummyNode as NodeRegistrationRequest)).rejects.toThrowError(
61+
"Failed to register node: 409 Conflict",
62+
);
63+
});
64+
test("create node with non-existed twin id", async () => {
65+
dummyNode.twin_id = 9999999999999;
66+
await expect(client.nodes.registerNode(dummyNode as NodeRegistrationRequest)).rejects.toThrowError(
67+
"Failed to register node: 404 Not Found",
68+
);
69+
});
70+
71+
test("create node with non-existed farm id", async () => {
72+
dummyNode.twin_id = twinID;
73+
dummyNode.farm_id = 9999999999999;
74+
await expect(client.nodes.registerNode(dummyNode as NodeRegistrationRequest)).rejects.toThrowError(
75+
"Failed to register node: 400 Bad Request",
76+
);
77+
});
78+
79+
test("create node with invalid twin id", async () => {
80+
dummyNode.twin_id = 0;
81+
dummyNode.farm_id = farmID;
82+
await expect(client.nodes.registerNode(dummyNode as NodeRegistrationRequest)).rejects.toThrowError(
83+
"Invalid node: twinId",
84+
);
85+
});
86+
87+
test("create node with invalid farm id", async () => {
88+
dummyNode.twin_id = twinID;
89+
dummyNode.farm_id = 0;
90+
await expect(client.nodes.registerNode(dummyNode as NodeRegistrationRequest)).rejects.toThrowError(
91+
"Invalid node: farmId",
92+
);
93+
});
94+
95+
test("create node with invalid location", async () => {
96+
dummyNode.twin_id = twinID;
97+
dummyNode.farm_id = farmID;
98+
dummyNode.location = {
99+
city: "Amsterdam",
100+
country: "Netherlands",
101+
latitude: "",
102+
longitude: "",
103+
};
104+
await expect(client.nodes.registerNode(dummyNode as NodeRegistrationRequest)).rejects.toThrowError(
105+
"Invalid location: latitude",
106+
);
107+
});
108+
57109
test("list nodes without filters", async () => {
58110
const nodes = await client.nodes.listNodes({});
59111
expect(nodes).not.toBeNull();
@@ -121,9 +173,5 @@ describe("test node module", () => {
121173
};
122174
const res = await client.nodes.reportNodeUptime(nodeID, twinID, uptime);
123175
expect(res).not.toBeNull();
124-
const node = await client.nodes.getNode(nodeID);
125-
expect(node).not.toBeNull();
126-
console.log(node);
127-
expect(node?.uptime.length).toBeGreaterThan(0);
128176
});
129177
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { describe, test, expect } from "@jest/globals";
2+
import { RegistrarClient } from "../../src/client/client";
3+
4+
describe("test zos module", () => {
5+
const client = new RegistrarClient({ baseURL: "http://localhost:8080/v1", privateKey: "private_key" });
6+
7+
test("get zos version", async () => {
8+
const zos = await client.zos.getZosVersion();
9+
expect(zos).not.toBeNull();
10+
});
11+
});

0 commit comments

Comments
 (0)