| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package cipd | |
| 6 | |
| 7 import ( | |
| 8 "bytes" | |
| 9 "io/ioutil" | |
| 10 "net/url" | |
| 11 "os" | |
| 12 "path/filepath" | |
| 13 "testing" | |
| 14 "time" | |
| 15 | |
| 16 . "github.com/smartystreets/goconvey/convey" | |
| 17 ) | |
| 18 | |
| 19 func TestFetchInstance(t *testing.T) { | |
| 20 Convey("Mocking remote service", t, func() { | |
| 21 tempDir, err := ioutil.TempDir("", "cipd_test") | |
| 22 So(err, ShouldBeNil) | |
| 23 Reset(func() { os.RemoveAll(tempDir) }) | |
| 24 tempFile := filepath.Join(tempDir, "pkg") | |
| 25 | |
| 26 mockClock(time.Now()) | |
| 27 mockResumableUpload() | |
| 28 | |
| 29 Convey("FetchInstance full flow", func() { | |
| 30 inst := buildInstanceInMemory("pkgname", nil) | |
| 31 defer inst.Close() | |
| 32 service := mockFetchBackend([]PackageInstance{inst}) | |
| 33 | |
| 34 out, err := os.OpenFile(tempFile, os.O_WRONLY|os.O_CREAT
E, 0666) | |
| 35 So(err, ShouldBeNil) | |
| 36 closed := false | |
| 37 defer func() { | |
| 38 if !closed { | |
| 39 out.Close() | |
| 40 } | |
| 41 }() | |
| 42 | |
| 43 err = FetchInstance(FetchInstanceOptions{ | |
| 44 Client: service.client, | |
| 45 Output: out, | |
| 46 PackageName: inst.PackageName(), | |
| 47 InstanceID: inst.InstanceID(), | |
| 48 }) | |
| 49 So(err, ShouldBeNil) | |
| 50 out.Close() | |
| 51 closed = true | |
| 52 | |
| 53 fetched, err := OpenInstanceFile(tempFile, "") | |
| 54 So(err, ShouldBeNil) | |
| 55 So(fetched.PackageName(), ShouldEqual, inst.PackageName(
)) | |
| 56 So(fetched.InstanceID(), ShouldEqual, inst.InstanceID()) | |
| 57 }) | |
| 58 }) | |
| 59 } | |
| 60 | |
| 61 func TestFetchAndDeployInstance(t *testing.T) { | |
| 62 Convey("Mocking temp dir", t, func() { | |
| 63 tempDir, err := ioutil.TempDir("", "cipd_test") | |
| 64 So(err, ShouldBeNil) | |
| 65 Reset(func() { os.RemoveAll(tempDir) }) | |
| 66 | |
| 67 mockClock(time.Now()) | |
| 68 mockResumableUpload() | |
| 69 | |
| 70 Convey("FetchAndDeployInstance full flow", func() { | |
| 71 // Build a package instance with some file. | |
| 72 inst := buildInstanceInMemory("testing/package", []File{ | |
| 73 makeTestFile("file", "test data", false), | |
| 74 }) | |
| 75 defer inst.Close() | |
| 76 service := mockFetchBackend([]PackageInstance{inst}) | |
| 77 | |
| 78 // Install the package, fetching it from the fake server
. | |
| 79 err = FetchAndDeployInstance(tempDir, FetchInstanceOptio
ns{ | |
| 80 Client: service.client, | |
| 81 PackageName: inst.PackageName(), | |
| 82 InstanceID: inst.InstanceID(), | |
| 83 }) | |
| 84 So(err, ShouldBeNil) | |
| 85 | |
| 86 // The file from the package should be installed. | |
| 87 data, err := ioutil.ReadFile(filepath.Join(tempDir, "fil
e")) | |
| 88 So(err, ShouldBeNil) | |
| 89 So(data, ShouldResemble, []byte("test data")) | |
| 90 }) | |
| 91 }) | |
| 92 } | |
| 93 | |
| 94 // buildInstanceInMemory makes fully functional PackageInstance object that uses | |
| 95 // memory buffer as a backing store. | |
| 96 func buildInstanceInMemory(pkgName string, files []File) PackageInstance { | |
| 97 out := bytes.Buffer{} | |
| 98 err := BuildInstance(BuildInstanceOptions{ | |
| 99 Input: files, | |
| 100 Output: &out, | |
| 101 PackageName: pkgName, | |
| 102 }) | |
| 103 So(err, ShouldBeNil) | |
| 104 inst, err := OpenInstance(bytes.NewReader(out.Bytes()), "") | |
| 105 So(err, ShouldBeNil) | |
| 106 return inst | |
| 107 } | |
| 108 | |
| 109 // mockFetchBackend returns remoteService that can be used by FetchInstance | |
| 110 // to download the package file (or multiple files). | |
| 111 func mockFetchBackend(instances []PackageInstance) *remoteService { | |
| 112 var readData = func(i PackageInstance) string { | |
| 113 r := i.DataReader() | |
| 114 _, err := r.Seek(0, os.SEEK_SET) | |
| 115 if err != nil { | |
| 116 panic(err) | |
| 117 } | |
| 118 data, err := ioutil.ReadAll(r) | |
| 119 if err != nil { | |
| 120 panic(err) | |
| 121 } | |
| 122 return string(data) | |
| 123 } | |
| 124 allCalls := []expectedHTTPCall{} | |
| 125 for _, inst := range instances { | |
| 126 instCalls := []expectedHTTPCall{ | |
| 127 expectedHTTPCall{ | |
| 128 Method: "GET", | |
| 129 Path: "/_ah/api/repo/v1/instance", | |
| 130 Query: url.Values{ | |
| 131 "instance_id": []string{inst.InstanceID
()}, | |
| 132 "package_name": []string{inst.PackageNam
e()}, | |
| 133 }, | |
| 134 Reply: `{ | |
| 135 "status": "SUCCESS", | |
| 136 "instance": { | |
| 137 "registered_by": "user:a@example.com", | |
| 138 "registered_ts": "0" | |
| 139 }, | |
| 140 "fetch_url": "http://localhost/fake_fetch_url" | |
| 141 }`, | |
| 142 }, | |
| 143 // Simulate a transient error. | |
| 144 expectedHTTPCall{ | |
| 145 Method: "GET", | |
| 146 Path: "/fake_fetch_url", | |
| 147 Status: 500, | |
| 148 Reply: "error", | |
| 149 }, | |
| 150 expectedHTTPCall{ | |
| 151 Method: "GET", | |
| 152 Path: "/fake_fetch_url", | |
| 153 Status: 200, | |
| 154 Reply: readData(inst), | |
| 155 }, | |
| 156 } | |
| 157 allCalls = append(allCalls, instCalls...) | |
| 158 } | |
| 159 return mockRemoteServiceWithExpectations(allCalls) | |
| 160 } | |
| OLD | NEW |