github.com/polydawn/docket@v0.5.4-0.20140630233848-90b70fb433da/dex/graph_integration_test.go (about) 1 package dex 2 3 // Very nearly all testing for dex is integration testing, sadly; this is inevitable since we're relying on exec to use git. 4 5 import ( 6 "path/filepath" 7 "bytes" 8 "os" 9 "archive/tar" 10 "testing" 11 "time" 12 "strings" 13 "github.com/coocood/assrt" 14 ) 15 16 func TestLoadGraphAbsentIsNil(t *testing.T) { 17 do(func() { 18 assert := assrt.NewAssert(t) 19 20 assert.Nil(LoadGraph(".")) 21 22 assert.Nil(LoadGraph("notadir")) 23 }) 24 } 25 26 func assertLegitGraph(assert *assrt.Assert, g *Graph) { 27 assert.NotNil(g) 28 29 gstat, _ := os.Stat(filepath.Join(g.dir)) 30 assert.True(gstat.IsDir()) 31 32 assert.True(g.HasBranch("hroot/init")) 33 34 assert.Equal( 35 "", 36 g.cmd("ls-tree")("HEAD").Output(), 37 ) 38 } 39 40 func TestNewGraphInit(t *testing.T) { 41 do(func() { 42 assertLegitGraph( 43 assrt.NewAssert(t), 44 NewGraph("."), 45 ) 46 }) 47 } 48 49 func TestLoadGraphEmpty(t *testing.T) { 50 do(func() { 51 assert := assrt.NewAssert(t) 52 53 NewGraph(".") 54 55 assertLegitGraph(assert, LoadGraph(".")) 56 }) 57 } 58 59 func TestNewGraphInitNewDir(t *testing.T) { 60 do(func() { 61 assertLegitGraph( 62 assrt.NewAssert(t), 63 NewGraph("deep"), 64 ) 65 }) 66 } 67 68 func TestNewGraphInitRejectedOnDeeper(t *testing.T) { 69 do(func() { 70 defer func() { 71 err := recover() 72 if err == nil { t.Fail(); } 73 }() 74 NewGraph("deep/deeper") 75 }) 76 } 77 78 func fsSetA() *tar.Reader { 79 var buf bytes.Buffer 80 fs := tar.NewWriter(&buf) 81 82 // file 'a' is just ascii text with normal permissions 83 fs.WriteHeader(&tar.Header{ 84 Name: "a", 85 Mode: 0644, 86 Size: 2, 87 Typeflag: tar.TypeReg, 88 ModTime: time.Unix(1000100, 5000), 89 }) 90 fs.Write([]byte{ 'a', 'b' }) 91 92 // file 'b' is binary with unusual permissions 93 fs.WriteHeader(&tar.Header{ 94 Name: "b", 95 Mode: 0640, 96 Size: 3, 97 Typeflag: tar.TypeReg, 98 }) 99 fs.Write([]byte{ 0x1, 0x2, 0x3 }) 100 101 fs.Close() 102 return tar.NewReader(&buf) 103 } 104 105 func fsSetB() *tar.Reader { 106 var buf bytes.Buffer 107 fs := tar.NewWriter(&buf) 108 109 // file 'a' is unchanged from SetA 110 fs.WriteHeader(&tar.Header{ 111 Name: "a", 112 Mode: 0644, 113 Size: 2, 114 Typeflag: tar.TypeReg, 115 ModTime: time.Unix(1000100, 5000), 116 }) 117 fs.Write([]byte{ 'a', 'b' }) 118 119 // file 'b' is removed 120 121 // file 'e' is executable 122 fs.WriteHeader(&tar.Header{ 123 Name: "e", 124 Mode: 0755, 125 Size: 3, 126 Typeflag: tar.TypeReg, 127 }) 128 fs.Write([]byte{ 'e', 'x', 'e' }) 129 130 // file 'd/d/z' is deeper 131 fs.WriteHeader(&tar.Header{ 132 Name: "d/d/z", 133 Mode: 0644, 134 Size: 2, 135 Typeflag: tar.TypeReg, 136 }) 137 fs.Write([]byte{ 'z', '\n' }) 138 139 fs.Close() 140 return tar.NewReader(&buf) 141 } 142 143 func fsSetA2() *tar.Reader { 144 var buf bytes.Buffer 145 fs := tar.NewWriter(&buf) 146 147 // file 'a' diffs from SetA 148 fs.WriteHeader(&tar.Header{ 149 Name: "a", 150 Mode: 0644, 151 Size: 3, 152 Typeflag: tar.TypeReg, 153 ModTime: time.Unix(1200100, 5000), 154 }) 155 fs.Write([]byte{ 'a', '\n', 'b' }) 156 157 // file 'b' is unchanged from SetA 158 fs.WriteHeader(&tar.Header{ 159 Name: "b", 160 Mode: 0640, 161 Size: 3, 162 Typeflag: tar.TypeReg, 163 }) 164 fs.Write([]byte{ 0x1, 0x2, 0x3 }) 165 166 fs.Close() 167 return tar.NewReader(&buf) 168 } 169 170 func fsSetC() *tar.Reader { 171 var buf bytes.Buffer 172 fs := tar.NewWriter(&buf) 173 174 // file 'a' diffs from SetA (and from SetA2, differently) 175 fs.WriteHeader(&tar.Header{ 176 Name: "a", 177 Mode: 0644, 178 Size: 3, 179 Typeflag: tar.TypeReg, 180 ModTime: time.Unix(5100100, 5000), 181 }) 182 fs.Write([]byte{ 'a', '\n', 'c' }) 183 184 // file 'b' is still gone 185 186 // file 'e' is deleted from SetB 187 188 // file 'd/d/z' is renamed to 'd/z' 189 fs.WriteHeader(&tar.Header{ 190 Name: "d/z", 191 Mode: 0644, 192 Size: 2, 193 Typeflag: tar.TypeReg, 194 }) 195 fs.Write([]byte{ 'z', '\n' }) 196 197 // and and 'd/d' is *still around* as a (empty!) dir 198 fs.WriteHeader(&tar.Header{ 199 Name: "d/d", 200 Mode: 0755, 201 Typeflag: tar.TypeDir, 202 }) 203 fs.Write([]byte{ 'z', '\n' }) //FIXME: heh 204 205 fs.Close() 206 return tar.NewReader(&buf) 207 } 208 209 func TestPublishNewOrphanLineage(t *testing.T) { 210 do(func() { 211 assert := assrt.NewAssert(t) 212 213 g := NewGraph(".") 214 lineage := "line" 215 ancestor := "" 216 217 g.Publish( 218 lineage, 219 ancestor, 220 &GraphStoreRequest_Tar{ 221 Tarstream: fsSetA(), 222 }, 223 ) 224 225 assert.Equal( 226 3, 227 strings.Count( 228 g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage).Output(), 229 "\n", 230 ), 231 ) 232 233 assert.Equal( 234 `{"Name":"a","Type":"F","Mode":644,"ModTime":"1970-01-12T13:48:20Z"}` + "\n" + 235 `{"Name":"b","Type":"F","Mode":640}` + "\n", 236 g.cmd("show", git_branch_ref_prefix+hroot_image_ref_prefix+lineage+":"+".guitar").Output(), 237 ) 238 }) 239 } 240 241 func TestPublishLinearExtensionToLineage(t *testing.T) { 242 do(func() { 243 assert := assrt.NewAssert(t) 244 245 g := NewGraph(".") 246 lineage := "line" 247 ancestor := "line" 248 249 g.Publish( 250 lineage, 251 "", 252 &GraphStoreRequest_Tar{ 253 Tarstream: fsSetA(), 254 }, 255 ) 256 257 g.Publish( 258 lineage, 259 ancestor, 260 &GraphStoreRequest_Tar{ 261 Tarstream: fsSetB(), 262 }, 263 ) 264 265 assert.Equal( 266 4, 267 strings.Count( 268 g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage).Output(), 269 "\n", 270 ), 271 ) 272 273 assert.Equal( 274 1, // shows a tree 275 strings.Count( 276 g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage, "d/d").Output(), 277 "\n", 278 ), 279 ) 280 281 assert.Equal( 282 1, // shows the file 283 strings.Count( 284 g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage, "d/d/z").Output(), 285 "\n", 286 ), 287 ) 288 289 assert.Equal( 290 `{"Name":"a","Type":"F","Mode":644,"ModTime":"1970-01-12T13:48:20Z"}` + "\n" + 291 `{"Name":"d/d/z","Type":"F","Mode":644}` + "\n" + 292 `{"Name":"e","Type":"F","Mode":755}` + "\n", 293 g.cmd("show", git_branch_ref_prefix+hroot_image_ref_prefix+lineage+":"+".guitar").Output(), 294 ) 295 }) 296 } 297 298 func TestPublishNewDerivedLineage(t *testing.T) { 299 do(func() { 300 assert := assrt.NewAssert(t) 301 302 g := NewGraph(".") 303 lineage := "ferk" 304 ancestor := "line" 305 306 g.Publish( 307 ancestor, 308 "", 309 &GraphStoreRequest_Tar{ 310 Tarstream: fsSetA(), 311 }, 312 ) 313 314 g.Publish( 315 lineage, 316 ancestor, 317 &GraphStoreRequest_Tar{ 318 Tarstream: fsSetB(), 319 }, 320 ) 321 322 println(g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage).Output()) 323 assert.Equal( 324 4, 325 strings.Count( 326 g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage).Output(), 327 "\n", 328 ), 329 ) 330 331 assert.Equal( 332 1, // shows a tree 333 strings.Count( 334 g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage, "d/d").Output(), 335 "\n", 336 ), 337 ) 338 339 assert.Equal( 340 1, // shows the file 341 strings.Count( 342 g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage, "d/d/z").Output(), 343 "\n", 344 ), 345 ) 346 347 assert.Equal( 348 `{"Name":"a","Type":"F","Mode":644,"ModTime":"1970-01-12T13:48:20Z"}` + "\n" + 349 `{"Name":"d/d/z","Type":"F","Mode":644}` + "\n" + 350 `{"Name":"e","Type":"F","Mode":755}` + "\n", 351 g.cmd("show", git_branch_ref_prefix+hroot_image_ref_prefix+lineage+":"+".guitar").Output(), 352 ) 353 }) 354 } 355 356 func TestPublishDerivativeExtensionToLineage(t *testing.T) { 357 do(func() { 358 assert := assrt.NewAssert(t) 359 360 g := NewGraph(".") 361 lineage := "ferk" 362 ancestor := "line" 363 364 // original ancestor import 365 g.Publish( 366 ancestor, 367 "", 368 &GraphStoreRequest_Tar{ 369 Tarstream: fsSetA(), 370 }, 371 ) 372 373 // derive 1 374 g.Publish( 375 lineage, 376 ancestor, 377 &GraphStoreRequest_Tar{ 378 Tarstream: fsSetB(), 379 }, 380 ) 381 382 // advance the ancestor 383 g.Publish( 384 ancestor, 385 ancestor, 386 &GraphStoreRequest_Tar{ 387 Tarstream: fsSetA2(), 388 }, 389 ) 390 391 // advance the derived from the updated ancestor 392 g.Publish( 393 lineage, 394 ancestor, 395 &GraphStoreRequest_Tar{ 396 Tarstream: fsSetC(), 397 }, 398 ) 399 400 assert.Equal( 401 3, 402 strings.Count( 403 g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage).Output(), 404 "\n", 405 ), 406 ) 407 408 assert.Equal( 409 1, // has the file. git itself still doesn't see dirs; just guitar does that. 410 strings.Count( 411 g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage, "d/").Output(), 412 "\n", 413 ), 414 ) 415 416 assert.Equal( 417 0, // nothing here. git itself still doesn't see dirs; just guitar does that. 418 strings.Count( 419 g.cmd("ls-tree", git_branch_ref_prefix+hroot_image_ref_prefix+lineage, "d/d/").Output(), 420 "\n", 421 ), 422 ) 423 424 assert.Equal( 425 `{"Name":"a","Type":"F","Mode":644,"ModTime":"1970-03-01T00:41:40Z"}` + "\n" + 426 `{"Name":"d/d","Type":"D","Mode":755}` + "\n" + 427 `{"Name":"d/z","Type":"F","Mode":644}` + "\n", 428 g.cmd("show", git_branch_ref_prefix+hroot_image_ref_prefix+lineage+":"+".guitar").Output(), 429 ) 430 }) 431 }