From 8659b230c8317497a30c1798f60833fb453f54f4 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Sat, 1 Aug 2020 03:20:56 +0000 Subject: [PATCH] just build both graphs at the same time. --- node.go | 41 +++++++++++++++++++++++++++++++++++++---- selection.go | 39 ++++++++++++++++++--------------------- selection_test.go | 20 ++++++++++++++++++++ test.go | 10 +++++++--- 4 files changed, 82 insertions(+), 28 deletions(-) diff --git a/node.go b/node.go index ded42d2..12d5272 100644 --- a/node.go +++ b/node.go @@ -7,10 +7,43 @@ func nextNodeID() int { return lastID } -type node struct { +// lnode is a node in the logical graph. Developers create a logical graph in +// which nodes may have more than one parent. Each test value written by a +// developer appears as one logical node in the logical graph. The public +// documentation refers to the logical graph as simply the test graph. +type lnode struct { id int - test Test name string - parents []*node - children []*node + xnodes []*xnode + parents []*lnode + children []*lnode +} + +// child adds an lnode as a child of the receiver. For every xnode in this +// lnode, the child lnode has a component xnode whose parent is the +// corresponding xnode in this lnode. +func (l *lnode) child(c *lnode, t Test) { + c.parents = append(c.parents, l) + l.children = append(l.children, c) + for _, x := range l.xnodes { + xchild := x.child(t) + xchild.lnode = c + 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. +type xnode struct { + lnode *lnode + test Test + parent *xnode + children []*xnode +} + +func (x *xnode) child(t Test) *xnode { + child := &xnode{test: t, parent: x} + x.children = append(x.children, child) + return child } diff --git a/selection.go b/selection.go index 90a2334..4a96f12 100644 --- a/selection.go +++ b/selection.go @@ -1,41 +1,38 @@ package tea -import ( - "testing" -) - func NewSelection(test Test) Selection { - n := node{test: test} - return Selection{ - nodes: []*node{&n}, + x := xnode{ + test: clone(test), } -} - -func RunSelection(t *testing.T, s Selection) { + l := lnode{ + id: nextNodeID(), + name: parseName(test), + xnodes: []*xnode{&x}, + } + x.lnode = &l + return Selection{ + nodes: []*lnode{&l}, + } } +// Selection represents a set of nodes in our graph. type Selection struct { - nodes []*node + nodes []*lnode } func (s Selection) Child(test Test) Selection { - child := &node{ - id: nextNodeID(), - test: test, - name: parseName(test), - parents: s.nodes, - } - for _, sn := range s.nodes { - sn.children = append(sn.children, child) + child := &lnode{id: nextNodeID(), name: parseName(test)} + for _, l := range s.nodes { + l.child(child, test) } - return Selection{nodes: []*node{child}} + return Selection{nodes: []*lnode{child}} } func (s Selection) And(other Selection) Selection { included := make(map[int]bool) - out := make([]*node, 0, len(s.nodes)+len(other.nodes)) + out := make([]*lnode, 0, len(s.nodes)+len(other.nodes)) for _, n := range append(s.nodes, other.nodes...) { if !included[n.id] { out = append(out, n) diff --git a/selection_test.go b/selection_test.go index f9164ac..ebcc8b7 100644 --- a/selection_test.go +++ b/selection_test.go @@ -1 +1,21 @@ package tea + +import ( + "testing" +) + +func TestNewSelection(t *testing.T) { + s := NewSelection(Passing("A")) + if len(s.nodes) != 1 { + t.Fatalf("expected 1 node in new selection, saw %d", len(s.nodes)) + } + + l := s.nodes[0] + if len(l.children) != 0 { + t.Fatalf("new selection should not have any children, but has %d", len(l.children)) + } + + if len(l.xnodes) != 1 { + t.Fatalf("expected 1 xnode in lnode, saw %d", len(l.xnodes)) + } +} diff --git a/test.go b/test.go index 218b2f0..1739dd2 100644 --- a/test.go +++ b/test.go @@ -18,9 +18,13 @@ type Test interface { // like, kinda on you though, I can't really enforce things that the Go type // system doesn't let me enforce. func clone(t Test) Test { - srcV := reflect.ValueOf(t).Elem() - destV := reflect.New(srcV.Type()) - destV.Elem().Set(srcV) + v := reflect.ValueOf(t) + switch v.Kind() { + case reflect.Ptr: + v = v.Elem() + } + destV := reflect.New(v.Type()) + destV.Elem().Set(v) return destV.Interface().(Test) }