Skip to content

Commit 0dcfd3d

Browse files
Adding more test cases (#70)
* Adding more tests * Adding more test cases - conditional upsert test - bulk set and delete test - conflict/exception test - doRequest test * Added test cases for type system/directive * Updated upsert and typeSystem tests * Adding ACL tests * removing commented sleep function * Minor changes - Reduced jest timeout to 1 minute per test - Using dgraph address from helper file - Removed debugging console logs * Code cleanup * Code cleanup and updated test labels * Adding line break for long error messages * Moved errors from handler to acl test
1 parent 48c9002 commit 0dcfd3d

File tree

9 files changed

+812
-44
lines changed

9 files changed

+812
-44
lines changed

tests/client.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as dgraph from "../src";
22

3-
import { createClient } from "./helper";
3+
import { createClient, createClientStub } from "./helper";
44

55
// tslint:disable no-console
66
describe("client", () => {
@@ -20,7 +20,7 @@ describe("client", () => {
2020
console.log = jest.fn();
2121

2222
const msg = "test message";
23-
const client = createClient();
23+
const client = createClient(createClientStub());
2424

2525
client.debug(msg);
2626
expect(console.log).not.toHaveBeenCalled();

tests/helper.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ import * as dgraph from "../src";
66
export const SERVER_ADDR = process.env.DGRAPH_SERVER_ADDR || "localhost:9080";
77
export const SERVER_CREDENTIALS = grpc.credentials.createInsecure();
88

9-
export function createClient(): dgraph.DgraphClient {
10-
return new dgraph.DgraphClient(new dgraph.DgraphClientStub(SERVER_ADDR, SERVER_CREDENTIALS));
9+
export function createClientStub(): dgraph.DgraphClientStub {
10+
return new dgraph.DgraphClientStub(SERVER_ADDR, SERVER_CREDENTIALS);
11+
}
12+
13+
export function createClient(clientStub: dgraph.DgraphClientStub): dgraph.DgraphClient {
14+
return new dgraph.DgraphClient(clientStub);
1115
}
1216

1317
export function setSchema(c: dgraph.DgraphClient, schema: string): Promise<dgraph.Payload> {
@@ -43,3 +47,22 @@ export function wait(time: number): Promise<void> {
4347
);
4448
});
4549
}
50+
51+
export async function tryUpsert(client: dgraph.DgraphClient, query: string, mutation: dgraph.Mutation, blankNodeLabel: string)
52+
: Promise<void> {
53+
const txn = client.newTxn();
54+
55+
const req = new dgraph.Request();
56+
req.setQuery(query);
57+
req.setMutationsList([mutation]);
58+
req.setCommitNow(true);
59+
60+
try {
61+
// Update account only if matching uid found.
62+
const response = await txn.doRequest(req);
63+
const uid = response.getUidsMap().get(blankNodeLabel);
64+
expect(uid).not.toEqual("");
65+
} finally {
66+
await txn.discard();
67+
}
68+
}

tests/integration/acl.spec.ts

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import { exec } from "child_process";
2+
import { promisify } from "util";
3+
4+
import * as dgraph from "../../src";
5+
import { createClient, createClientStub, SERVER_ADDR, setSchema, setup, wait } from "../helper";
6+
7+
const JEST_TIMEOUT = 60 * 1000; // 1 minute in milliseconds
8+
const WAIT_FOR_SIX_SECONDS = 6 * 1000; // 6 seconds in milliseconds
9+
10+
// tslint:disable-next-line no-string-based-set-timeout
11+
jest.setTimeout(JEST_TIMEOUT);
12+
13+
let client: dgraph.DgraphClient;
14+
let aclClient: dgraph.DgraphClient;
15+
16+
const GROOT_PWD = "password";
17+
const USERID = "alice";
18+
const USERPWD = "alicepassword";
19+
const PRED = "name";
20+
const DEV_GROUP = "dev";
21+
22+
// tslint:disable-next-line mocha-no-side-effect-code
23+
const execute = promisify(exec);
24+
25+
// tslint:disable-next-line mocha-no-side-effect-code
26+
const QUERY_PERMISSION_DENIED = new Error("7 PERMISSION_DENIED:\
27+
unauthorized to query the predicate: unauthorized to do Read on predicate name");
28+
// tslint:disable-next-line mocha-no-side-effect-code
29+
const MUTATE_PERMISSION_DENIED = new Error("7 PERMISSION_DENIED:\
30+
unauthorized to mutate the predicate: unauthorized to do Write on predicate name");
31+
// tslint:disable-next-line mocha-no-side-effect-code
32+
const ALTER_PERMISSION_DENIED = new Error("7 PERMISSION_DENIED:\
33+
unauthorized to alter the predicate: unauthorized to do Modify on predicate name");
34+
35+
async function cmd(command: string) {
36+
try {
37+
await execute(command);
38+
} catch (err) {
39+
fail(`Failed to execute command:\n\t${command}\nError: ${err}`);
40+
}
41+
}
42+
43+
async function insertSampleData() {
44+
const txn = client.newTxn();
45+
try {
46+
const mu = new dgraph.Mutation();
47+
mu.setSetNquads(`
48+
_:prashant <${PRED}> "Prashant" .
49+
`);
50+
mu.setCommitNow(true);
51+
const res = await txn.mutate(mu);
52+
const uid = res.getUidsMap().get("prashant");
53+
expect(uid).toBeDefined();
54+
} finally {
55+
await txn.discard();
56+
}
57+
}
58+
59+
async function loginUser(): Promise<dgraph.DgraphClient> {
60+
const aclClientStub = createClientStub();
61+
try {
62+
await aclClientStub.login(USERID, USERPWD);
63+
} catch (e) {
64+
fail(`Login error: \tUSERID - ${USERID} \tUSERPWD - ${USERPWD}\n${e}`);
65+
}
66+
return createClient(aclClientStub);
67+
}
68+
69+
async function aclSetup() {
70+
client = await setup();
71+
await setSchema(client, `
72+
${PRED}: string .
73+
`);
74+
await insertSampleData();
75+
await addUser();
76+
await addGroup();
77+
await addUserToGroup();
78+
aclClient = await loginUser();
79+
}
80+
81+
async function addUser() {
82+
const command = `dgraph acl -a ${SERVER_ADDR} add -u ${USERID} -p ${USERPWD} -x ${GROOT_PWD}`;
83+
await cmd(command);
84+
}
85+
86+
async function addGroup() {
87+
const command = `dgraph acl -a ${SERVER_ADDR} add -g ${DEV_GROUP} -x ${GROOT_PWD}`;
88+
await cmd(command);
89+
}
90+
91+
async function addUserToGroup() {
92+
const command = `dgraph acl -a ${SERVER_ADDR} mod -u ${USERID} -l ${DEV_GROUP} -x ${GROOT_PWD}`;
93+
await cmd(command);
94+
}
95+
96+
async function changePermission(permission: number) {
97+
const command = `dgraph acl -a ${SERVER_ADDR} mod -g ${DEV_GROUP} -p ${PRED} -m ${permission} -x ${GROOT_PWD}`;
98+
await cmd(command);
99+
await wait(WAIT_FOR_SIX_SECONDS);
100+
}
101+
102+
async function tryReading(): Promise<Boolean> {
103+
let success: Boolean;
104+
const txn = aclClient.newTxn();
105+
const query = `{
106+
me(func: has(${PRED})) {
107+
uid
108+
${PRED}
109+
}
110+
}`;
111+
try {
112+
const res: dgraph.Response = await txn.query(query);
113+
expect(res.getJson().me).not.toHaveLength(0);
114+
success = true;
115+
} catch (e) {
116+
expect(e).toEqual(QUERY_PERMISSION_DENIED);
117+
success = false;
118+
}
119+
return success;
120+
}
121+
122+
async function tryWriting(): Promise<Boolean> {
123+
let success: Boolean;
124+
const txn = aclClient.newTxn();
125+
try {
126+
const mu = new dgraph.Mutation();
127+
mu.setSetNquads(`
128+
_:ashish <${PRED}> "Ashish" .
129+
`);
130+
mu.setCommitNow(true);
131+
const res = await txn.mutate(mu);
132+
const uid = res.getUidsMap().get("ashish");
133+
expect(uid).toBeDefined();
134+
success = true;
135+
} catch (e) {
136+
expect(e).toEqual(MUTATE_PERMISSION_DENIED);
137+
success = false;
138+
}
139+
return success;
140+
}
141+
142+
async function tryAltering(): Promise<Boolean> {
143+
let success: Boolean;
144+
try {
145+
const operation = new dgraph.Operation();
146+
operation.setSchema(`
147+
${PRED}: string @index(exact, term) .
148+
`);
149+
await aclClient.alter(operation);
150+
success = true;
151+
} catch (e) {
152+
expect(e).toEqual(ALTER_PERMISSION_DENIED);
153+
success = false;
154+
}
155+
return success;
156+
}
157+
158+
describe("ACL tests", () => {
159+
it("only has read access", async () => {
160+
await aclSetup();
161+
await changePermission(4);
162+
await expect(tryReading()).resolves.toBe(true);
163+
await expect(tryWriting()).resolves.toBe(false);
164+
await expect(tryAltering()).resolves.toBe(false);
165+
});
166+
167+
it("only has write access", async () => {
168+
await aclSetup();
169+
await changePermission(2);
170+
await expect(tryReading()).resolves.toBe(false);
171+
await expect(tryWriting()).resolves.toBe(true);
172+
await expect(tryAltering()).resolves.toBe(false);
173+
});
174+
175+
it("only has modify access", async () => {
176+
await aclSetup();
177+
await changePermission(1);
178+
await expect(tryReading()).resolves.toBe(false);
179+
await expect(tryWriting()).resolves.toBe(false);
180+
await expect(tryAltering()).resolves.toBe(true);
181+
});
182+
183+
afterEach(async () => {
184+
await changePermission(0);
185+
});
186+
});
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import * as dgraph from "../../src";
2+
3+
import { setSchema, setup } from "../helper";
4+
5+
let client: dgraph.DgraphClient;
6+
7+
type Profile = {
8+
name: string;
9+
email: string;
10+
age: number;
11+
};
12+
const profiles: Profile[] = [
13+
{ name: "Aman", email: "[email protected]", age: 26 },
14+
{ name: "Animesh", email: "[email protected]", age: 24 },
15+
{ name: "Ashish", email: "[email protected]", age: 26 },
16+
{ name: "Prashant", email: "[email protected]", age: 23 },
17+
];
18+
const names: string[] = [];
19+
profiles.forEach((profile: Profile): void => {
20+
names.push(profile.name);
21+
});
22+
23+
function getMutationNquads() {
24+
let mutationNquads = "";
25+
profiles.forEach((profile: Profile) => {
26+
const blankNodeLabel = `_:${profile.name.toLocaleLowerCase()}`;
27+
mutationNquads += `
28+
${blankNodeLabel} <name> "${profile.name}" .
29+
${blankNodeLabel} <email> "${profile.email}" .
30+
${blankNodeLabel} <age> "${profile.age}"^^<xs:int> .
31+
`;
32+
});
33+
return mutationNquads;
34+
}
35+
36+
async function doBulkSet() {
37+
const txn = client.newTxn();
38+
const mu = new dgraph.Mutation();
39+
mu.setSetNquads(getMutationNquads());
40+
41+
const req = new dgraph.Request();
42+
req.addMutations(mu);
43+
req.setCommitNow(true);
44+
45+
await txn.doRequest(req);
46+
47+
const res = await readProfiles();
48+
expect(res).toEqual({all: profiles});
49+
}
50+
51+
async function readProfiles() {
52+
const query = `query {
53+
all(func: anyofterms(name, "${names.join(", ")}"), orderasc: name) {
54+
name
55+
email
56+
age
57+
}
58+
}`;
59+
const req = new dgraph.Request();
60+
req.setQuery(query);
61+
const res = await client.newTxn().doRequest(req);
62+
63+
return res.getJson();
64+
}
65+
66+
async function doBulkDelete() {
67+
const txn = client.newTxn();
68+
const query = `query {
69+
a as var(func: eq(name, "Prashant"))
70+
}`;
71+
const mu = new dgraph.Mutation();
72+
mu.setDelNquads(`
73+
uid(a) <name> * .
74+
uid(a) <email> * .
75+
uid(a) <age> * .
76+
`);
77+
78+
const req = new dgraph.Request();
79+
req.addMutations(mu);
80+
req.setQuery(query);
81+
req.setCommitNow(true);
82+
83+
await txn.doRequest(req);
84+
85+
const res = await readProfiles();
86+
const tempProfiles = profiles;
87+
tempProfiles.pop();
88+
expect(res).toEqual({ all: tempProfiles });
89+
}
90+
91+
describe("Bulk operations using doRequest", () => {
92+
it("successfully perform bulk set", async () => {
93+
client = await setup();
94+
await setSchema(client, `
95+
name: string @index(term) .
96+
email: string @index(exact) .
97+
age: int @index(int) .
98+
`);
99+
100+
await doBulkSet();
101+
});
102+
103+
it("successfully perform bulk delete", async () => {
104+
client = await setup();
105+
await setSchema(client, `
106+
name: string @index(term) .
107+
email: string @index(exact) .
108+
age: int @index(int) .
109+
`);
110+
111+
await doBulkSet();
112+
await doBulkDelete();
113+
});
114+
});

0 commit comments

Comments
 (0)