| // Copyright 2019 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| package repo |
| |
| import ( |
| "context" |
| "encoding/base64" |
| "fmt" |
| "github.com/golang/mock/gomock" |
| "go.chromium.org/chromiumos/infra/go/internal/gerrit" |
| gitilespb "go.chromium.org/luci/common/proto/gitiles" |
| "gotest.tools/assert" |
| "net/http" |
| "testing" |
| ) |
| |
| func TestFetchFilesFromGitiles_success(t *testing.T) { |
| ctl := gomock.NewController(t) |
| defer ctl.Finish() |
| |
| // This is a base64-encoded .tar.gz file containing a snapshot of external full.xml and |
| // _remotes.xml. I apologize to your eyes. This is a good representation of what comes back from |
| // the Gitiles Archive call though. |
| base64Enc := `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` |
| // Override because this is the name of the file in the above base64 gibberish. |
| rootXml = "full.xml" |
| encodedZip, err := base64.StdEncoding.DecodeString(base64Enc) |
| if err != nil { |
| t.Error(err) |
| } |
| |
| gitilesMock := gitilespb.NewMockGitilesClient(ctl) |
| gitilesMock.EXPECT().Archive(gomock.Any(), gomock.Any()).Times(2).Return( |
| &gitilespb.ArchiveResponse{ |
| Contents: encodedZip, |
| }, |
| nil, |
| ) |
| gerrit.MockGitiles = gitilesMock |
| |
| m, err := GetRepoToSourceRootFromManifests(http.DefaultClient, context.Background(), "master") |
| if err != nil { |
| t.Error(err) |
| } |
| if len(m) != 176 { |
| t.Errorf("expected %d project mappings, found %d", 176, len(m)) |
| } |
| // Make sure that a sample project is present. |
| if m["chromiumos/platform/mosys"] != "src/platform/mosys" { |
| t.Errorf("expected to find a mapping for mosys repo. Got mappings: %v", m) |
| } |
| } |
| |
| func ManifestEq(a, b *Manifest) bool { |
| if len(a.Projects) != len(b.Projects) { |
| return false |
| } |
| for i := range a.Projects { |
| if a.Projects[i] != b.Projects[i] { |
| return false |
| } |
| } |
| if len(a.Includes) != len(b.Includes) { |
| return false |
| } |
| for i := range a.Includes { |
| if a.Includes[i] != b.Includes[i] { |
| return false |
| } |
| } |
| return true |
| } |
| |
| func ManifestMapEq(expected, actual map[string]*Manifest) error { |
| for file := range expected { |
| if _, ok := actual[file]; !ok { |
| return fmt.Errorf("missing manifest %s", file) |
| } |
| if !ManifestEq(expected[file], actual[file]) { |
| return fmt.Errorf("expected %v, found %v", expected[file], actual[file]) |
| } |
| } |
| return nil |
| } |
| |
| func TestLoadManifestFromFile_success(t *testing.T) { |
| expected_results := make(map[string]*Manifest) |
| expected_results["test_data/foo.xml"] = &Manifest{ |
| Projects: []Project{ |
| {Path: "baz/", Name: "baz", Revision: "123", RemoteName: "chromium"}, |
| {Path: "fiz/", Name: "fiz", Revision: "124", RemoteName: "chromeos"}, |
| {Path: "buz/", Name: "buz", Revision: "125", RemoteName: "google"}, |
| }, |
| Includes: []Include{ |
| {"bar.xml"}, |
| }, |
| } |
| expected_results["test_data/bar.xml"] = &Manifest{ |
| Projects: []Project{ |
| {Path: "baz/", Name: "baz"}, |
| }, |
| } |
| |
| res, err := LoadManifestFromFile("test_data/foo.xml") |
| assert.NilError(t, err) |
| if err = ManifestMapEq(expected_results, res); err != nil { |
| t.Errorf(err.Error()) |
| } |
| } |
| |
| func TestLoadManifestFromFile_bad_include(t *testing.T) { |
| _, err := LoadManifestFromFile("test_data/bogus.xml") |
| assert.ErrorContains(t, err, "bad-include.xml") |
| } |
| |
| func TestLoadManifestFromFile_bad_xml(t *testing.T) { |
| _, err := LoadManifestFromFile("test_data/invalid.xml") |
| assert.ErrorContains(t, err, "unmarshal") |
| } |
| |
| func TestGetUniqueProject(t *testing.T) { |
| manifest := &Manifest{ |
| Projects: []Project{ |
| {Path: "foo-a/", Name: "foo"}, |
| {Path: "foo-b/", Name: "foo"}, |
| {Path: "bar/", Name: "bar"}, |
| }, |
| } |
| |
| _, err := manifest.GetUniqueProject("foo") |
| assert.ErrorContains(t, err, "multiple projects") |
| |
| project, err := manifest.GetUniqueProject("bar") |
| assert.NilError(t, err) |
| assert.Equal(t, project, manifest.Projects[2]) |
| } |