382 lines
7.5 KiB
Go
382 lines
7.5 KiB
Go
/*
|
|
Copyright 2022 The Flux authors
|
|
|
|
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 index
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"testing"
|
|
|
|
. "github.com/onsi/gomega"
|
|
"github.com/opencontainers/go-digest"
|
|
)
|
|
|
|
func TestWithIndex(t *testing.T) {
|
|
t.Run("sets the index", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
i := map[string]string{"foo": "bar"}
|
|
d := &Digester{}
|
|
WithIndex(i)(d)
|
|
|
|
g.Expect(d.index).To(Equal(i))
|
|
})
|
|
|
|
t.Run("resets the digests", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
i := map[string]string{"foo": "bar"}
|
|
d := &Digester{
|
|
digests: map[digest.Algorithm]digest.Digest{
|
|
digest.SHA256: "sha256:foo",
|
|
},
|
|
}
|
|
WithIndex(i)(d)
|
|
|
|
g.Expect(d.digests).To(BeEmpty())
|
|
})
|
|
|
|
t.Run("handles nil index", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
d := &Digester{}
|
|
WithIndex(nil)(d)
|
|
g.Expect(d.index).To(BeNil())
|
|
})
|
|
}
|
|
|
|
func TestNewDigester(t *testing.T) {
|
|
t.Run("default", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester()
|
|
|
|
g.Expect(d).ToNot(BeNil())
|
|
g.Expect(d.index).ToNot(BeNil())
|
|
g.Expect(d.digests).ToNot(BeNil())
|
|
})
|
|
|
|
t.Run("with index", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
i := map[string]string{"foo": "bar"}
|
|
d := NewDigester(WithIndex(i))
|
|
|
|
g.Expect(d).ToNot(BeNil())
|
|
g.Expect(d.index).To(Equal(i))
|
|
g.Expect(d.digests).ToNot(BeNil())
|
|
})
|
|
}
|
|
|
|
func TestDigester_Add(t *testing.T) {
|
|
t.Run("adds", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester()
|
|
d.Add("foo", "bar")
|
|
|
|
g.Expect(d.index).To(HaveKeyWithValue("foo", "bar"))
|
|
})
|
|
|
|
t.Run("overwrites", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester()
|
|
d.Add("foo", "bar")
|
|
d.Add("foo", "baz")
|
|
|
|
g.Expect(d.index).To(HaveKeyWithValue("foo", "baz"))
|
|
})
|
|
|
|
t.Run("resets digests", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := &Digester{
|
|
index: map[string]string{},
|
|
digests: map[digest.Algorithm]digest.Digest{
|
|
digest.SHA256: "sha256:foo",
|
|
},
|
|
}
|
|
d.Add("foo", "bar")
|
|
|
|
g.Expect(d.digests).To(BeEmpty())
|
|
})
|
|
|
|
t.Run("adds empty key and value", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
d := NewDigester()
|
|
d.Add("", "")
|
|
g.Expect(d.index).To(HaveKeyWithValue("", ""))
|
|
})
|
|
}
|
|
|
|
func TestDigester_Delete(t *testing.T) {
|
|
t.Run("deletes", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester()
|
|
d.Add("foo", "bar")
|
|
d.Delete("foo")
|
|
|
|
g.Expect(d.index).ToNot(HaveKey("foo"))
|
|
})
|
|
|
|
t.Run("resets digests", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := &Digester{
|
|
index: map[string]string{
|
|
"foo": "bar",
|
|
},
|
|
digests: map[digest.Algorithm]digest.Digest{
|
|
digest.SHA256: "sha256:foo",
|
|
},
|
|
}
|
|
|
|
d.Delete("nop")
|
|
g.Expect(d.digests).To(HaveLen(1))
|
|
|
|
d.Delete("foo")
|
|
g.Expect(d.digests).To(BeEmpty())
|
|
})
|
|
|
|
t.Run("deletes non-existent key without error", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
d := NewDigester()
|
|
d.Delete("non-existent")
|
|
g.Expect(d.index).To(BeEmpty())
|
|
g.Expect(d.digests).To(BeEmpty())
|
|
})
|
|
}
|
|
|
|
func TestDigester_Get(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester()
|
|
d.Add("foo", "bar")
|
|
|
|
g.Expect(d.Get("foo")).To(Equal("bar"))
|
|
g.Expect(d.Get("bar")).To(BeEmpty())
|
|
}
|
|
|
|
func TestDigester_Has(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester()
|
|
d.Add("foo", "bar")
|
|
|
|
g.Expect(d.Has("foo")).To(BeTrue())
|
|
g.Expect(d.Has("bar")).To(BeFalse())
|
|
}
|
|
|
|
func TestDigester_Index(t *testing.T) {
|
|
t.Run("returns a copy of the index", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
i := map[string]string{
|
|
"foo": "bar",
|
|
"bar": "baz",
|
|
}
|
|
d := NewDigester(WithIndex(i))
|
|
|
|
iCopy := d.Index()
|
|
g.Expect(iCopy).To(Equal(i))
|
|
g.Expect(iCopy).ToNot(BeIdenticalTo(i))
|
|
})
|
|
|
|
t.Run("returns an empty copy for an empty index", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
d := NewDigester()
|
|
emptyIndex := d.Index()
|
|
g.Expect(emptyIndex).To(BeEmpty())
|
|
})
|
|
}
|
|
|
|
func TestDigester_Len(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester(WithIndex(map[string]string{
|
|
"foo": "bar",
|
|
"bar": "baz",
|
|
}))
|
|
|
|
g.Expect(d.Len()).To(Equal(2))
|
|
|
|
g.Expect(NewDigester().Len()).To(Equal(0))
|
|
}
|
|
|
|
func TestDigester_String(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester(WithIndex(map[string]string{
|
|
"foo": "bar",
|
|
"bar": "baz",
|
|
}))
|
|
|
|
g.Expect(d.String()).To(Equal(`bar baz
|
|
foo bar
|
|
`))
|
|
|
|
g.Expect(NewDigester().String()).To(Equal(""))
|
|
}
|
|
|
|
func TestDigester_WriteTo(t *testing.T) {
|
|
t.Run("writes", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester(WithIndex(map[string]string{
|
|
"foo": "bar",
|
|
"bar": "baz",
|
|
}))
|
|
expect := `bar baz
|
|
foo bar
|
|
`
|
|
|
|
var buf bytes.Buffer
|
|
n, err := d.WriteTo(&buf)
|
|
|
|
g.Expect(n).To(Equal(int64(len(expect))))
|
|
g.Expect(err).ToNot(HaveOccurred())
|
|
g.Expect(buf.String()).To(Equal(expect))
|
|
})
|
|
|
|
t.Run("errors", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester(WithIndex(map[string]string{
|
|
"foo": "bar",
|
|
"bar": "baz",
|
|
}))
|
|
|
|
w := &fakeWriter{
|
|
err: errors.New("write error"),
|
|
written: 5,
|
|
}
|
|
n, err := d.WriteTo(w)
|
|
|
|
g.Expect(err).To(HaveOccurred())
|
|
g.Expect(errors.Is(err, w.err)).To(BeTrue())
|
|
g.Expect(n).To(Equal(int64(w.written)))
|
|
})
|
|
}
|
|
|
|
func TestDigester_Digest(t *testing.T) {
|
|
t.Run("returns digest", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester(WithIndex(map[string]string{
|
|
"foo": "bar",
|
|
"bar": "baz",
|
|
}))
|
|
expect := digest.SHA256.FromString(d.String())
|
|
|
|
g.Expect(d.Digest(digest.SHA256)).To(Equal(expect))
|
|
g.Expect(d.digests).To(HaveKeyWithValue(digest.SHA256, expect))
|
|
})
|
|
|
|
t.Run("returns cached digest", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := &Digester{
|
|
index: map[string]string{
|
|
"foo": "bar",
|
|
"bar": "baz",
|
|
},
|
|
digests: map[digest.Algorithm]digest.Digest{
|
|
digest.SHA256: "sha256:foo",
|
|
},
|
|
}
|
|
|
|
g.Expect(d.Digest(digest.SHA256)).To(Equal(d.digests[digest.SHA256]))
|
|
})
|
|
}
|
|
|
|
func TestDigester_Verify(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester(WithIndex(map[string]string{
|
|
"foo": "bar",
|
|
}))
|
|
|
|
g.Expect(d.Verify(d.Digest(digest.SHA256))).To(BeTrue())
|
|
g.Expect(d.Verify(digest.SHA256.FromString("different"))).To(BeFalse())
|
|
}
|
|
|
|
func TestDigester_sortedKeys(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester(WithIndex(map[string]string{
|
|
"c/d/e": "bar",
|
|
"a/b/c": "baz",
|
|
"f/g/h": "foo",
|
|
}))
|
|
|
|
g.Expect(d.sortedKeys()).To(Equal([]string{
|
|
"a/b/c",
|
|
"c/d/e",
|
|
"f/g/h",
|
|
}))
|
|
}
|
|
|
|
func TestDigester_reset(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
d := NewDigester()
|
|
d.digests = map[digest.Algorithm]digest.Digest{
|
|
digest.SHA256: "sha256:foo",
|
|
}
|
|
|
|
d.reset()
|
|
g.Expect(d.digests).To(BeEmpty())
|
|
}
|
|
|
|
func Test_writeLine(t *testing.T) {
|
|
t.Run("writes", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
var buf bytes.Buffer
|
|
n, err := writeLine(&buf, "foo", "bar")
|
|
|
|
g.Expect(n).To(Equal(8))
|
|
g.Expect(err).ToNot(HaveOccurred())
|
|
g.Expect(buf.String()).To(Equal(`foo bar
|
|
`))
|
|
})
|
|
|
|
t.Run("errors", func(t *testing.T) {
|
|
g := NewWithT(t)
|
|
|
|
w := &fakeWriter{
|
|
err: errors.New("write error"),
|
|
written: 5,
|
|
}
|
|
n, err := writeLine(w, "foo", "bar")
|
|
|
|
g.Expect(err).To(HaveOccurred())
|
|
g.Expect(errors.Is(err, w.err)).To(BeTrue())
|
|
g.Expect(n).To(Equal(w.written))
|
|
})
|
|
}
|
|
|
|
type fakeWriter struct {
|
|
written int
|
|
err error
|
|
}
|
|
|
|
func (f *fakeWriter) Write(p []byte) (n int, err error) {
|
|
return f.written, f.err
|
|
}
|