blob: 7d7a2b90caba164719bf0d3fed14cbbb2c00d0d9 [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 pmhttp
import (
"encoding/json"
"errors"
"math"
"os"
"path/filepath"
"testing"
tuf_data "github.com/theupdateframework/go-tuf/data"
"go.fuchsia.dev/fuchsia/src/sys/pkg/bin/pm/repo"
repo_structs "go.fuchsia.dev/fuchsia/src/sys/pkg/lib/repo"
)
func TestConfigV2(t *testing.T) {
repoDir := t.TempDir()
repository, err := repo.New(repoDir, t.TempDir())
if err != nil {
t.Fatal(err)
}
if err := repository.Init(); err != nil {
t.Fatal(err)
}
if err := repository.AddTargets([]string{}, json.RawMessage{}); err != nil {
t.Fatal(err)
}
if err := repository.CommitUpdates(false); err != nil {
t.Fatal(err)
}
rootBytes, err := os.ReadFile(filepath.Join(repoDir, "repository", "root.json"))
if err != nil {
t.Fatal(err)
}
t.Run("parse config", func(t *testing.T) {
var signed tuf_data.Signed
var root tuf_data.Root
if err := json.Unmarshal(rootBytes, &signed); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(signed.Signed, &root); err != nil {
t.Fatal(err)
}
server := NewConfigServerV2(func() []byte { return rootBytes }, false)
config, err := server.parseConfig("http://localhost")
if err != nil {
t.Fatal(err)
}
if root.Version != int(config.RootVersion) {
t.Fatalf("expected root version to be %v, not %v", root.Version, config.RootVersion)
}
rootRole, ok := root.Roles["root"]
if !ok {
t.Fatalf("root does not have root role")
}
if rootRole.Threshold != int(config.RootThreshold) {
t.Fatalf("expected root version to be %v, not %v", root.Version, config.RootThreshold)
}
})
t.Run("parse config with persistency flag set", func(t *testing.T) {
var signed tuf_data.Signed
var root tuf_data.Root
if err := json.Unmarshal(rootBytes, &signed); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(signed.Signed, &root); err != nil {
t.Fatal(err)
}
server := NewConfigServerV2(func() []byte { return rootBytes }, true)
config, err := server.parseConfig("http://localhost")
if err != nil {
t.Fatal(err)
}
if root.Version != int(config.RootVersion) {
t.Fatalf("expected root version to be %v, not %v", root.Version, config.RootVersion)
}
rootRole, ok := root.Roles["root"]
if !ok {
t.Fatalf("root does not have root role")
}
if rootRole.Threshold != int(config.RootThreshold) {
t.Fatalf("expected root version to be %v, not %v", root.Version, config.RootThreshold)
}
if config.StorageType != repo_structs.Persistent {
t.Fatalf("expected storage type to be %v, not %v", repo_structs.Persistent, config.StorageType)
}
})
t.Run("parse config errs with underflow root version", func(t *testing.T) {
var signed tuf_data.Signed
var root tuf_data.Root
if err := json.Unmarshal(rootBytes, &signed); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(signed.Signed, &root); err != nil {
t.Fatal(err)
}
root.Version = -1
signed.Signed, err = json.Marshal(root)
if err != nil {
t.Fatal(err)
}
badRootBytes, err := json.Marshal(signed)
if err != nil {
t.Fatal(err)
}
server := NewConfigServerV2(func() []byte { return badRootBytes }, false)
if _, err := server.parseConfig("http://localhost"); !errors.Is(err, OutOfRangeError) {
t.Fatalf("expected error to be out of range, not %v", err)
}
})
t.Run("parse config errs with overflow root version", func(t *testing.T) {
var signed tuf_data.Signed
var root tuf_data.Root
if err := json.Unmarshal(rootBytes, &signed); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(signed.Signed, &root); err != nil {
t.Fatal(err)
}
root.Version = math.MaxUint32 + 1
signed.Signed, err = json.Marshal(root)
if err != nil {
t.Fatal(err)
}
badRootBytes, err := json.Marshal(signed)
if err != nil {
t.Fatal(err)
}
server := NewConfigServerV2(func() []byte { return badRootBytes }, false)
if _, err := server.parseConfig("http://localhost"); !errors.Is(err, OutOfRangeError) {
t.Fatalf("expected error to be out of range, not %v", err)
}
})
t.Run("parse config errs with underflow root threshold", func(t *testing.T) {
var signed tuf_data.Signed
var root tuf_data.Root
if err := json.Unmarshal(rootBytes, &signed); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(signed.Signed, &root); err != nil {
t.Fatal(err)
}
root.Roles["root"].Threshold = -1
signed.Signed, err = json.Marshal(root)
if err != nil {
t.Fatal(err)
}
badRootBytes, err := json.Marshal(signed)
if err != nil {
t.Fatal(err)
}
server := NewConfigServerV2(func() []byte { return badRootBytes }, false)
if _, err := server.parseConfig("http://localhost"); !errors.Is(err, OutOfRangeError) {
t.Fatalf("expected error to be out of range, not %v", err)
}
})
t.Run("parse config errs with overrflow root threshold", func(t *testing.T) {
var signed tuf_data.Signed
var root tuf_data.Root
if err := json.Unmarshal(rootBytes, &signed); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(signed.Signed, &root); err != nil {
t.Fatal(err)
}
root.Roles["root"].Threshold = math.MaxUint32 + 1
signed.Signed, err = json.Marshal(root)
if err != nil {
t.Fatal(err)
}
badRootBytes, err := json.Marshal(signed)
if err != nil {
t.Fatal(err)
}
server := NewConfigServerV2(func() []byte { return badRootBytes }, false)
if _, err := server.parseConfig("http://localhost"); !errors.Is(err, OutOfRangeError) {
t.Fatalf("expected error to be out of range, not %v", err)
}
})
}
func TestBuildRepoUrl(t *testing.T) {
testCases := []struct {
url string
want string
}{
{
url: "fuchsia-pkg://devhost",
want: "fuchsia-pkg://devhost",
},
{
url: "fuchsia-pkg://DEVHOST",
want: "fuchsia-pkg://devhost",
},
{
url: "http://fuchsia.com",
want: "fuchsia-pkg://fuchsia.com",
},
{
url: "https://fuchsia.com/packages",
want: "fuchsia-pkg://fuchsia.com-packages",
},
}
for _, tc := range testCases {
got := buildRepoUrl(tc.url)
if got != tc.want {
t.Errorf("buildRepoUrl(%v) returned %v, wanted %v", tc.url, got, tc.want)
}
}
}