Chromium Code Reviews| Index: client/cmd/isolate/exp_archive_test.go |
| diff --git a/client/cmd/isolate/exp_archive_test.go b/client/cmd/isolate/exp_archive_test.go |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..fb6948fe3dfc3fcca7733bc2533135f393fcfc8c |
| --- /dev/null |
| +++ b/client/cmd/isolate/exp_archive_test.go |
| @@ -0,0 +1,228 @@ |
| +// Copyright 2017 The LUCI Authors. All rights reserved. |
| +// Use of this source code is governed under the Apache License, Version 2.0 |
| +// that can be found in the LICENSE file. |
| + |
| +package main |
| + |
| +import ( |
| + "errors" |
| + "os" |
| + "reflect" |
| + "testing" |
| +) |
| + |
| +// basicFileInfo implements some of os.FileInfo, and panics if unexpected parts |
| +// of that interface are called. |
| +type basicFileInfo struct { |
| + size int64 |
| + mode os.FileMode |
| + isDir bool |
| + |
| + os.FileInfo |
| +} |
| + |
| +func (bfi basicFileInfo) Size() int64 { return bfi.size } |
| +func (bfi basicFileInfo) Mode() os.FileMode { return bfi.mode } |
| +func (bfi basicFileInfo) IsDir() bool { return bfi.isDir } |
| + |
| +type file struct { |
| + path string |
| + bfi basicFileInfo |
| +} |
| + |
| +func symlink(path string, size int64) file { |
| + return file{ |
| + path: path, |
| + bfi: basicFileInfo{ |
| + size: size, |
| + mode: os.ModeSymlink, |
| + isDir: false, |
| + }, |
| + } |
| +} |
| + |
| +func regularFile(path string, size int64) file { |
| + return file{ |
| + path: path, |
| + bfi: basicFileInfo{ |
| + size: size, |
| + mode: 0, |
| + isDir: false, |
| + }, |
| + } |
| +} |
| + |
| +func directory(path string) file { |
| + return file{ |
| + path: path, |
| + bfi: basicFileInfo{ |
| + size: 0, |
| + mode: os.ModeDir, |
| + isDir: true, |
| + }, |
| + } |
| +} |
| + |
| +var errBang = errors.New("bang") |
| + |
| +func TestWalkFn(t *testing.T) { |
| + type testCase struct { |
| + name string |
| + files []file |
| + walkFnErr error |
| + want partitionedDeps |
| + wantErr error |
| + } |
| + |
| +TestCases: |
| + for _, tc := range []testCase{ |
|
mithro
2017/06/27 07:48:10
I would have tested the following cases;
* empty
mcgreevy
2017/06/28 01:25:51
Most of the tests that you have suggested below wo
mithro
2017/06/29 07:25:17
If I understand correctly, walkFn is called with a
mcgreevy
2017/06/30 01:24:19
walkFn is called with the *path*, and an os.FileIn
|
| + { |
| + name: "partitions files", |
| + files: []file{ |
| + symlink("/rootDir/patha", 1e3), |
| + regularFile("/rootDir/pathb", 10e3), |
| + regularFile("/rootDir/pathc", 100e3), |
| + }, |
| + want: partitionedDeps{ |
| + links: itemGroup{ |
| + items: []*Item{ |
| + { |
| + Path: "/rootDir/patha", |
| + RelPath: "patha", |
| + Mode: os.ModeSymlink, |
| + Size: 1e3, |
| + }, |
| + }, |
| + size: 1e3, |
| + }, |
| + archiveFiles: itemGroup{ |
| + items: []*Item{ |
| + { |
| + Path: "/rootDir/pathb", |
| + RelPath: "pathb", |
| + Mode: 0, |
| + Size: 10e3, |
| + }, |
| + }, |
| + size: 10e3, |
| + }, |
| + indivFiles: itemGroup{ |
| + items: []*Item{ |
| + { |
| + Path: "/rootDir/pathc", |
| + RelPath: "pathc", |
| + Mode: 0, |
| + Size: 100e3, |
| + }, |
| + }, |
| + size: 100e3, |
| + }, |
| + }, |
| + }, |
| + { |
| + name: "aggregates link sizes", |
| + files: []file{ |
| + symlink("/rootDir/patha", 1), |
| + symlink("/rootDir/pathb", 2), |
| + }, |
| + want: partitionedDeps{ |
| + links: itemGroup{ |
| + items: []*Item{ |
| + { |
| + Path: "/rootDir/patha", |
| + RelPath: "patha", |
| + Mode: os.ModeSymlink, |
| + Size: 1, |
|
mithro
2017/06/27 07:48:10
Why are these size 1 / 2?
mcgreevy
2017/06/28 01:25:51
When testing things that add up values, I tend to
mithro
2017/06/29 07:25:17
Minor comments;
That makes a lot of sense, but wi
mcgreevy
2017/06/30 01:24:19
OK, done.
|
| + }, |
| + { |
| + Path: "/rootDir/pathb", |
| + RelPath: "pathb", |
| + Mode: os.ModeSymlink, |
| + Size: 2, |
| + }, |
| + }, |
| + size: 3, |
|
mithro
2017/06/27 07:48:10
Size 3?
Is this the cumulative size / total size?
mcgreevy
2017/06/28 01:25:50
total size.
|
| + }, |
| + }, |
| + }, |
| + { |
| + name: "aggregates large file sizes", |
| + files: []file{ |
| + regularFile("/rootDir/patha", 100e3), |
| + regularFile("/rootDir/pathb", 200e3), |
| + }, |
| + want: partitionedDeps{ |
| + indivFiles: itemGroup{ |
| + items: []*Item{ |
| + { |
| + Path: "/rootDir/patha", |
| + RelPath: "patha", |
| + Mode: 0, |
| + Size: 100e3, |
| + }, |
| + { |
| + Path: "/rootDir/pathb", |
| + RelPath: "pathb", |
| + Mode: 0, |
| + Size: 200e3, |
| + }, |
| + }, |
| + size: 300e3, |
| + }, |
| + }, |
| + }, |
| + { |
| + name: "aggregates small file sizes", |
| + files: []file{ |
| + regularFile("/rootDir/patha", 10e3), |
| + regularFile("/rootDir/pathb", 20e3), |
| + }, |
| + want: partitionedDeps{ |
| + archiveFiles: itemGroup{ |
| + items: []*Item{ |
| + { |
| + Path: "/rootDir/patha", |
| + RelPath: "patha", |
| + Mode: 0, |
| + Size: 10e3, |
| + }, |
| + { |
| + Path: "/rootDir/pathb", |
| + RelPath: "pathb", |
| + Mode: 0, |
| + Size: 20e3, |
| + }, |
| + }, |
| + size: 30e3, |
| + }, |
| + }, |
| + }, |
| + { |
| + name: "returns errors unchanged", |
| + files: []file{regularFile("/rootDir/patha", 1)}, |
| + walkFnErr: errBang, |
| + want: partitionedDeps{}, |
| + wantErr: errBang, |
| + }, |
| + { |
| + name: "does nothing for directories", |
| + files: []file{directory("/rootDir/patha")}, |
| + want: partitionedDeps{}, |
| + wantErr: nil, |
| + }, |
| + } { |
| + pw := partitionWalker{rootDir: "/rootDir"} |
| + for _, f := range tc.files { |
| + err := pw.walkFn(f.path, f.bfi, tc.walkFnErr) |
| + if err != tc.wantErr { |
| + t.Errorf("partitioning deps(%s): walkFn got err %v; want %v", tc.name, err, tc.wantErr) |
| + continue TestCases |
|
mithro
2017/06/27 07:48:10
I don't quite get the usage of the continue here?
mcgreevy
2017/06/28 01:25:51
If we get an unexpected error from walkFunc, there
mithro
2017/06/29 07:25:17
I think the biggest problem is that the label for
mcgreevy
2017/06/30 01:24:19
Looking at this more closely, I think that it is w
|
| + } |
| + } |
| + if got, want := pw.parts, tc.want; !reflect.DeepEqual(got, want) { |
| + t.Errorf("partitioning deps(%s): got %#v; want %#v", tc.name, got, want) |
| + |
| + } |
| + } |
| + |
| +} |