aboutsummaryrefslogtreecommitdiffhomepage
path: root/pkg/net_test.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-08-29 18:58:06 +0900
committerOphestra <cat@gensokyo.uk>2026-08-29 18:58:06 +0900
commitc2d900ec74e03e9c782cfe7b7ce06ff62cda6601 (patch)
treefb13320bfdc62d810aa59769e8809dc2f707919e /pkg/net_test.go
parentbd4f29909e0750a4660eaf48e3169777a265b0ab (diff)
pkg: move from internalHEADstagingmasterdevelop
Closes #43. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'pkg/net_test.go')
-rw-r--r--pkg/net_test.go168
1 files changed, 168 insertions, 0 deletions
diff --git a/pkg/net_test.go b/pkg/net_test.go
new file mode 100644
index 00000000..b16a2019
--- /dev/null
+++ b/pkg/net_test.go
@@ -0,0 +1,168 @@
+package pkg_test
+
+import (
+ "crypto/sha512"
+ "io"
+ "io/fs"
+ "net/http"
+ "reflect"
+ "testing"
+ "testing/fstest"
+ "unique"
+
+ "hakurei.app/check"
+ "hakurei.app/pkg"
+)
+
+func TestHTTPGet(t *testing.T) {
+ t.Parallel()
+
+ const testdata = "\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69"
+
+ testdataChecksum := func() unique.Handle[pkg.Checksum] {
+ h := sha512.New384()
+ h.Write([]byte(testdata))
+ return unique.Make(pkg.Checksum(h.Sum(nil)))
+ }()
+
+ var transport http.Transport
+ client := http.Client{Transport: &transport}
+ transport.RegisterProtocol("file", http.NewFileTransportFS(fstest.MapFS{
+ "testdata": {Data: []byte(testdata), Mode: 0400},
+ }))
+
+ checkWithCache(t, []cacheTestCase{
+ {"direct", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
+ r := newRContext(t, c)
+ f := pkg.NewHTTPGet(
+ &client,
+ "file:///testdata",
+ testdataChecksum.Value(),
+ )
+ var got []byte
+ if rc, err := f.Cure(r); err != nil {
+ t.Fatalf("Cure: error = %v", err)
+ } else if got, err = io.ReadAll(rc); err != nil {
+ t.Fatalf("ReadAll: error = %v", err)
+ } else if string(got) != testdata {
+ t.Fatalf("Cure: %x, want %x", got, testdata)
+ } else if err = rc.Close(); err != nil {
+ t.Fatalf("Close: error = %v", err)
+ }
+
+ // check direct validation
+ f = pkg.NewHTTPGet(
+ &client,
+ "file:///testdata",
+ pkg.Checksum{},
+ )
+ wantErrMismatch := &pkg.ChecksumMismatchError{
+ Got: testdataChecksum.Value(),
+ }
+ if rc, err := f.Cure(r); err != nil {
+ t.Fatalf("Cure: error = %v", err)
+ } else if got, err = io.ReadAll(rc); err != nil {
+ t.Fatalf("ReadAll: error = %v", err)
+ } else if string(got) != testdata {
+ t.Fatalf("Cure: %x, want %x", got, testdata)
+ } else if err = rc.Close(); !reflect.DeepEqual(err, wantErrMismatch) {
+ t.Fatalf("Close: error = %#v, want %#v", err, wantErrMismatch)
+ }
+
+ // check fallback validation
+ if rc, err := f.Cure(r); err != nil {
+ t.Fatalf("Cure: error = %v", err)
+ } else if err = rc.Close(); !reflect.DeepEqual(err, wantErrMismatch) {
+ t.Fatalf("Close: error = %#v, want %#v", err, wantErrMismatch)
+ }
+
+ // check direct response error
+ f = pkg.NewHTTPGet(
+ &client,
+ "file:///nonexistent",
+ pkg.Checksum{},
+ )
+ wantErrNotFound := pkg.ResponseStatusError(http.StatusNotFound)
+ if _, err := f.Cure(r); !reflect.DeepEqual(err, wantErrNotFound) {
+ t.Fatalf("Cure: error = %#v, want %#v", err, wantErrNotFound)
+ }
+ }, expectsFS{
+ ".": {Mode: fs.ModeDir | 0700},
+ "checksum": {Mode: fs.ModeDir | 0700},
+ "identifier": {Mode: fs.ModeDir | 0700},
+ "substitute": {Mode: fs.ModeDir | 0700},
+ "work": {Mode: fs.ModeDir | 0700},
+ }},
+
+ {"cure", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
+ r := newRContext(t, c)
+
+ f := pkg.NewHTTPGet(
+ &client,
+ "file:///testdata",
+ testdataChecksum.Value(),
+ )
+ wantPathname := base.Append(
+ "identifier",
+ "COBRUwkxpIvZWJggpRxn7HVXiw6epXZOex8jGRJKpowpwukV7GRBY_LBvOJNQHue",
+ )
+ if pathname, checksum, err := c.Cure(f); err != nil {
+ t.Fatalf("Cure: error = %v", err)
+ } else if !pathname.Is(wantPathname) {
+ t.Fatalf("Cure: %q, want %q", pathname, wantPathname)
+ } else if checksum != testdataChecksum {
+ t.Fatalf("Cure: %x, want %x", checksum.Value(), testdataChecksum.Value())
+ }
+
+ var got []byte
+ if rc, err := f.Cure(r); err != nil {
+ t.Fatalf("Cure: error = %v", err)
+ } else if got, err = io.ReadAll(rc); err != nil {
+ t.Fatalf("ReadAll: error = %v", err)
+ } else if string(got) != testdata {
+ t.Fatalf("Cure: %x, want %x", got, testdata)
+ } else if err = rc.Close(); err != nil {
+ t.Fatalf("Close: error = %v", err)
+ }
+
+ // check load from cache
+ f = pkg.NewHTTPGet(
+ &client,
+ "file:///testdata",
+ testdataChecksum.Value(),
+ )
+ if rc, err := f.Cure(r); err != nil {
+ t.Fatalf("Cure: error = %v", err)
+ } else if got, err = io.ReadAll(rc); err != nil {
+ t.Fatalf("ReadAll: error = %v", err)
+ } else if string(got) != testdata {
+ t.Fatalf("Cure: %x, want %x", got, testdata)
+ } else if err = rc.Close(); err != nil {
+ t.Fatalf("Close: error = %v", err)
+ }
+
+ // check error passthrough
+ f = pkg.NewHTTPGet(
+ &client,
+ "file:///nonexistent",
+ pkg.Checksum{},
+ )
+ wantErrNotFound := pkg.ResponseStatusError(http.StatusNotFound)
+ if _, _, err := c.Cure(f); !reflect.DeepEqual(err, wantErrNotFound) {
+ t.Fatalf("Pathname: error = %#v, want %#v", err, wantErrNotFound)
+ }
+ }, expectsFS{
+ ".": {Mode: fs.ModeDir | 0700},
+
+ "checksum": {Mode: fs.ModeDir | 0700},
+ "checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU": {Mode: 0400, Data: []byte("\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69")},
+
+ "identifier": {Mode: fs.ModeDir | 0700},
+ "identifier/COBRUwkxpIvZWJggpRxn7HVXiw6epXZOex8jGRJKpowpwukV7GRBY_LBvOJNQHue": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")},
+
+ "substitute": {Mode: fs.ModeDir | 0700},
+
+ "work": {Mode: fs.ModeDir | 0700},
+ }},
+ })
+}