additional project info Test: m droid Bug: 254901942 Change-Id: I3de4bc528bd321c76900d277295bb10709035a9c
723 lines
18 KiB
Go
723 lines
18 KiB
Go
// Copyright 2022 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package projectmetadata
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"android/soong/compliance/project_metadata_proto"
|
|
"android/soong/tools/compliance/testfs"
|
|
)
|
|
|
|
const (
|
|
// EMPTY represents a METADATA file with no recognized fields
|
|
EMPTY = ``
|
|
|
|
// INVALID_NAME represents a METADATA file with the wrong type of name
|
|
INVALID_NAME = `name: a library\n`
|
|
|
|
// INVALID_DESCRIPTION represents a METADATA file with the wrong type of description
|
|
INVALID_DESCRIPTION = `description: unquoted text\n`
|
|
|
|
// INVALID_VERSION represents a METADATA file with the wrong type of version
|
|
INVALID_VERSION = `third_party { version: 1 }`
|
|
|
|
// MY_LIB_1_0 represents a METADATA file for version 1.0 of mylib
|
|
MY_LIB_1_0 = `name: "mylib" description: "my library" third_party { version: "1.0" }`
|
|
|
|
// NO_NAME_0_1 represents a METADATA file with a description but no name
|
|
NO_NAME_0_1 = `description: "my library" third_party { version: "0.1" }`
|
|
|
|
// URL values per type
|
|
GIT_URL = "http://example.github.com/my_lib"
|
|
SVN_URL = "http://example.svn.com/my_lib"
|
|
HG_URL = "http://example.hg.com/my_lib"
|
|
DARCS_URL = "http://example.darcs.com/my_lib"
|
|
PIPER_URL = "http://google3/third_party/my/package"
|
|
HOMEPAGE_URL = "http://example.com/homepage"
|
|
OTHER_URL = "http://google.com/"
|
|
ARCHIVE_URL = "http://ftp.example.com/"
|
|
LOCAL_SOURCE_URL = "https://android.googlesource.com/platform/external/apache-http/"
|
|
)
|
|
|
|
// libWithUrl returns a METADATA file with the right download url
|
|
func libWithUrl(urlTypes ...string) string {
|
|
var sb strings.Builder
|
|
|
|
fmt.Fprintln(&sb, `name: "mylib" description: "my library"
|
|
third_party {
|
|
version: "1.0"`)
|
|
|
|
for _, urltype := range urlTypes {
|
|
var urlValue string
|
|
switch urltype {
|
|
case "GIT":
|
|
urlValue = GIT_URL
|
|
case "SVN":
|
|
urlValue = SVN_URL
|
|
case "HG":
|
|
urlValue = HG_URL
|
|
case "DARCS":
|
|
urlValue = DARCS_URL
|
|
case "PIPER":
|
|
urlValue = PIPER_URL
|
|
case "HOMEPAGE":
|
|
urlValue = HOMEPAGE_URL
|
|
case "OTHER":
|
|
urlValue = OTHER_URL
|
|
case "ARCHIVE":
|
|
urlValue = ARCHIVE_URL
|
|
case "LOCAL_SOURCE":
|
|
urlValue = LOCAL_SOURCE_URL
|
|
default:
|
|
panic(fmt.Errorf("unknown url type: %q. Please update libWithUrl() in build/make/tools/compliance/projectmetadata/projectmetadata_test.go", urltype))
|
|
}
|
|
fmt.Fprintf(&sb, " url { type: %s value: %q }\n", urltype, urlValue)
|
|
}
|
|
fmt.Fprintln(&sb, `}`)
|
|
|
|
return sb.String()
|
|
}
|
|
|
|
func TestVerifyAllUrlTypes(t *testing.T) {
|
|
t.Run("verifyAllUrlTypes", func(t *testing.T) {
|
|
types := make([]string, 0, len(project_metadata_proto.URL_Type_value))
|
|
for t := range project_metadata_proto.URL_Type_value {
|
|
types = append(types, t)
|
|
}
|
|
libWithUrl(types...)
|
|
})
|
|
}
|
|
|
|
func TestUnknownPanics(t *testing.T) {
|
|
t.Run("Unknown panics", func(t *testing.T) {
|
|
defer func() {
|
|
if r := recover(); r == nil {
|
|
t.Errorf("unexpected success: got no error, want panic")
|
|
}
|
|
}()
|
|
libWithUrl("SOME WILD VALUE THAT DOES NOT EXIST")
|
|
})
|
|
}
|
|
|
|
func TestReadMetadataForProjects(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
fs *testfs.TestFS
|
|
projects []string
|
|
expectedError string
|
|
expected []pmeta
|
|
}{
|
|
{
|
|
name: "trivial",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte("name: \"Android\"\n"),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "Android",
|
|
name: "Android",
|
|
version: "",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "versioned",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(MY_LIB_1_0),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_homepage",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("HOMEPAGE")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_git",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("GIT")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: GIT_URL,
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_svn",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("SVN")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: SVN_URL,
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_hg",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("HG")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: HG_URL,
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_darcs",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("DARCS")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: DARCS_URL,
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_piper",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("PIPER")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_other",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("OTHER")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_local_source",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("LOCAL_SOURCE")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_archive",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("ARCHIVE")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_all_downloads",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("DARCS", "HG", "SVN", "GIT")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: GIT_URL,
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_all_downloads_in_different_order",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("DARCS", "GIT", "SVN", "HG")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: GIT_URL,
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_all_but_git",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("DARCS", "HG", "SVN")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: SVN_URL,
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_all_but_git_and_svn",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("DARCS", "HG")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: HG_URL,
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_all_nondownloads_and_git",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("HOMEPAGE", "LOCAL_SOURCE", "PIPER", "ARCHIVE", "GIT")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: GIT_URL,
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_all_nondownloads",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl("HOMEPAGE", "LOCAL_SOURCE", "PIPER", "ARCHIVE")),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "lib_with_all_nondownloads",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(libWithUrl()),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "versioneddesc",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(NO_NAME_0_1),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "my library",
|
|
name: "",
|
|
version: "0.1",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "unterminated",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte("name: \"Android\n"),
|
|
},
|
|
projects: []string{"/a"},
|
|
expectedError: `invalid character '\n' in string`,
|
|
},
|
|
{
|
|
name: "abc",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(EMPTY),
|
|
"/b/METADATA": []byte(MY_LIB_1_0),
|
|
"/c/METADATA": []byte(NO_NAME_0_1),
|
|
},
|
|
projects: []string{"/a", "/b", "/c"},
|
|
expected: []pmeta{
|
|
{
|
|
project: "/a",
|
|
versionedName: "",
|
|
name: "",
|
|
version: "",
|
|
downloadUrl: "",
|
|
},
|
|
{
|
|
project: "/b",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
},
|
|
{
|
|
project: "/c",
|
|
versionedName: "my library",
|
|
name: "",
|
|
version: "0.1",
|
|
downloadUrl: "",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "ab",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(EMPTY),
|
|
"/b/METADATA": []byte(MY_LIB_1_0),
|
|
},
|
|
projects: []string{"/a", "/b", "/c"},
|
|
expected: []pmeta{
|
|
{
|
|
project: "/a",
|
|
versionedName: "",
|
|
name: "",
|
|
version: "",
|
|
downloadUrl: "",
|
|
},
|
|
{
|
|
project: "/b",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "ac",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(EMPTY),
|
|
"/c/METADATA": []byte(NO_NAME_0_1),
|
|
},
|
|
projects: []string{"/a", "/b", "/c"},
|
|
expected: []pmeta{
|
|
{
|
|
project: "/a",
|
|
versionedName: "",
|
|
name: "",
|
|
version: "",
|
|
downloadUrl: "",
|
|
},
|
|
{
|
|
project: "/c",
|
|
versionedName: "my library",
|
|
name: "",
|
|
version: "0.1",
|
|
downloadUrl: "",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "bc",
|
|
fs: &testfs.TestFS{
|
|
"/b/METADATA": []byte(MY_LIB_1_0),
|
|
"/c/METADATA": []byte(NO_NAME_0_1),
|
|
},
|
|
projects: []string{"/a", "/b", "/c"},
|
|
expected: []pmeta{
|
|
{
|
|
project: "/b",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
},
|
|
{
|
|
project: "/c",
|
|
versionedName: "my library",
|
|
name: "",
|
|
version: "0.1",
|
|
downloadUrl: "",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "wrongnametype",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(INVALID_NAME),
|
|
},
|
|
projects: []string{"/a"},
|
|
expectedError: `invalid value for string type`,
|
|
},
|
|
{
|
|
name: "wrongdescriptiontype",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(INVALID_DESCRIPTION),
|
|
},
|
|
projects: []string{"/a"},
|
|
expectedError: `invalid value for string type`,
|
|
},
|
|
{
|
|
name: "wrongversiontype",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(INVALID_VERSION),
|
|
},
|
|
projects: []string{"/a"},
|
|
expectedError: `invalid value for string type`,
|
|
},
|
|
{
|
|
name: "wrongtype",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(INVALID_NAME + INVALID_DESCRIPTION + INVALID_VERSION),
|
|
},
|
|
projects: []string{"/a"},
|
|
expectedError: `invalid value for string type`,
|
|
},
|
|
{
|
|
name: "empty",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(EMPTY),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "",
|
|
name: "",
|
|
version: "",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "emptyother",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA.bp": []byte(EMPTY),
|
|
},
|
|
projects: []string{"/a"},
|
|
},
|
|
{
|
|
name: "emptyfs",
|
|
fs: &testfs.TestFS{},
|
|
projects: []string{"/a"},
|
|
},
|
|
{
|
|
name: "override",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(INVALID_NAME + INVALID_DESCRIPTION + INVALID_VERSION),
|
|
"/a/METADATA.android": []byte(MY_LIB_1_0),
|
|
},
|
|
projects: []string{"/a"},
|
|
expected: []pmeta{{
|
|
project: "/a",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "enchilada",
|
|
fs: &testfs.TestFS{
|
|
"/a/METADATA": []byte(INVALID_NAME + INVALID_DESCRIPTION + INVALID_VERSION),
|
|
"/a/METADATA.android": []byte(EMPTY),
|
|
"/b/METADATA": []byte(MY_LIB_1_0),
|
|
"/c/METADATA": []byte(NO_NAME_0_1),
|
|
},
|
|
projects: []string{"/a", "/b", "/c"},
|
|
expected: []pmeta{
|
|
{
|
|
project: "/a",
|
|
versionedName: "",
|
|
name: "",
|
|
version: "",
|
|
downloadUrl: "",
|
|
},
|
|
{
|
|
project: "/b",
|
|
versionedName: "mylib_v_1.0",
|
|
name: "mylib",
|
|
version: "1.0",
|
|
downloadUrl: "",
|
|
},
|
|
{
|
|
project: "/c",
|
|
versionedName: "my library",
|
|
name: "",
|
|
version: "0.1",
|
|
downloadUrl: "",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ix := NewIndex(tt.fs)
|
|
pms, err := ix.MetadataForProjects(tt.projects...)
|
|
if err != nil {
|
|
if len(tt.expectedError) == 0 {
|
|
t.Errorf("unexpected error: got %s, want no error", err)
|
|
} else if !strings.Contains(err.Error(), tt.expectedError) {
|
|
t.Errorf("unexpected error: got %s, want %q", err, tt.expectedError)
|
|
}
|
|
return
|
|
}
|
|
t.Logf("actual %d project metadata", len(pms))
|
|
for _, pm := range pms {
|
|
t.Logf(" %v", pm.String())
|
|
}
|
|
t.Logf("expected %d project metadata", len(tt.expected))
|
|
for _, pm := range tt.expected {
|
|
t.Logf(" %s", pm.String())
|
|
}
|
|
if len(tt.expectedError) > 0 {
|
|
t.Errorf("unexpected success: got no error, want %q err", tt.expectedError)
|
|
return
|
|
}
|
|
if len(pms) != len(tt.expected) {
|
|
t.Errorf("missing project metadata: got %d project metadata, want %d", len(pms), len(tt.expected))
|
|
}
|
|
for i := 0; i < len(pms) && i < len(tt.expected); i++ {
|
|
if msg := tt.expected[i].difference(pms[i]); msg != "" {
|
|
t.Errorf("unexpected metadata starting at index %d: %s", i, msg)
|
|
return
|
|
}
|
|
}
|
|
if len(pms) < len(tt.expected) {
|
|
t.Errorf("missing metadata starting at index %d: got nothing, want %s", len(pms), tt.expected[len(pms)].String())
|
|
}
|
|
if len(tt.expected) < len(pms) {
|
|
t.Errorf("unexpected metadata starting at index %d: got %s, want nothing", len(tt.expected), pms[len(tt.expected)].String())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
type pmeta struct {
|
|
project string
|
|
versionedName string
|
|
name string
|
|
version string
|
|
downloadUrl string
|
|
}
|
|
|
|
func (pm pmeta) String() string {
|
|
return fmt.Sprintf("project: %q versionedName: %q name: %q version: %q downloadUrl: %q\n", pm.project, pm.versionedName, pm.name, pm.version, pm.downloadUrl)
|
|
}
|
|
|
|
func (pm pmeta) equals(other *ProjectMetadata) bool {
|
|
if pm.project != other.project {
|
|
return false
|
|
}
|
|
if pm.versionedName != other.VersionedName() {
|
|
return false
|
|
}
|
|
if pm.name != other.Name() {
|
|
return false
|
|
}
|
|
if pm.version != other.Version() {
|
|
return false
|
|
}
|
|
if pm.downloadUrl != other.UrlsByTypeName().DownloadUrl() {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (pm pmeta) difference(other *ProjectMetadata) string {
|
|
if pm.equals(other) {
|
|
return ""
|
|
}
|
|
var sb strings.Builder
|
|
fmt.Fprintf(&sb, "got")
|
|
if pm.project != other.project {
|
|
fmt.Fprintf(&sb, " project: %q", other.project)
|
|
}
|
|
if pm.versionedName != other.VersionedName() {
|
|
fmt.Fprintf(&sb, " versionedName: %q", other.VersionedName())
|
|
}
|
|
if pm.name != other.Name() {
|
|
fmt.Fprintf(&sb, " name: %q", other.Name())
|
|
}
|
|
if pm.version != other.Version() {
|
|
fmt.Fprintf(&sb, " version: %q", other.Version())
|
|
}
|
|
if pm.downloadUrl != other.UrlsByTypeName().DownloadUrl() {
|
|
fmt.Fprintf(&sb, " downloadUrl: %q", other.UrlsByTypeName().DownloadUrl())
|
|
}
|
|
fmt.Fprintf(&sb, ", want")
|
|
if pm.project != other.project {
|
|
fmt.Fprintf(&sb, " project: %q", pm.project)
|
|
}
|
|
if pm.versionedName != other.VersionedName() {
|
|
fmt.Fprintf(&sb, " versionedName: %q", pm.versionedName)
|
|
}
|
|
if pm.name != other.Name() {
|
|
fmt.Fprintf(&sb, " name: %q", pm.name)
|
|
}
|
|
if pm.version != other.Version() {
|
|
fmt.Fprintf(&sb, " version: %q", pm.version)
|
|
}
|
|
if pm.downloadUrl != other.UrlsByTypeName().DownloadUrl() {
|
|
fmt.Fprintf(&sb, " downloadUrl: %q", pm.downloadUrl)
|
|
}
|
|
return sb.String()
|
|
}
|