From ca3502009be957bbb0d7f4f4cd9d47d054bdedb2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dandelion=20Man=C3=A9?=
Date: Fri, 2 Mar 2018 13:45:52 -0800
Subject: [PATCH] Create an 'advancedMealGraph' test case (#54)
Create an 'advancedMealGraph' test case
The advancedMealGraph will be a grab-all that holds all advanced and
edge behaviors, e.g. the crab-self-referential loop, and the case
where there are multiple directed edges between the same two nodes.
Aggregating them into one test case will make it easier to test more
complex behaviors, like graph merging and serialization, on the
edge case graphs. However, it's still nice to have the simple graph
so that we can test simple things too. The specific tests for edge
case behavior are left mostly unchanged, in that they start from the
simple graph and add just the advanced feature that they want to test.
---
src/backend/graph.test.js | 134 +++++++++++++++++++++++++-------------
1 file changed, 88 insertions(+), 46 deletions(-)
diff --git a/src/backend/graph.test.js b/src/backend/graph.test.js
index 1359ed6..a06c119 100644
--- a/src/backend/graph.test.js
+++ b/src/backend/graph.test.js
@@ -90,7 +90,7 @@ describe("graph", () => {
dst: mealNode().address,
payload: {},
});
- const mealGraph = () =>
+ const simpleMealGraph = () =>
new Graph()
.addNode(heroNode())
.addNode(bananasNode())
@@ -103,14 +103,40 @@ describe("graph", () => {
.addEdge(crabIngredientEdge())
.addEdge(eatEdge());
+ const crabLoopEdge = () => ({
+ address: makeAddress("crab-self-assessment"),
+ src: crabNode().address,
+ dst: crabNode().address,
+ payload: {evaluation: "not effective at avoiding hero"},
+ });
+
+ const duplicateCookEdge = () => ({
+ address: makeAddress("hero_of_time#0@again_cooks@seafood_fruit_mix#3"),
+ src: mealNode().address,
+ dst: heroNode().address,
+ payload: {
+ crit: true,
+ saveScummed: true,
+ },
+ });
+
+ const advancedMealGraph = () =>
+ simpleMealGraph()
+ .addEdge(crabLoopEdge())
+ .addEdge(duplicateCookEdge());
+
describe("construction", () => {
it("works for a simple graph", () => {
- mealGraph();
+ simpleMealGraph();
+ });
+
+ it("works for an advanced graph", () => {
+ advancedMealGraph();
});
it("forbids adding an edge with dangling `dst`", () => {
expect(() => {
- mealGraph().addEdge({
+ simpleMealGraph().addEdge({
address: makeAddress(
"treasure_octorok#5@helps_cook@seafood_fruit_mix#3"
),
@@ -123,7 +149,7 @@ describe("graph", () => {
it("forbids adding an edge with dangling `src`", () => {
expect(() => {
- mealGraph().addEdge({
+ simpleMealGraph().addEdge({
address: makeAddress("health_bar#6@healed_by@seafood_fruit_mix#3"),
src: makeAddress("health_bar#6"),
dst: mealNode().address,
@@ -134,15 +160,22 @@ describe("graph", () => {
});
describe("getting nodes and edges", () => {
- it("correctly gets nodes that exist", () => {
- const g = mealGraph();
+ it("correctly gets nodes in the simple graph", () => {
+ const g = simpleMealGraph();
[heroNode(), bananasNode(), crabNode(), mealNode()].forEach((x) => {
expect(g.getNode(x.address)).toEqual(x);
});
});
- it("correctly gets edges that exist", () => {
- const g = mealGraph();
+ it("correctly gets nodes in the advanced graph", () => {
+ const g = advancedMealGraph();
+ [heroNode(), bananasNode(), crabNode(), mealNode()].forEach((x) => {
+ expect(g.getNode(x.address)).toEqual(x);
+ });
+ });
+
+ it("correctly gets edges in the simple graph", () => {
+ const g = simpleMealGraph();
[
pickEdge(),
grabEdge(),
@@ -155,15 +188,31 @@ describe("graph", () => {
});
});
+ it("correctly gets edges in the advanced graph", () => {
+ const g = advancedMealGraph();
+ [
+ pickEdge(),
+ grabEdge(),
+ cookEdge(),
+ bananasIngredientEdge(),
+ crabIngredientEdge(),
+ eatEdge(),
+ crabLoopEdge(),
+ duplicateCookEdge(),
+ ].forEach((x) => {
+ expect(g.getEdge(x.address)).toEqual(x);
+ });
+ });
+
it("returns `undefined` for nodes that do not exist", () => {
expect(
- mealGraph().getNode(makeAddress("treasure_octorok#5"))
+ simpleMealGraph().getNode(makeAddress("treasure_octorok#5"))
).toBeUndefined();
});
it("returns `undefined` for edges that do not exist", () => {
expect(
- mealGraph().getNode(
+ simpleMealGraph().getNode(
makeAddress("treasure_octorok#5@helps_cook@seafood_fruit_mix#3")
)
).toBeUndefined();
@@ -171,7 +220,7 @@ describe("graph", () => {
it("forbids adding a node with existing address", () => {
expect(() =>
- mealGraph().addNode({
+ simpleMealGraph().addNode({
address: crabNode().address,
payload: {anotherCrab: true},
})
@@ -180,7 +229,7 @@ describe("graph", () => {
it("forbids adding an edge with existing address", () => {
expect(() =>
- mealGraph().addEdge({
+ simpleMealGraph().addEdge({
address: cookEdge().address,
src: crabNode().address,
dst: crabNode().address,
@@ -190,33 +239,18 @@ describe("graph", () => {
});
it("allows creating self-loops", () => {
- const g = mealGraph();
- const crabLoop = {
- address: makeAddress("crab-self-assessment"),
- src: crabNode().address,
- dst: crabNode().address,
- payload: {evaluation: "not effective at avoiding hero"},
- };
- g.addEdge(crabLoop);
- expect(g.getOutEdges(crabNode().address)).toContainEqual(crabLoop);
- expect(g.getInEdges(crabNode().address)).toContainEqual(crabLoop);
+ const g = simpleMealGraph();
+ g.addEdge(crabLoopEdge());
+ expect(g.getOutEdges(crabNode().address)).toContainEqual(
+ crabLoopEdge()
+ );
+ expect(g.getInEdges(crabNode().address)).toContainEqual(crabLoopEdge());
});
it("allows creating multiple edges between the same nodes", () => {
- const g = mealGraph();
- const critCookEdge = () => ({
- address: makeAddress(
- "hero_of_time#0@again_cooks@seafood_fruit_mix#3"
- ),
- src: mealNode().address,
- dst: heroNode().address,
- payload: {
- crit: true,
- saveScummed: true,
- },
- });
- g.addEdge(critCookEdge());
- [cookEdge(), critCookEdge()].forEach((e) => {
+ const g = simpleMealGraph();
+ g.addEdge(duplicateCookEdge());
+ [cookEdge(), duplicateCookEdge()].forEach((e) => {
expect(g.getOutEdges(mealNode().address)).toContainEqual(e);
expect(g.getEdge(e.address)).toEqual(e);
});
@@ -246,7 +280,7 @@ describe("graph", () => {
// the namespaces to be forced to be disjoint. In that case, we can
// certainly change these tests.
it("allows adding an edge with an existing node's address", () => {
- mealGraph().addEdge({
+ simpleMealGraph().addEdge({
address: crabNode().address,
src: crabNode().address,
dst: crabNode().address,
@@ -254,7 +288,7 @@ describe("graph", () => {
});
});
it("allows adding a node with an existing edge's address", () => {
- mealGraph().addNode({
+ simpleMealGraph().addNode({
address: cookEdge().address,
payload: {},
});
@@ -266,40 +300,48 @@ describe("graph", () => {
const nodeAndExpectedEdgePairs = [
[heroNode(), [eatEdge()]],
[bananasNode(), [pickEdge()]],
- [crabNode(), [grabEdge()]],
+ [crabNode(), [grabEdge(), crabLoopEdge()]],
[
mealNode(),
- [bananasIngredientEdge(), crabIngredientEdge(), cookEdge()],
+ [
+ bananasIngredientEdge(),
+ crabIngredientEdge(),
+ cookEdge(),
+ duplicateCookEdge(),
+ ],
],
];
nodeAndExpectedEdgePairs.forEach(([node, expectedEdges]) => {
- const actual = mealGraph().getOutEdges(node.address);
+ const actual = advancedMealGraph().getOutEdges(node.address);
expectSameSorted(actual, expectedEdges);
});
});
it("gets in-edges", () => {
const nodeAndExpectedEdgePairs = [
- [heroNode(), [pickEdge(), grabEdge(), cookEdge()]],
+ [
+ heroNode(),
+ [pickEdge(), grabEdge(), cookEdge(), duplicateCookEdge()],
+ ],
[bananasNode(), [bananasIngredientEdge()]],
- [crabNode(), [crabIngredientEdge()]],
+ [crabNode(), [crabIngredientEdge(), crabLoopEdge()]],
[mealNode(), [eatEdge()]],
];
nodeAndExpectedEdgePairs.forEach(([node, expectedEdges]) => {
- const actual = mealGraph().getInEdges(node.address);
+ const actual = advancedMealGraph().getInEdges(node.address);
expectSameSorted(actual, expectedEdges);
});
});
it("fails to get out-edges for a nonexistent node", () => {
expect(() => {
- mealGraph().getOutEdges(makeAddress("hinox"));
+ simpleMealGraph().getOutEdges(makeAddress("hinox"));
}).toThrow(/no node for address/);
});
it("fails to get in-edges for a nonexistent node", () => {
expect(() => {
- mealGraph().getInEdges(makeAddress("hinox"));
+ simpleMealGraph().getInEdges(makeAddress("hinox"));
}).toThrow(/no node for address/);
});
});