Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Unified Diff: client/cmd/isolate/upload_tracker_test.go

Issue 2992113002: isolate: test uploading of individual regular files (Closed)
Patch Set: (revert accidental patchset 3) Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « client/cmd/isolate/upload_tracker.go ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: client/cmd/isolate/upload_tracker_test.go
diff --git a/client/cmd/isolate/upload_tracker_test.go b/client/cmd/isolate/upload_tracker_test.go
index ca45233ac985821177091c90e2bf4d3985b041c7..05e7d297726164f19227dd0081d0489b18ee3edd 100644
--- a/client/cmd/isolate/upload_tracker_test.go
+++ b/client/cmd/isolate/upload_tracker_test.go
@@ -18,8 +18,10 @@ import (
"bytes"
"fmt"
"io"
+ "io/ioutil"
"os"
"reflect"
+ "strings"
"testing"
"github.com/luci/luci-go/common/isolated"
@@ -30,7 +32,8 @@ import (
// Fake OS imitiates a filesystem by storing file contents in a map.
// It also provides a dummy Readlink implementation.
type fakeOS struct {
- files map[string]*bytes.Buffer
+ writeFiles map[string]*bytes.Buffer
+ readFiles map[string]io.Reader
}
// shouldResembleByteMap asserts that actual (a map[string]*bytes.Buffer) contains
@@ -73,11 +76,20 @@ func (nopWriteCloser) Close() error { return nil }
// implements OpenFile by returning a writer that writes to a bytes.Buffer.
func (fos *fakeOS) OpenFile(name string, flag int, perm os.FileMode) (io.WriteCloser, error) {
- if fos.files == nil {
- fos.files = make(map[string]*bytes.Buffer)
+ if fos.writeFiles == nil {
+ fos.writeFiles = make(map[string]*bytes.Buffer)
}
- fos.files[name] = &bytes.Buffer{}
- return nopWriteCloser{fos.files[name]}, nil
+ fos.writeFiles[name] = &bytes.Buffer{}
+ return nopWriteCloser{fos.writeFiles[name]}, nil
+}
+
+// implements Open by returning a pre-configured Reader.
+func (fos *fakeOS) Open(name string) (io.ReadCloser, error) {
+ r, ok := fos.readFiles[name]
+ if !ok {
+ panic(fmt.Sprintf("fakeOS: file not found (%s); not implemented.", name))
+ }
+ return ioutil.NopCloser(r), nil
}
// fakeChecker implements Checker by responding to method invocations by
@@ -106,6 +118,8 @@ func (checker *fakeChecker) Close() error { return nil }
type fakeUploader struct {
// uploadBytesCalls is a record of the arguments to each call of UploadBytes.
uploadBytesCalls []uploaderUploadBytesArgs
+ // uploadFileCalls is a record of the arguments to each call of UploadFile.
+ uploadFileCalls []uploaderUploadFileArgs
Uploader // TODO(mcgreevy): implement other methods.
}
@@ -116,10 +130,20 @@ type uploaderUploadBytesArgs struct {
ps *isolatedclient.PushState
}
-func (uploader *fakeUploader) UploadBytes(relPath string, isolJSON []byte, ps *isolatedclient.PushState, f func()) {
+type uploaderUploadFileArgs struct {
+ item *Item
+ ps *isolatedclient.PushState
+}
+
+func (uploader *fakeUploader) UploadBytes(relPath string, isolJSON []byte, ps *isolatedclient.PushState, done func()) {
uploader.uploadBytesCalls = append(uploader.uploadBytesCalls, uploaderUploadBytesArgs{relPath, isolJSON, ps})
+ done()
}
+func (uploader *fakeUploader) UploadFile(item *Item, ps *isolatedclient.PushState, done func()) {
+ uploader.uploadFileCalls = append(uploader.uploadFileCalls, uploaderUploadFileArgs{item, ps})
+ done()
+}
func (uploader *fakeUploader) Close() error { return nil }
func TestSkipsUpload(t *testing.T) {
@@ -149,7 +173,7 @@ func TestSkipsUpload(t *testing.T) {
// In this test, the only item that is checked and uploaded is the generated isolated file.
wantIsolJSON := []byte(`{"algo":"","version":""}`)
- So(fos.files, shouldResembleByteMap, map[string][]byte{"/a/isolatedPath": wantIsolJSON})
+ So(fos.writeFiles, shouldResembleByteMap, map[string][]byte{"/a/isolatedPath": wantIsolJSON})
So(isolSummary.Digest, ShouldResemble, isolated.HashBytes(wantIsolJSON))
So(isolSummary.Name, ShouldEqual, "isolatedPath")
@@ -185,7 +209,7 @@ func TestDontSkipUpload(t *testing.T) {
// In this test, the only item that is checked and uploaded is the generated isolated file.
wantIsolJSON := []byte(`{"algo":"","version":""}`)
- So(fos.files, shouldResembleByteMap, map[string][]byte{"/a/isolatedPath": wantIsolJSON})
+ So(fos.writeFiles, shouldResembleByteMap, map[string][]byte{"/a/isolatedPath": wantIsolJSON})
So(isolSummary.Digest, ShouldResemble, isolated.HashBytes(wantIsolJSON))
So(isolSummary.Name, ShouldEqual, "isolatedPath")
@@ -236,7 +260,71 @@ func TestHandlesSymlinks(t *testing.T) {
// In this test, the only item that is checked and uploaded is the generated isolated file.
wantIsolJSON := []byte(`{"algo":"","files":{"c":{"l":"link:/a/b/c"}},"version":""}`)
- So(fos.files, shouldResembleByteMap, map[string][]byte{"/a/isolatedPath": wantIsolJSON})
+ So(fos.writeFiles, shouldResembleByteMap, map[string][]byte{"/a/isolatedPath": wantIsolJSON})
+
+ So(isolSummary.Digest, ShouldResemble, isolated.HashBytes(wantIsolJSON))
+ So(isolSummary.Name, ShouldEqual, "isolatedPath")
+
+ So(uploader.uploadBytesCalls, ShouldResemble, []uploaderUploadBytesArgs{
+ {"isolatedPath", wantIsolJSON, checker.ps},
+ })
+ })
+}
+
+func TestHandlesIndividualFiles(t *testing.T) {
+ t.Parallel()
+ Convey(`Individual files should be stored in the isolated json and uploaded`, t, func() {
+ isol := &isolated.Isolated{}
+
+ // non-nil PushState means don't skip the upload.
+ pushState := &isolatedclient.PushState{}
+ checker := &fakeChecker{ps: pushState}
+ uploader := &fakeUploader{}
+
+ ut := NewUploadTracker(checker, uploader, isol)
+ fos := &fakeOS{
+ readFiles: map[string]io.Reader{
+ "/a/b/foo": strings.NewReader("foo contents"),
+ "/a/b/bar": strings.NewReader("bar contents"),
+ },
+ }
+ ut.lOS = fos // Override filesystem calls with fake.
+
+ parts := partitionedDeps{
+ indivFiles: itemGroup{
+ items: []*Item{
+ {Path: "/a/b/foo", RelPath: "foo", Size: 1, Mode: 004},
+ {Path: "/a/b/bar", RelPath: "bar", Size: 2, Mode: 006},
+ },
+ totalSize: 3,
+ },
+ }
+ err := ut.UploadDeps(parts)
+ So(err, ShouldBeNil)
+
+ fooHash := isolated.HashBytes([]byte("foo contents"))
+ barHash := isolated.HashBytes([]byte("bar contents"))
+ wantFiles := map[string]isolated.File{
+ "foo": {
+ Digest: fooHash,
+ Mode: Int(4),
+ Size: Int64(1)},
+ "bar": {
+ Digest: barHash,
+ Mode: Int(6),
+ Size: Int64(2)},
+ }
+
+ So(ut.isol.Files, ShouldResemble, wantFiles)
+
+ So(uploader.uploadBytesCalls, ShouldEqual, nil)
+
+ isolSummary, err := ut.Finalize("/a/isolatedPath")
+ So(err, ShouldBeNil)
+
+ wantIsolJSONTmpl := `{"algo":"","files":{"bar":{"h":"%s","m":6,"s":2},"foo":{"h":"%s","m":4,"s":1}},"version":""}`
+ wantIsolJSON := []byte(fmt.Sprintf(wantIsolJSONTmpl, barHash, fooHash))
+ So(fos.writeFiles, shouldResembleByteMap, map[string][]byte{"/a/isolatedPath": wantIsolJSON})
So(isolSummary.Digest, ShouldResemble, isolated.HashBytes(wantIsolJSON))
So(isolSummary.Name, ShouldEqual, "isolatedPath")
@@ -244,5 +332,33 @@ func TestHandlesSymlinks(t *testing.T) {
So(uploader.uploadBytesCalls, ShouldResemble, []uploaderUploadBytesArgs{
{"isolatedPath", wantIsolJSON, checker.ps},
})
+ So(uploader.uploadFileCalls, ShouldResemble, []uploaderUploadFileArgs{
+ {
+ item: &Item{
+ Path: "/a/b/foo",
+ RelPath: "foo",
+ Size: 1,
+ Mode: os.FileMode(4),
+ Digest: fooHash,
+ },
+ ps: pushState,
+ },
+ {
+ item: &Item{
+ Path: "/a/b/bar",
+ RelPath: "bar",
+ Size: 2,
+ Mode: os.FileMode(6),
+ Digest: barHash,
+ },
+ ps: pushState,
+ },
+ })
})
}
+
+// Int is a helper routine that allocates a new int value to store v and returns a pointer to it.
+func Int(i int) *int { return &i }
+
+// Int64 is a helper routine that allocates a new int64 value to store v and returns a pointer to it.
+func Int64(i int64) *int64 { return &i }
« no previous file with comments | « client/cmd/isolate/upload_tracker.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698