go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/pkg/dbmodel/main_test.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 package dbmodel 9 10 import ( 11 "bytes" 12 "context" 13 "fmt" 14 "os" 15 "os/exec" 16 "path/filepath" 17 "testing" 18 "time" 19 20 "github.com/wcharczuk/go-incr" 21 "go.charczuk.com/sdk/apputil" 22 "go.charczuk.com/sdk/assert" 23 "go.charczuk.com/sdk/db" 24 "go.charczuk.com/sdk/db/dbutil" 25 "go.charczuk.com/sdk/logutil" 26 "go.charczuk.com/sdk/testutil" 27 "go.charczuk.com/sdk/uuid" 28 ) 29 30 func TestMain(m *testing.M) { 31 testutil.New(m, 32 testutil.OptWithDefaultDB( 33 ifDebug(db.OptLog(logutil.New())), 34 ), 35 testutil.OptBefore( 36 func(ctx context.Context) error { 37 return Migrations().Apply(ctx, testutil.DefaultDB()) 38 }, 39 ), 40 ).Run() 41 } 42 43 func ifDebug(opt db.Option) db.Option { 44 return func(s *db.Connection) error { 45 if os.Getenv("DEBUG") != "" { 46 opt(s) 47 } 48 return nil 49 } 50 } 51 52 const ( 53 TestNodeV0Label = "test-var-00" 54 TestNodeV1Label = "test-var-01" 55 TestNodeM0Label = "test-expression" 56 TestNodeO0Label = "test-observer" 57 ) 58 59 // CreateTestGraph creates a test graph. 60 func CreateTestGraph(t *testing.T, mgr *dbutil.BaseManager, user *apputil.User) (*Graph, map[string]*Node) { 61 ctx := context.Background() 62 g := NewGraph() 63 g.UserID = user.ID 64 var err error 65 err = mgr.Invoke(ctx).Create(g) 66 assert.ItsNil(t, err) 67 68 v0 := Node{ 69 ID: uuid.V4(), 70 CreatedUTC: time.Now().UTC(), 71 GraphID: g.ID, 72 UserID: user.ID, 73 Label: TestNodeV0Label, 74 NodeType: "var", 75 OutputType: "string", 76 } 77 78 err = mgr.Invoke(ctx).Create(v0) 79 assert.ItsNil(t, err) 80 81 err = mgr.Invoke(ctx).Create(NodeValue{ 82 GraphID: g.ID, 83 NodeID: v0.ID, 84 UserID: user.ID, 85 ValueType: "string", 86 Value: "hello", 87 }) 88 assert.ItsNil(t, err) 89 90 v1 := Node{ 91 ID: uuid.V4(), 92 CreatedUTC: time.Now().UTC(), 93 GraphID: g.ID, 94 UserID: user.ID, 95 Label: TestNodeV1Label, 96 NodeType: "var", 97 OutputType: "string", 98 } 99 100 err = mgr.Invoke(ctx).Create(v1) 101 assert.ItsNil(t, err) 102 103 err = mgr.Invoke(ctx).Create(NodeValue{ 104 GraphID: g.ID, 105 NodeID: v1.ID, 106 UserID: user.ID, 107 ValueType: "string", 108 Value: "world", 109 }) 110 assert.ItsNil(t, err) 111 112 m0 := Node{ 113 ID: uuid.V4(), 114 CreatedUTC: time.Now().UTC(), 115 GraphID: g.ID, 116 UserID: user.ID, 117 Label: TestNodeM0Label, 118 NodeType: "expression", 119 InputType: "string", 120 OutputType: "string", 121 Expression: `output = input(0) + " " + input(1)`, 122 } 123 124 err = mgr.Invoke(ctx).Create(m0) 125 assert.ItsNil(t, err) 126 127 o0 := Node{ 128 ID: uuid.V4(), 129 CreatedUTC: time.Now().UTC(), 130 GraphID: g.ID, 131 UserID: user.ID, 132 NodeType: "observer", 133 Label: TestNodeO0Label, 134 InputType: "string", 135 } 136 137 err = mgr.Invoke(ctx).Create(o0) 138 assert.ItsNil(t, err) 139 140 err = mgr.Invoke(ctx).Create(Edge{ 141 GraphID: g.ID, 142 UserID: user.ID, 143 ParentID: v0.ID, 144 ChildID: m0.ID, 145 }) 146 assert.ItsNil(t, err) 147 148 err = mgr.Invoke(ctx).Create(Edge{ 149 GraphID: g.ID, 150 UserID: user.ID, 151 ParentID: v1.ID, 152 ChildID: m0.ID, 153 }) 154 assert.ItsNil(t, err) 155 156 err = mgr.Invoke(ctx).Create(Edge{ 157 GraphID: g.ID, 158 UserID: user.ID, 159 ParentID: m0.ID, 160 ChildID: o0.ID, 161 }) 162 assert.ItsNil(t, err) 163 164 err = mgr.Invoke(ctx).Create(GraphRecomputeHeap{ 165 GraphID: g.ID, 166 UserID: user.ID, 167 NodeID: v0.ID, 168 }) 169 assert.ItsNil(t, err) 170 171 err = mgr.Invoke(ctx).Create(GraphRecomputeHeap{ 172 GraphID: g.ID, 173 UserID: user.ID, 174 NodeID: v1.ID, 175 }) 176 assert.ItsNil(t, err) 177 178 return g, map[string]*Node{ 179 v0.Label: &v0, 180 v1.Label: &v1, 181 m0.Label: &m0, 182 o0.Label: &o0, 183 } 184 } 185 186 func homedir(filename string) string { 187 var rootDir string 188 if rootDir = os.Getenv("INCR_DEBUG_DOT_ROOT"); rootDir == "" { 189 rootDir = os.ExpandEnv("$HOME/Desktop") 190 } 191 return filepath.Join(rootDir, filename) 192 } 193 194 func dumpDot(g *incr.Graph, path string) error { 195 if os.Getenv("INCR_DEBUG_DOT") != "true" { 196 return nil 197 } 198 199 dotContents := new(bytes.Buffer) 200 if err := incr.Dot(dotContents, g); err != nil { 201 return err 202 } 203 dotOutput, err := os.Create(os.ExpandEnv(path)) 204 if err != nil { 205 return err 206 } 207 defer func() { _ = dotOutput.Close() }() 208 dotFullPath, err := exec.LookPath("dot") 209 if err != nil { 210 return fmt.Errorf("there was an issue finding `dot` in your path; you may need to install the `graphviz` package or similar on your platform: %w", err) 211 } 212 213 errOut := new(bytes.Buffer) 214 cmd := exec.Command(dotFullPath, "-Tpng") 215 cmd.Stdin = dotContents 216 cmd.Stdout = dotOutput 217 cmd.Stderr = errOut 218 if err := cmd.Run(); err != nil { 219 return fmt.Errorf("%v; %w", errOut.String(), err) 220 } 221 return nil 222 }