From 500b02db34d4bfb70ee0a569136806ecf2bd891a Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Sat, 1 Aug 2020 20:34:52 +0000 Subject: [PATCH] graph-building seems to be working --- node.go | 85 +++++++++++++++++++------------------------- selection.go | 24 +++---------- selection_test.go | 90 +++++++++++++++++++++++++++++++++-------------- test.go | 1 + 4 files changed, 107 insertions(+), 93 deletions(-) diff --git a/node.go b/node.go index 87f08cd..eca61ab 100644 --- a/node.go +++ b/node.go @@ -26,38 +26,41 @@ type lnode struct { // If there are no parents, the lnode is a root node, and the provided test is // run once. Otherwise, the provided test is used to create xnodes that are // children of all of the provided parent nodes' xnodes. -func newLNode(test Test, parents ...*lnode) *lnode { - if len(parents) == 0 { +func newLNode(test Test, sel Selection) *lnode { + if len(sel.nodes) == 0 { return rootLNode(test) } - id := nextNodeID() node := lnode{ - id: id, + id: nextNodeID(), name: parseName(test), test: test, - parents: parents, + parents: make([]*lnode, len(sel.nodes)), } + copy(node.parents, sel.nodes) xID := 0 - for _, parent := range parents { + for _, parent := range node.parents { + parent.children = append(parent.children, &node) for i, _ := range parent.xnodes { - node.xnodes = append(node.xnodes, xnode{ + x := xnode{ id: xID, lnode: &node, parent: &parent.xnodes[i], - }) + } + node.xnodes = append(node.xnodes, x) xID++ } } - for i, _ := range node.xnodes { - xparent := node.xnodes[i] - xparent.children = append(xparent.children, &node.xnodes[i]) + for i, x := range node.xnodes { + x.parent.children = append(x.parent.children, &node.xnodes[i]) } return &node } +// rootLNode creates a root lnode. This case is a lot simpler so I split it out +// to keep newLNode a little more readable. func rootLNode(test Test) *lnode { id := nextNodeID() node := lnode{ @@ -69,21 +72,6 @@ func rootLNode(test Test) *lnode { return &node } -// child adds an lnode as a child of the receiver. For every xnode in this -// receiver, the child lnode has a component xnode whose parent is the -// corresponding xnode in this lnode. -func (l *lnode) child(c *lnode, t Test) { - panic("nuh") - //c.parents = append(c.parents, l) - //l.children = append(l.children, c) - //for i, x := range l.xnodes { - // xchild := x.child(t) - // xchild.lnode = c - // xchild.id = i - // c.xnodes = append(c.xnodes, xchild) - //} -} - // xnode is a node in the execution graph, representing one instance of a test // to be executed. xnode is the unit test in tea. every xnode is either // unparented or has one parent. @@ -94,32 +82,33 @@ type xnode struct { children []*xnode } -// func newXNode(L *lnode - -func (x *xnode) child(t Test) *xnode { - panic("no") - // child := &xnode{test: t, parent: x} - // x.children = append(x.children, child) - // return child -} - func (x *xnode) isOnlyTestInLNode() bool { - return len(x.lnode.children) == 1 + return len(x.lnode.xnodes) == 1 } func (x *xnode) label() string { - if x.isOnlyTestInLNode() { - return x.lnode.name - } - switch { - case len(x.lnode.children) < 10: - return fmt.Sprintf("%s:%d", x.lnode.name, x.id) - case len(x.lnode.children) < 100: - return fmt.Sprintf("%s:%02d", x.lnode.name, x.id) - case len(x.lnode.children) < 1000: - return fmt.Sprintf("%s:%03d", x.lnode.name, x.id) - default: - return fmt.Sprintf("%s:%04d", x.lnode.name, x.id) + if x.parent == nil { + switch { + case len(x.lnode.children) < 10: + return fmt.Sprintf("%s.%d", x.lnode.name, x.id) + case len(x.lnode.children) < 100: + return fmt.Sprintf("%s.%02d", x.lnode.name, x.id) + case len(x.lnode.children) < 1000: + return fmt.Sprintf("%s.%03d", x.lnode.name, x.id) + default: + return fmt.Sprintf("%s.%04d", x.lnode.name, x.id) + } + } else { + switch { + case len(x.lnode.children) < 10: + return fmt.Sprintf("%s.%d.%s", x.lnode.name, x.id, x.parent.lnode.name) + case len(x.lnode.children) < 100: + return fmt.Sprintf("%s.%02d.%s", x.lnode.name, x.id, x.parent.lnode.name) + case len(x.lnode.children) < 1000: + return fmt.Sprintf("%s.%03d.%s", x.lnode.name, x.id, x.parent.lnode.name) + default: + return fmt.Sprintf("%s.%04d.%s", x.lnode.name, x.id, x.parent.lnode.name) + } } } diff --git a/selection.go b/selection.go index 53db31d..a738910 100644 --- a/selection.go +++ b/selection.go @@ -1,7 +1,8 @@ package tea func NewSelection(test Test) Selection { - return Selection{nodes: []*lnode{newLNode(test)}} + node := newLNode(test, Selection{}) + return Selection{nodes: []*lnode{node}} } // Selection represents a set of nodes in our graph. @@ -10,7 +11,7 @@ type Selection struct { } func (s Selection) Child(test Test) Selection { - node := newLNode(test, s.nodes...) + node := newLNode(test, s) return Selection{nodes: []*lnode{node}} } @@ -32,8 +33,8 @@ func (s Selection) And(other Selection) Selection { func (s Selection) xnodes() []*xnode { xnodes := make([]*xnode, 0, s.countXNodes()) for _, L := range s.nodes { - for _, x := range L.xnodes { - xnodes = append(xnodes, &x) + for i, _ := range L.xnodes { + xnodes = append(xnodes, &L.xnodes[i]) } } return xnodes @@ -46,18 +47,3 @@ func (s Selection) countXNodes() int { } return total } - -// func (s Selection) writeXDOT(w io.Writer) { -// xnodes := s.xnodes() -// -// type xedge [2]string -// included := make(map[xedge]bool) -// edges := make([]xedge, 0, len(xnodes)) -// -// for _, X := range xnodes { -// -// for p := X; p != nil; p = p.parent { -// -// } -// } -// } diff --git a/selection_test.go b/selection_test.go index 3041ac6..f911619 100644 --- a/selection_test.go +++ b/selection_test.go @@ -5,21 +5,59 @@ import ( ) type selectionTest struct { - label string - selection Selection - selLNodes int // number of lnodes in the selection - selXNodes int // number of xnodes in the selection - reachLNodes int // number of lnodes reachable by the selection - reachXnodes int // number of xnodes reachable by the selection + label string + selection Selection + lnodes []string + xnodes []string } func (test *selectionTest) Run(t *testing.T) { - if count := len(test.selection.nodes); count != test.selLNodes { - t.Errorf("expected %d node in selection, saw %d", test.selLNodes, count) + lfound := make(map[string]bool) + for _, L := range test.selection.nodes { + if len(L.parents) > 0 { + pnames := make([]string, 0, len(L.parents)) + for _, p := range L.parents { + pnames = append(pnames, p.name) + } + t.Logf("found lnode with label %s having %d parents: %s", L.name, len(L.parents), pnames) + } else { + t.Logf("found root lnode with label %s", L.name) + } + lfound[L.name] = true + } + + for _, expected := range test.lnodes { + if lfound[expected] { + delete(lfound, expected) + } else { + t.Errorf("missing expected lnode with label %s", expected) + } + } + + for label, _ := range lfound { + t.Errorf("found unexpected lnode with label %s", label) + } + + xfound := make(map[string]bool) + for _, x := range test.selection.xnodes() { + if x.parent != nil { + t.Logf("found xnode with label %s having parent %s", x.label(), x.parent.label()) + } else { + t.Logf("found root xnode with label %s", x.label()) + } + xfound[x.label()] = true + } + + for _, expected := range test.xnodes { + if xfound[expected] { + delete(xfound, expected) + } else { + t.Errorf("missing expected xnode with label %s", expected) + } } - if count := test.selection.countXNodes(); count != test.selXNodes { - t.Errorf("expected %d xnode in lnode, saw %d", test.selXNodes, count) + for label, _ := range xfound { + t.Errorf("found unexpected xnode with label %s", label) } } @@ -28,20 +66,20 @@ func TestSelections(t *testing.T) { { label: "new selection", selection: NewSelection(A), - selLNodes: 1, - selXNodes: 1, + lnodes: []string{"A"}, + xnodes: []string{"A.0"}, }, { label: "root with one child", selection: NewSelection(A).Child(B), - selLNodes: 1, - selXNodes: 1, + lnodes: []string{"B"}, + xnodes: []string{"B.0.A"}, }, { label: "two selected roots", selection: NewSelection(A).And(NewSelection(B)), - selLNodes: 2, - selXNodes: 2, + lnodes: []string{"A", "B"}, + xnodes: []string{"A.0", "B.0"}, }, } @@ -53,8 +91,8 @@ func TestSelections(t *testing.T) { return selectionTest{ label: "root and child selected", selection: root.And(b), - selLNodes: 2, - selXNodes: 2, + lnodes: []string{"A", "B"}, + xnodes: []string{"A.0", "B.0.A"}, } }) @@ -64,8 +102,8 @@ func TestSelections(t *testing.T) { return selectionTest{ label: "an optional test", selection: root.And(b).Child(C), - selLNodes: 1, - selXNodes: 2, + lnodes: []string{"C"}, + xnodes: []string{"C.0.A", "C.1.B"}, } }) @@ -77,8 +115,8 @@ func TestSelections(t *testing.T) { return selectionTest{ label: "two children selected", selection: b.And(c), - selLNodes: 2, - selXNodes: 2, + lnodes: []string{"B", "C"}, + xnodes: []string{"B.0.A", "C.0.A"}, } }) @@ -89,8 +127,8 @@ func TestSelections(t *testing.T) { return selectionTest{ label: "a diamond test", selection: b.And(c).Child(D), - selLNodes: 1, - selXNodes: 2, + lnodes: []string{"D"}, + xnodes: []string{"D.0.B", "D.1.C"}, } }) @@ -102,8 +140,8 @@ func TestSelections(t *testing.T) { return selectionTest{ label: "child of a node having multiple parents", selection: d.Child(E), - selLNodes: 1, - selXNodes: 2, + lnodes: []string{"E"}, + xnodes: []string{"E.0.D", "E.1.D"}, } }) diff --git a/test.go b/test.go index 1739dd2..23f27f8 100644 --- a/test.go +++ b/test.go @@ -57,6 +57,7 @@ const Pass = Passing("test passed") type Passing string func (p Passing) Run(t *testing.T) {} +func (p Passing) String() string { return string(p) } // parseName parses the name for a given test func parseName(test Test) string {