github.com/rigado/snapd@v2.42.5-go-mod+incompatible/snap/squashfs/squashfs_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014-2015 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package squashfs_test 21 22 import ( 23 "errors" 24 "io/ioutil" 25 "math" 26 "os" 27 "os/exec" 28 "path/filepath" 29 "strings" 30 "testing" 31 "time" 32 33 . "gopkg.in/check.v1" 34 "gopkg.in/yaml.v2" 35 36 "github.com/snapcore/snapd/dirs" 37 "github.com/snapcore/snapd/osutil" 38 "github.com/snapcore/snapd/snap/snapdir" 39 "github.com/snapcore/snapd/snap/squashfs" 40 "github.com/snapcore/snapd/testutil" 41 ) 42 43 // Hook up check.v1 into the "go test" runner 44 func Test(t *testing.T) { TestingT(t) } 45 46 type SquashfsTestSuite struct { 47 oldStdout, oldStderr, outf *os.File 48 } 49 50 var _ = Suite(&SquashfsTestSuite{}) 51 52 func makeSnap(c *C, manifest, data string) *squashfs.Snap { 53 cur, _ := os.Getwd() 54 return makeSnapInDir(c, cur, manifest, data) 55 } 56 57 func makeSnapContents(c *C, manifest, data string) string { 58 tmp := c.MkDir() 59 err := os.MkdirAll(filepath.Join(tmp, "meta", "hooks", "dir"), 0755) 60 c.Assert(err, IsNil) 61 62 // our regular snap.yaml 63 err = ioutil.WriteFile(filepath.Join(tmp, "meta", "snap.yaml"), []byte(manifest), 0644) 64 c.Assert(err, IsNil) 65 66 // some hooks 67 err = ioutil.WriteFile(filepath.Join(tmp, "meta", "hooks", "foo-hook"), nil, 0755) 68 c.Assert(err, IsNil) 69 err = ioutil.WriteFile(filepath.Join(tmp, "meta", "hooks", "bar-hook"), nil, 0755) 70 c.Assert(err, IsNil) 71 // And a file in another directory in there, just for testing (not a valid 72 // hook) 73 err = ioutil.WriteFile(filepath.Join(tmp, "meta", "hooks", "dir", "baz"), nil, 0755) 74 c.Assert(err, IsNil) 75 76 // some empty directories 77 err = os.MkdirAll(filepath.Join(tmp, "food", "bard", "bazd"), 0755) 78 c.Assert(err, IsNil) 79 80 // some data 81 err = ioutil.WriteFile(filepath.Join(tmp, "data.bin"), []byte(data), 0644) 82 c.Assert(err, IsNil) 83 84 return tmp 85 } 86 87 func makeSnapInDir(c *C, dir, manifest, data string) *squashfs.Snap { 88 snapType := "app" 89 var m struct { 90 Type string `yaml:"type"` 91 } 92 if err := yaml.Unmarshal([]byte(manifest), &m); err == nil && m.Type != "" { 93 snapType = m.Type 94 } 95 96 tmp := makeSnapContents(c, manifest, data) 97 // build it 98 snap := squashfs.New(filepath.Join(dir, "foo.snap")) 99 err := snap.Build(tmp, snapType) 100 c.Assert(err, IsNil) 101 102 return snap 103 } 104 105 func (s *SquashfsTestSuite) SetUpTest(c *C) { 106 d := c.MkDir() 107 dirs.SetRootDir(d) 108 err := os.Chdir(d) 109 c.Assert(err, IsNil) 110 111 s.outf, err = ioutil.TempFile(c.MkDir(), "") 112 c.Assert(err, IsNil) 113 s.oldStdout, s.oldStderr = os.Stdout, os.Stderr 114 os.Stdout, os.Stderr = s.outf, s.outf 115 } 116 117 func (s *SquashfsTestSuite) TearDownTest(c *C) { 118 os.Stdout, os.Stderr = s.oldStdout, s.oldStderr 119 120 // this ensures things were quiet 121 _, err := s.outf.Seek(0, 0) 122 c.Assert(err, IsNil) 123 outbuf, err := ioutil.ReadAll(s.outf) 124 c.Assert(err, IsNil) 125 c.Check(string(outbuf), Equals, "") 126 } 127 128 func (s *SquashfsTestSuite) TestInstallSimpleNoCp(c *C) { 129 // mock cp but still cp 130 cmd := testutil.MockCommand(c, "cp", `#!/bin/sh 131 exec /bin/cp "$@" 132 `) 133 defer cmd.Restore() 134 // mock link but still link 135 linked := 0 136 r := squashfs.MockLink(func(a, b string) error { 137 linked++ 138 return os.Link(a, b) 139 }) 140 defer r() 141 142 snap := makeSnap(c, "name: test", "") 143 targetPath := filepath.Join(c.MkDir(), "target.snap") 144 mountDir := c.MkDir() 145 err := snap.Install(targetPath, mountDir) 146 c.Assert(err, IsNil) 147 c.Check(osutil.FileExists(targetPath), Equals, true) 148 c.Check(linked, Equals, 1) 149 c.Check(cmd.Calls(), HasLen, 0) 150 } 151 152 func noLink() func() { 153 return squashfs.MockLink(func(string, string) error { return errors.New("no.") }) 154 } 155 156 func (s *SquashfsTestSuite) TestInstallNotCopyTwice(c *C) { 157 // first, disable os.Link 158 defer noLink()() 159 160 // then, mock cp but still cp 161 cmd := testutil.MockCommand(c, "cp", `#!/bin/sh 162 exec /bin/cp "$@" 163 `) 164 defer cmd.Restore() 165 166 snap := makeSnap(c, "name: test2", "") 167 targetPath := filepath.Join(c.MkDir(), "target.snap") 168 mountDir := c.MkDir() 169 err := snap.Install(targetPath, mountDir) 170 c.Assert(err, IsNil) 171 c.Check(cmd.Calls(), HasLen, 1) 172 173 err = snap.Install(targetPath, mountDir) 174 c.Assert(err, IsNil) 175 c.Check(cmd.Calls(), HasLen, 1) // and not 2 \o/ 176 } 177 178 func (s *SquashfsTestSuite) TestInstallSeedNoLink(c *C) { 179 defer noLink()() 180 181 c.Assert(os.MkdirAll(dirs.SnapSeedDir, 0755), IsNil) 182 snap := makeSnapInDir(c, dirs.SnapSeedDir, "name: test2", "") 183 targetPath := filepath.Join(c.MkDir(), "target.snap") 184 _, err := os.Lstat(targetPath) 185 c.Check(os.IsNotExist(err), Equals, true) 186 187 err = snap.Install(targetPath, c.MkDir()) 188 c.Assert(err, IsNil) 189 c.Check(osutil.IsSymlink(targetPath), Equals, true) // \o/ 190 } 191 192 func (s *SquashfsTestSuite) TestPath(c *C) { 193 p := "/path/to/foo.snap" 194 snap := squashfs.New("/path/to/foo.snap") 195 c.Assert(snap.Path(), Equals, p) 196 } 197 198 func (s *SquashfsTestSuite) TestReadFile(c *C) { 199 snap := makeSnap(c, "name: foo", "") 200 201 content, err := snap.ReadFile("meta/snap.yaml") 202 c.Assert(err, IsNil) 203 c.Assert(string(content), Equals, "name: foo") 204 } 205 206 func (s *SquashfsTestSuite) TestListDir(c *C) { 207 snap := makeSnap(c, "name: foo", "") 208 209 fileNames, err := snap.ListDir("meta/hooks") 210 c.Assert(err, IsNil) 211 c.Assert(len(fileNames), Equals, 3) 212 c.Check(fileNames[0], Equals, "bar-hook") 213 c.Check(fileNames[1], Equals, "dir") 214 c.Check(fileNames[2], Equals, "foo-hook") 215 } 216 217 func (s *SquashfsTestSuite) TestWalk(c *C) { 218 sub := "." 219 snap := makeSnap(c, "name: foo", "") 220 sqw := map[string]os.FileInfo{} 221 snap.Walk(sub, func(path string, info os.FileInfo, err error) error { 222 if err != nil { 223 return err 224 } 225 if path == "food" { 226 return filepath.SkipDir 227 } 228 sqw[path] = info 229 return nil 230 }) 231 232 base := c.MkDir() 233 c.Assert(snap.Unpack("*", base), IsNil) 234 235 sdw := map[string]os.FileInfo{} 236 snapdir.New(base).Walk(sub, func(path string, info os.FileInfo, err error) error { 237 if err != nil { 238 return err 239 } 240 if path == "food" { 241 return filepath.SkipDir 242 } 243 sdw[path] = info 244 return nil 245 }) 246 247 fpw := map[string]os.FileInfo{} 248 filepath.Walk(filepath.Join(base, sub), func(path string, info os.FileInfo, err error) error { 249 if err != nil { 250 return err 251 } 252 path, err = filepath.Rel(base, path) 253 if err != nil { 254 return err 255 } 256 if path == "food" { 257 return filepath.SkipDir 258 } 259 fpw[path] = info 260 return nil 261 }) 262 263 for k := range fpw { 264 squashfs.Alike(sqw[k], fpw[k], c, Commentf(k)) 265 squashfs.Alike(sdw[k], fpw[k], c, Commentf(k)) 266 } 267 268 for k := range sqw { 269 squashfs.Alike(fpw[k], sqw[k], c, Commentf(k)) 270 squashfs.Alike(sdw[k], sqw[k], c, Commentf(k)) 271 } 272 273 for k := range sdw { 274 squashfs.Alike(fpw[k], sdw[k], c, Commentf(k)) 275 squashfs.Alike(sqw[k], sdw[k], c, Commentf(k)) 276 } 277 278 } 279 280 // TestUnpackGlob tests the internal unpack 281 func (s *SquashfsTestSuite) TestUnpackGlob(c *C) { 282 data := "some random data" 283 snap := makeSnap(c, "", data) 284 285 outputDir := c.MkDir() 286 err := snap.Unpack("data*", outputDir) 287 c.Assert(err, IsNil) 288 289 // this is the file we expect 290 c.Assert(filepath.Join(outputDir, "data.bin"), testutil.FileEquals, data) 291 292 // ensure glob was honored 293 c.Assert(osutil.FileExists(filepath.Join(outputDir, "meta/snap.yaml")), Equals, false) 294 } 295 296 func (s *SquashfsTestSuite) TestUnpackDetectsFailures(c *C) { 297 mockUnsquashfs := testutil.MockCommand(c, "unsquashfs", ` 298 cat >&2 <<EOF 299 Failed to write /tmp/1/modules/4.4.0-112-generic/modules.symbols, skipping 300 301 Write on output file failed because No space left on device 302 303 writer: failed to write data block 0 304 305 Failed to write /tmp/1/modules/4.4.0-112-generic/modules.symbols.bin, skipping 306 307 Write on output file failed because No space left on device 308 309 writer: failed to write data block 0 310 311 Failed to write /tmp/1/modules/4.4.0-112-generic/vdso/vdso32.so, skipping 312 313 Write on output file failed because No space left on device 314 315 writer: failed to write data block 0 316 317 Failed to write /tmp/1/modules/4.4.0-112-generic/vdso/vdso64.so, skipping 318 319 Write on output file failed because No space left on device 320 321 writer: failed to write data block 0 322 323 Failed to write /tmp/1/modules/4.4.0-112-generic/vdso/vdsox32.so, skipping 324 325 Write on output file failed because No space left on device 326 327 writer: failed to write data block 0 328 329 Failed to write /tmp/1/snap/manifest.yaml, skipping 330 331 Write on output file failed because No space left on device 332 333 writer: failed to write data block 0 334 335 Failed to write /tmp/1/snap/snapcraft.yaml, skipping 336 EOF 337 `) 338 defer mockUnsquashfs.Restore() 339 340 data := "mock kernel snap" 341 snap := makeSnap(c, "", data) 342 err := snap.Unpack("*", "some-output-dir") 343 c.Assert(err, NotNil) 344 c.Check(err.Error(), Equals, `cannot extract "*" to "some-output-dir": failed: "Failed to write /tmp/1/modules/4.4.0-112-generic/modules.symbols, skipping", "Write on output file failed because No space left on device", "writer: failed to write data block 0", "Failed to write /tmp/1/modules/4.4.0-112-generic/modules.symbols.bin, skipping", and 15 more`) 345 } 346 347 func (s *SquashfsTestSuite) TestBuild(c *C) { 348 // please keep TestBuildUsesExcludes in sync with this one so it makes sense. 349 buildDir := c.MkDir() 350 err := os.MkdirAll(filepath.Join(buildDir, "/random/dir"), 0755) 351 c.Assert(err, IsNil) 352 err = ioutil.WriteFile(filepath.Join(buildDir, "data.bin"), []byte("data"), 0644) 353 c.Assert(err, IsNil) 354 err = ioutil.WriteFile(filepath.Join(buildDir, "random", "data.bin"), []byte("more data"), 0644) 355 c.Assert(err, IsNil) 356 357 snap := squashfs.New(filepath.Join(c.MkDir(), "foo.snap")) 358 err = snap.Build(buildDir, "app") 359 c.Assert(err, IsNil) 360 361 // unsquashfs writes a funny header like: 362 // "Parallel unsquashfs: Using 1 processor" 363 // "1 inodes (1 blocks) to write" 364 outputWithHeader, err := exec.Command("unsquashfs", "-n", "-l", snap.Path()).Output() 365 c.Assert(err, IsNil) 366 split := strings.Split(string(outputWithHeader), "\n") 367 output := strings.Join(split[3:], "\n") 368 c.Assert(string(output), Equals, ` 369 squashfs-root 370 squashfs-root/data.bin 371 squashfs-root/random 372 squashfs-root/random/data.bin 373 squashfs-root/random/dir 374 `[1:]) // skip the first newline :-) 375 } 376 377 func (s *SquashfsTestSuite) TestBuildUsesExcludes(c *C) { 378 // please keep TestBuild in sync with this one so it makes sense. 379 buildDir := c.MkDir() 380 err := os.MkdirAll(filepath.Join(buildDir, "/random/dir"), 0755) 381 c.Assert(err, IsNil) 382 err = ioutil.WriteFile(filepath.Join(buildDir, "data.bin"), []byte("data"), 0644) 383 c.Assert(err, IsNil) 384 err = ioutil.WriteFile(filepath.Join(buildDir, "random", "data.bin"), []byte("more data"), 0644) 385 c.Assert(err, IsNil) 386 387 excludesFilename := filepath.Join(buildDir, ".snapignore") 388 err = ioutil.WriteFile(excludesFilename, []byte(` 389 # ignore just one of the data.bin files we just added (the toplevel one) 390 data.bin 391 # also ignore ourselves 392 .snapignore 393 # oh and anything called "dir" anywhere 394 ... dir 395 `), 0644) 396 c.Assert(err, IsNil) 397 398 snap := squashfs.New(filepath.Join(c.MkDir(), "foo.snap")) 399 err = snap.Build(buildDir, "app", excludesFilename) 400 c.Assert(err, IsNil) 401 402 outputWithHeader, err := exec.Command("unsquashfs", "-n", "-l", snap.Path()).Output() 403 c.Assert(err, IsNil) 404 split := strings.Split(string(outputWithHeader), "\n") 405 output := strings.Join(split[3:], "\n") 406 // compare with TestBuild 407 c.Assert(string(output), Equals, ` 408 squashfs-root 409 squashfs-root/random 410 squashfs-root/random/data.bin 411 `[1:]) // skip the first newline :-) 412 } 413 414 func (s *SquashfsTestSuite) TestBuildSupportsMultipleExcludesWithOnlyOneWildcardsFlag(c *C) { 415 defer squashfs.MockCommandFromSystemSnap(func(cmd string, args ...string) (*exec.Cmd, error) { 416 c.Check(cmd, Equals, "/usr/bin/mksquashfs") 417 return nil, errors.New("bzzt") 418 })() 419 mksq := testutil.MockCommand(c, "mksquashfs", "") 420 defer mksq.Restore() 421 422 snapPath := filepath.Join(c.MkDir(), "foo.snap") 423 snap := squashfs.New(snapPath) 424 err := snap.Build(c.MkDir(), "core", "exclude1", "exclude2", "exclude3") 425 c.Assert(err, IsNil) 426 calls := mksq.Calls() 427 c.Assert(calls, HasLen, 1) 428 c.Check(calls[0], DeepEquals, []string{ 429 // the usual: 430 "mksquashfs", ".", snapPath, "-noappend", "-comp", "xz", "-no-fragments", "-no-progress", 431 // the interesting bits: 432 "-wildcards", "-ef", "exclude1", "-ef", "exclude2", "-ef", "exclude3", 433 }) 434 } 435 436 func (s *SquashfsTestSuite) TestBuildUsesMksquashfsFromCoreIfAvailable(c *C) { 437 usedFromCore := false 438 defer squashfs.MockCommandFromSystemSnap(func(cmd string, args ...string) (*exec.Cmd, error) { 439 usedFromCore = true 440 c.Check(cmd, Equals, "/usr/bin/mksquashfs") 441 return &exec.Cmd{Path: "/bin/true"}, nil 442 })() 443 mksq := testutil.MockCommand(c, "mksquashfs", "exit 1") 444 defer mksq.Restore() 445 446 buildDir := c.MkDir() 447 448 snap := squashfs.New(filepath.Join(c.MkDir(), "foo.snap")) 449 err := snap.Build(buildDir, "app") 450 c.Assert(err, IsNil) 451 c.Check(usedFromCore, Equals, true) 452 c.Check(mksq.Calls(), HasLen, 0) 453 } 454 455 func (s *SquashfsTestSuite) TestBuildUsesMksquashfsFromClassicIfCoreUnavailable(c *C) { 456 triedFromCore := false 457 defer squashfs.MockCommandFromSystemSnap(func(cmd string, args ...string) (*exec.Cmd, error) { 458 triedFromCore = true 459 c.Check(cmd, Equals, "/usr/bin/mksquashfs") 460 return nil, errors.New("bzzt") 461 })() 462 mksq := testutil.MockCommand(c, "mksquashfs", "") 463 defer mksq.Restore() 464 465 buildDir := c.MkDir() 466 467 snap := squashfs.New(filepath.Join(c.MkDir(), "foo.snap")) 468 err := snap.Build(buildDir, "app") 469 c.Assert(err, IsNil) 470 c.Check(triedFromCore, Equals, true) 471 c.Check(mksq.Calls(), HasLen, 1) 472 } 473 474 func (s *SquashfsTestSuite) TestBuildFailsIfNoMksquashfs(c *C) { 475 triedFromCore := false 476 defer squashfs.MockCommandFromSystemSnap(func(cmd string, args ...string) (*exec.Cmd, error) { 477 triedFromCore = true 478 c.Check(cmd, Equals, "/usr/bin/mksquashfs") 479 return nil, errors.New("bzzt") 480 })() 481 mksq := testutil.MockCommand(c, "mksquashfs", "exit 1") 482 defer mksq.Restore() 483 484 buildDir := c.MkDir() 485 486 snap := squashfs.New(filepath.Join(c.MkDir(), "foo.snap")) 487 err := snap.Build(buildDir, "app") 488 c.Assert(err, ErrorMatches, "mksquashfs call failed:.*") 489 c.Check(triedFromCore, Equals, true) 490 c.Check(mksq.Calls(), HasLen, 1) 491 } 492 493 func (s *SquashfsTestSuite) TestBuildVariesArgsByType(c *C) { 494 defer squashfs.MockCommandFromSystemSnap(func(cmd string, args ...string) (*exec.Cmd, error) { 495 return nil, errors.New("bzzt") 496 })() 497 mksq := testutil.MockCommand(c, "mksquashfs", "") 498 defer mksq.Restore() 499 500 buildDir := c.MkDir() 501 filename := filepath.Join(c.MkDir(), "foo.snap") 502 snap := squashfs.New(filename) 503 504 permissiveTypeArgs := []string{".", filename, "-noappend", "-comp", "xz", "-no-fragments", "-no-progress"} 505 restrictedTypeArgs := append(permissiveTypeArgs, "-all-root", "-no-xattrs") 506 tests := []struct { 507 snapType string 508 args []string 509 }{ 510 {"", restrictedTypeArgs}, 511 {"app", restrictedTypeArgs}, 512 {"gadget", restrictedTypeArgs}, 513 {"kernel", restrictedTypeArgs}, 514 {"snapd", restrictedTypeArgs}, 515 {"base", permissiveTypeArgs}, 516 {"os", permissiveTypeArgs}, 517 {"core", permissiveTypeArgs}, 518 } 519 520 for _, t := range tests { 521 mksq.ForgetCalls() 522 comm := Commentf("type: %s", t.snapType) 523 524 c.Check(snap.Build(buildDir, t.snapType), IsNil, comm) 525 c.Assert(mksq.Calls(), HasLen, 1, comm) 526 c.Assert(mksq.Calls()[0], HasLen, len(t.args)+1) 527 c.Check(mksq.Calls()[0][0], Equals, "mksquashfs", comm) 528 c.Check(mksq.Calls()[0][1:], DeepEquals, t.args, comm) 529 } 530 } 531 532 func (s *SquashfsTestSuite) TestBuildReportsFailures(c *C) { 533 mockUnsquashfs := testutil.MockCommand(c, "mksquashfs", ` 534 echo Yeah, nah. >&2 535 exit 1 536 `) 537 defer mockUnsquashfs.Restore() 538 539 data := "mock kernel snap" 540 dir := makeSnapContents(c, "", data) 541 snap := squashfs.New("foo.snap") 542 c.Check(snap.Build(dir, "kernel"), ErrorMatches, `mksquashfs call failed: Yeah, nah.`) 543 } 544 545 func (s *SquashfsTestSuite) TestUnsquashfsStderrWriter(c *C) { 546 for _, t := range []struct { 547 inp []string 548 expectedErr string 549 }{ 550 { 551 inp: []string{"failed to write something\n"}, 552 expectedErr: `failed: "failed to write something"`, 553 }, 554 { 555 inp: []string{"fai", "led to write", " something\nunrelated\n"}, 556 expectedErr: `failed: "failed to write something"`, 557 }, 558 { 559 inp: []string{"failed to write\nfailed to read\n"}, 560 expectedErr: `failed: "failed to write", and "failed to read"`, 561 }, 562 { 563 inp: []string{"failed 1\nfailed 2\n3 failed\n"}, 564 expectedErr: `failed: "failed 1", "failed 2", and "3 failed"`, 565 }, 566 { 567 inp: []string{"failed 1\nfailed 2\n3 Failed\n4 Failed\n"}, 568 expectedErr: `failed: "failed 1", "failed 2", "3 Failed", and "4 Failed"`, 569 }, 570 { 571 inp: []string{"failed 1\nfailed 2\n3 Failed\n4 Failed\nfailed #5\n"}, 572 expectedErr: `failed: "failed 1", "failed 2", "3 Failed", "4 Failed", and 1 more`, 573 }, 574 } { 575 usw := squashfs.NewUnsquashfsStderrWriter() 576 for _, l := range t.inp { 577 usw.Write([]byte(l)) 578 } 579 if t.expectedErr != "" { 580 c.Check(usw.Err(), ErrorMatches, t.expectedErr, Commentf("inp: %q failed", t.inp)) 581 } else { 582 c.Check(usw.Err(), IsNil) 583 } 584 } 585 } 586 587 func (s *SquashfsTestSuite) TestBuildDate(c *C) { 588 // This env is used in reproducible builds and will force 589 // squashfs to use a specific date. We need to unset it 590 // for this specific test. 591 if oldEnv := os.Getenv("SOURCE_DATE_EPOCH"); oldEnv != "" { 592 os.Unsetenv("SOURCE_DATE_EPOCH") 593 defer func() { os.Setenv("SOURCE_DATE_EPOCH", oldEnv) }() 594 } 595 596 // make a directory 597 d := c.MkDir() 598 // set its time waaay back 599 now := time.Now() 600 then := now.Add(-10000 * time.Hour) 601 c.Assert(os.Chtimes(d, then, then), IsNil) 602 // make a snap using this directory 603 filename := filepath.Join(c.MkDir(), "foo.snap") 604 snap := squashfs.New(filename) 605 c.Assert(snap.Build(d, "app"), IsNil) 606 // and see it's BuildDate is _now_, not _then_. 607 c.Check(squashfs.BuildDate(filename), Equals, snap.BuildDate()) 608 c.Check(math.Abs(now.Sub(snap.BuildDate()).Seconds()) <= 61, Equals, true, Commentf("Unexpected build date %s", snap.BuildDate())) 609 }