about summary refs log tree commit diff
path: root/tvix
diff options
context:
space:
mode:
Diffstat (limited to 'tvix')
-rw-r--r--tvix/default.nix2
-rw-r--r--tvix/nar-bridge/pkg/exporter/export.go3
-rw-r--r--tvix/store/protos/go.mod4
-rw-r--r--tvix/store/protos/go.sum13
-rw-r--r--tvix/store/protos/pathinfo_test.go113
5 files changed, 131 insertions, 4 deletions
diff --git a/tvix/default.nix b/tvix/default.nix
index c35ba733a517..802ec9497fa5 100644
--- a/tvix/default.nix
+++ b/tvix/default.nix
@@ -108,7 +108,7 @@ in
   store-protos-go = pkgs.buildGoModule {
     name = "store-golang";
     src = depot.third_party.gitignoreSource ./store/protos;
-    vendorHash = "sha256-o7moXRxhKxCpsds96sSsHHafKJf2AWhFMu/YdSu+FM4=";
+    vendorHash = "sha256-L+mHTUYRZu8PSbD7LJ9QRuW1+ImIYbH9/SKgAoL9W8w=";
   };
 
   # Build the Rust documentation for publishing on docs.tvix.dev.
diff --git a/tvix/nar-bridge/pkg/exporter/export.go b/tvix/nar-bridge/pkg/exporter/export.go
index 40ccc4b6380c..1f898ccad6dd 100644
--- a/tvix/nar-bridge/pkg/exporter/export.go
+++ b/tvix/nar-bridge/pkg/exporter/export.go
@@ -194,9 +194,6 @@ func Export(
 	}
 }
 
-// TODO: add validation functions to Directory in both rust and golang, to
-// validate the keys in directories, files and symlinks are sorted.
-
 // drainNextNode will drain a directory message with one of its child nodes,
 // whichever comes first alphabetically.
 func drainNextNode(d *castorev1pb.Directory) interface{} {
diff --git a/tvix/store/protos/go.mod b/tvix/store/protos/go.mod
index 3038b2a6c58c..5c6306f5175a 100644
--- a/tvix/store/protos/go.mod
+++ b/tvix/store/protos/go.mod
@@ -5,16 +5,20 @@ go 1.19
 require (
 	code.tvl.fyi/tvix/castore/protos v0.0.0-20230922125121-72355662d742
 	github.com/nix-community/go-nix v0.0.0-20231005143722-b0f8b73c06df
+	github.com/stretchr/testify v1.8.1
 	google.golang.org/grpc v1.51.0
 	google.golang.org/protobuf v1.28.1
 )
 
 require (
+	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/klauspost/cpuid/v2 v2.0.9 // indirect
+	github.com/pmezard/go-difflib v1.0.0 // indirect
 	golang.org/x/net v0.7.0 // indirect
 	golang.org/x/sys v0.5.0 // indirect
 	golang.org/x/text v0.7.0 // indirect
 	google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
 	lukechampine.com/blake3 v1.1.7 // indirect
 )
diff --git a/tvix/store/protos/go.sum b/tvix/store/protos/go.sum
index e1840f8d154f..b5b92a74d6fb 100644
--- a/tvix/store/protos/go.sum
+++ b/tvix/store/protos/go.sum
@@ -4,7 +4,9 @@ code.tvl.fyi/tvix/castore/protos v0.0.0-20230922125121-72355662d742/go.mod h1:Ej
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -31,8 +33,15 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
 github.com/nix-community/go-nix v0.0.0-20231005143722-b0f8b73c06df h1:n4I26uXUST5vmdsDWPo9ikK57il4htQyhnsLWoHYFmY=
 github.com/nix-community/go-nix v0.0.0-20231005143722-b0f8b73c06df/go.mod h1:hHM9UK2zOCjvmiLgeaW4LVbOW/vBaRWFJGzfi31/slQ=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -83,7 +92,11 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
diff --git a/tvix/store/protos/pathinfo_test.go b/tvix/store/protos/pathinfo_test.go
new file mode 100644
index 000000000000..adac30a97f88
--- /dev/null
+++ b/tvix/store/protos/pathinfo_test.go
@@ -0,0 +1,113 @@
+package storev1_test
+
+import (
+	"path"
+	"testing"
+
+	"github.com/nix-community/go-nix/pkg/storepath"
+	"github.com/stretchr/testify/assert"
+
+	castorev1pb "code.tvl.fyi/tvix/castore/protos"
+	storev1pb "code.tvl.fyi/tvix/store/protos"
+)
+
+const (
+	EXAMPLE_STORE_PATH = "00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p2017022118243"
+)
+
+var (
+	exampleStorePathDigest = []byte{
+		0x8a, 0x12, 0x32, 0x15, 0x22, 0xfd, 0x91, 0xef, 0xbd, 0x60, 0xeb, 0xb2, 0x48, 0x1a, 0xf8, 0x85,
+		0x80, 0xf6, 0x16, 0x00}
+)
+
+func genPathInfoSymlink() *storev1pb.PathInfo {
+	return &storev1pb.PathInfo{
+		Node: &castorev1pb.Node{
+			Node: &castorev1pb.Node_Symlink{
+				Symlink: &castorev1pb.SymlinkNode{
+					Name:   []byte("00000000000000000000000000000000-dummy"),
+					Target: []byte("/nix/store/somewhereelse"),
+				},
+			},
+		},
+		References: [][]byte{exampleStorePathDigest},
+		Narinfo: &storev1pb.NARInfo{
+			NarSize:        0,
+			NarSha256:      []byte{},
+			Signatures:     []*storev1pb.NARInfo_Signature{},
+			ReferenceNames: []string{EXAMPLE_STORE_PATH},
+		},
+	}
+}
+
+func genPathInfoSymlinkThin() *storev1pb.PathInfo {
+	pi := genPathInfoSymlink()
+	pi.Narinfo = nil
+
+	return pi
+}
+
+func TestValidate(t *testing.T) {
+	t.Run("happy symlink", func(t *testing.T) {
+		storePath, err := genPathInfoSymlink().Validate()
+		assert.NoError(t, err, "PathInfo must validate")
+		assert.Equal(t, "00000000000000000000000000000000-dummy", storePath.String())
+	})
+
+	t.Run("happy symlink thin", func(t *testing.T) {
+		storePath, err := genPathInfoSymlinkThin().Validate()
+		assert.NoError(t, err, "PathInfo must validate")
+		assert.Equal(t, "00000000000000000000000000000000-dummy", storePath.String())
+	})
+
+	t.Run("invalid reference digest", func(t *testing.T) {
+		pi := genPathInfoSymlink()
+
+		// create broken references, where the reference digest is wrong
+		pi.References = append(pi.References, []byte{0x00})
+
+		_, err := pi.Validate()
+		assert.Error(t, err, "must not validate")
+	})
+
+	t.Run("invalid reference name", func(t *testing.T) {
+		pi := genPathInfoSymlink()
+
+		// make the reference name an invalid store path
+		pi.Narinfo.ReferenceNames[0] = "00000000000000000000000000000000-"
+
+		_, err := pi.Validate()
+		assert.Error(t, err, "must not validate")
+	})
+
+	t.Run("reference name digest mismatch", func(t *testing.T) {
+		pi := genPathInfoSymlink()
+
+		// cause the digest for the reference to mismatch
+		pi.Narinfo.ReferenceNames[0] = "11111111111111111111111111111111-dummy"
+
+		_, err := pi.Validate()
+		assert.Error(t, err, "must not validate")
+	})
+
+	t.Run("nil root node", func(t *testing.T) {
+		pi := genPathInfoSymlink()
+
+		pi.Node = nil
+
+		_, err := pi.Validate()
+		assert.Error(t, err, "must not validate")
+	})
+
+	t.Run("invalid root node name", func(t *testing.T) {
+		pi := genPathInfoSymlink()
+
+		// make the reference name an invalid store path - it may not be absolute
+		symlinkNode := pi.Node.GetSymlink()
+		symlinkNode.Name = []byte(path.Join(storepath.StoreDir, "00000000000000000000000000000000-dummy"))
+
+		_, err := pi.Validate()
+		assert.Error(t, err, "must not validate")
+	})
+}