176 lines
4.4 KiB
Go
176 lines
4.4 KiB
Go
|
|
package container
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"crypto/rand"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/ipfs/go-cid"
|
||
|
|
"github.com/libp2p/go-libp2p/core/crypto"
|
||
|
|
mh "github.com/multiformats/go-multihash"
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
|
||
|
|
"github.com/ucan-wg/go-ucan/did"
|
||
|
|
"github.com/ucan-wg/go-ucan/pkg/command"
|
||
|
|
"github.com/ucan-wg/go-ucan/pkg/policy"
|
||
|
|
"github.com/ucan-wg/go-ucan/pkg/policy/literal"
|
||
|
|
"github.com/ucan-wg/go-ucan/pkg/policy/selector"
|
||
|
|
"github.com/ucan-wg/go-ucan/token/delegation"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestContainerRoundTrip(t *testing.T) {
|
||
|
|
for _, tc := range []struct {
|
||
|
|
name string
|
||
|
|
writer func(ctn Container, w io.Writer) error
|
||
|
|
reader func(io.Reader) (Container, error)
|
||
|
|
}{
|
||
|
|
{"car", Container.ToCar, FromCar},
|
||
|
|
{"carBase64", Container.ToCarBase64, FromCarBase64},
|
||
|
|
{"carGzip", Container.ToCarGzip, FromCarGzip},
|
||
|
|
{"carGzipBase64", Container.ToCarGzipBase64, FromCarGzipBase64},
|
||
|
|
{"cbor", Container.ToCbor, FromCbor},
|
||
|
|
{"cborBase64", Container.ToCborBase64, FromCborBase64},
|
||
|
|
{"cborGzip", Container.ToCborGzip, FromCborGzip},
|
||
|
|
{"cborGzipBase64", Container.ToCborGzipBase64, FromCborGzipBase64},
|
||
|
|
{"cborFlate", Container.ToCborFlate, FromCborFlate},
|
||
|
|
{"cborFlateBase64", Container.ToCborFlateBase64, FromCborFlateBase64},
|
||
|
|
{"cbor2", Container.ToCbor2, FromCbor2},
|
||
|
|
} {
|
||
|
|
t.Run(tc.name, func(t *testing.T) {
|
||
|
|
ctn := New()
|
||
|
|
|
||
|
|
builder := cid.V1Builder{Codec: cid.DagCBOR, MhType: mh.SHA2_256}
|
||
|
|
|
||
|
|
var dataSize int
|
||
|
|
|
||
|
|
for i := 0; i < 10; i++ {
|
||
|
|
data := randTokenBytes()
|
||
|
|
c, err := builder.Sum(data)
|
||
|
|
require.NoError(t, err)
|
||
|
|
ctn.AddBytes(c, data)
|
||
|
|
dataSize += len(data)
|
||
|
|
}
|
||
|
|
|
||
|
|
buf := bytes.NewBuffer(nil)
|
||
|
|
|
||
|
|
err := tc.writer(ctn, buf)
|
||
|
|
require.NoError(t, err)
|
||
|
|
|
||
|
|
t.Logf("data size %d", dataSize)
|
||
|
|
t.Logf("container overhead: %d%%, %d bytes", int(float32(buf.Len()-dataSize)/float32(dataSize)*100.0), buf.Len()-dataSize)
|
||
|
|
|
||
|
|
ctn2, err := tc.reader(bytes.NewReader(buf.Bytes()))
|
||
|
|
require.NoError(t, err)
|
||
|
|
|
||
|
|
require.Equal(t, ctn, ctn2)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func BenchmarkContainerSerialisation(b *testing.B) {
|
||
|
|
for _, tc := range []struct {
|
||
|
|
name string
|
||
|
|
writer func(ctn Container, w io.Writer) error
|
||
|
|
reader func(io.Reader) (Container, error)
|
||
|
|
}{
|
||
|
|
{"car", Container.ToCar, FromCar},
|
||
|
|
{"carBase64", Container.ToCarBase64, FromCarBase64},
|
||
|
|
{"carGzip", Container.ToCarGzip, FromCarGzip},
|
||
|
|
{"carGzipBase64", Container.ToCarGzipBase64, FromCarGzipBase64},
|
||
|
|
{"cbor", Container.ToCbor, FromCbor},
|
||
|
|
{"cborBase64", Container.ToCborBase64, FromCborBase64},
|
||
|
|
{"cborGzip", Container.ToCborGzip, FromCborGzip},
|
||
|
|
{"cborGzipBase64", Container.ToCborGzipBase64, FromCborGzipBase64},
|
||
|
|
{"cborFlate", Container.ToCborFlate, FromCborFlate},
|
||
|
|
{"cborFlateBase64", Container.ToCborFlateBase64, FromCborFlateBase64},
|
||
|
|
{"cbor2", Container.ToCbor2, FromCbor2},
|
||
|
|
} {
|
||
|
|
ctn := New()
|
||
|
|
|
||
|
|
builder := cid.V1Builder{Codec: cid.DagCBOR, MhType: mh.SHA2_256}
|
||
|
|
|
||
|
|
var dataSize int
|
||
|
|
|
||
|
|
for i := 0; i < 10; i++ {
|
||
|
|
data := randTokenBytes()
|
||
|
|
c, err := builder.Sum(data)
|
||
|
|
require.NoError(b, err)
|
||
|
|
ctn.AddBytes(c, data)
|
||
|
|
dataSize += len(data)
|
||
|
|
}
|
||
|
|
|
||
|
|
buf := bytes.NewBuffer(nil)
|
||
|
|
_ = tc.writer(ctn, buf)
|
||
|
|
|
||
|
|
b.Run(tc.name+"_write", func(b *testing.B) {
|
||
|
|
b.ReportAllocs()
|
||
|
|
for i := 0; i < b.N; i++ {
|
||
|
|
buf := bytes.NewBuffer(nil)
|
||
|
|
_ = tc.writer(ctn, buf)
|
||
|
|
}
|
||
|
|
})
|
||
|
|
|
||
|
|
b.Run(tc.name+"_read", func(b *testing.B) {
|
||
|
|
b.ReportAllocs()
|
||
|
|
for i := 0; i < b.N; i++ {
|
||
|
|
_, _ = tc.reader(bytes.NewReader(buf.Bytes()))
|
||
|
|
}
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func randBytes(n int) []byte {
|
||
|
|
b := make([]byte, n)
|
||
|
|
_, _ = rand.Read(b)
|
||
|
|
return b
|
||
|
|
}
|
||
|
|
|
||
|
|
func randDID() (crypto.PrivKey, did.DID) {
|
||
|
|
privKey, _, err := crypto.GenerateEd25519Key(rand.Reader)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
d, err := did.FromPrivKey(privKey)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
return privKey, d
|
||
|
|
}
|
||
|
|
|
||
|
|
func randomString(length int) string {
|
||
|
|
b := make([]byte, length/2+1)
|
||
|
|
rand.Read(b)
|
||
|
|
return fmt.Sprintf("%x", b)[0:length]
|
||
|
|
}
|
||
|
|
|
||
|
|
func randTokenBytes() []byte {
|
||
|
|
priv, iss := randDID()
|
||
|
|
_, aud := randDID()
|
||
|
|
cmd := command.New("foo", "bar")
|
||
|
|
pol := policy.Policy{policy.All(
|
||
|
|
selector.MustParse(".[]"),
|
||
|
|
policy.GreaterThan(selector.MustParse(".value"), literal.Int(2)),
|
||
|
|
)}
|
||
|
|
|
||
|
|
opts := []delegation.Option{
|
||
|
|
delegation.WithExpiration(time.Now().Add(time.Hour)),
|
||
|
|
delegation.WithSubject(iss),
|
||
|
|
}
|
||
|
|
for i := 0; i < 3; i++ {
|
||
|
|
opts = append(opts, delegation.WithMeta(randomString(8), randomString(10)))
|
||
|
|
}
|
||
|
|
|
||
|
|
t, err := delegation.New(priv, aud, cmd, pol, opts...)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
b, _, err := t.ToSealed(priv)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
return b
|
||
|
|
}
|