//go:build linux package hostfiles import ( "context" "errors" "os" "path/filepath" "strings" "testing" "time" "github.com/carlosframework/platform/internal/release" ) // Fix 4 (Astra confirming P2): a deep path within the byte cap (257 // one-byte components, 513 bytes) travels the whole way: published by a // walk, accepted by every reader, restored and found present. func TestADeepPathWithinTheCapPublishesAndRestores(t *testing.T) { ctx := context.Background() rel := strings.Repeat("d/", 256) + "f" src := t.TempDir() root, err := os.OpenRoot(src) if err != nil { t.Fatal(err) } if err := root.MkdirAll(strings.TrimSuffix(strings.Repeat("d/", 256), "/"), 0o700); err != nil { t.Fatal(err) } if err := root.WriteFile(rel, []byte("deep"), 0o600); err != nil { t.Fatal(err) } root.Close() s := release.NewDirStore(t.TempDir()) p := open(t, s) if _, err := SyncDir(ctx, p, src, nil); err != nil { t.Fatal(err) } commit(t, p) m, _, err := Load(ctx, s, pfx) if err != nil { t.Fatal(err) } if err := ValidateManifest(m, []string{pfx}); err != nil { t.Fatalf("ValidateManifest refused what the writer published: %v", err) } dst := t.TempDir() if _, st, err := Restore(ctx, s, pfx, dst, nil); err != nil || st.Written != 1 { t.Fatalf("Restore: %+v %v", st, err) } r2, err := os.OpenRoot(dst) if err != nil { t.Fatal(err) } defer r2.Close() if b, err := r2.ReadFile(rel); err != nil || string(b) != "deep" { t.Fatalf("restored %q %v", b, err) } if ok, err := Present(dst, filepath.Join(t.TempDir(), "shop.example.env"), m, true); err != nil || !ok { t.Fatalf("Present: %v %v", ok, err) } } // Every writer refuses a path past the byte cap, exactly where the readers // do, and accepts one at it; Commit never writes a manifest that holds one. func TestTheWritersRefuseAPathPastTheCapAsTheReadersDo(t *testing.T) { ctx := context.Background() at, past := pathOfBytes(MaxPathBytes), pathOfBytes(MaxPathBytes+1) p := open(t, release.NewDirStore(t.TempDir())) if err := p.Stage(ctx, at, []byte("x"), 0o600, false); err != nil { t.Fatalf("Stage at the cap: %v", err) } if err := p.Stage(ctx, past, []byte("x"), 0o600, false); !errors.Is(err, ErrTooDeep) { t.Fatalf("Stage past the cap: %v", err) } if err := p.StageSkipped(past, "too-large"); !errors.Is(err, ErrTooDeep) { t.Fatalf("StageSkipped past the cap: %v", err) } if err := p.StageDelete(past); !errors.Is(err, ErrTooDeep) { t.Fatalf("StageDelete past the cap: %v", err) } // A manifest the publisher continued that already holds such a path // (written before the cap) is refused at Commit, never written again. s := release.NewDirStore(t.TempDir()) q := open(t, s) q.mu.Lock() q.next++ q.man.Entries[past], q.dirty = Entry{Seq: q.next, Skipped: "too-large"}, true q.mu.Unlock() if _, err := q.Commit(ctx); !errors.Is(err, ErrTooDeep) { t.Fatalf("Commit of a manifest holding a path past the cap: %v", err) } if _, found, err := Load(ctx, s, pfx); found || err != nil { t.Fatalf("a refused Commit wrote a manifest: %v %v", found, err) } // And the readers draw the line at the same byte. sha := strings.Repeat("a", 64) e := Entry{Object: pfx + objectKey(1, sha), SHA256: sha, Seq: 1, Size: 1} for path, ok := range map[string]bool{at: true, past: false} { err := ValidateManifest(Manifest{V: ManifestVersion, Seq: 1, Entries: map[string]Entry{path: e}, Platform: map[string]Entry{}}, []string{pfx}) if ok != (err == nil) || !ok && !errors.Is(err, ErrTooDeep) { t.Fatalf("ValidateManifest of %d bytes: %v", len(path), err) } } } // The watcher skips a path past the cap for good: it is never staged, so // no manifest a reader refuses is committed; it is not retried; and it // costs one log line however often it is touched. Other paths publish. func TestRunSkipsAPathPastTheCapAndLogsItOnce(t *testing.T) { logs := captureLog(t) s, dir, w := release.NewDirStore(t.TempDir()), t.TempDir(), newFake() p := open(t, s) stop := startRun(t, p, dir, w, eventsOnly) past := pathOfBytes(MaxPathBytes + 1) root, err := os.OpenRoot(dir) if err != nil { t.Fatal(err) } if err := root.MkdirAll(filepath.Dir(past), 0o700); err != nil { t.Fatal(err) } if err := root.WriteFile(past, []byte("x"), 0o600); err != nil { t.Fatal(err) } root.Close() w.ch <- event{rel: past} write(t, dir, "ok", "ok") w.ch <- event{rel: "ok"} eventually(t, "ok published", func() bool { return manifestHas(s, "ok", sum([]byte("ok"))) }) w.ch <- event{rel: past} w.ch <- event{rel: "ok"} eventually(t, "the second touch handled", func() bool { return logs.count("past the 4095-byte cap") >= 1 }) // Long enough for a retry at every deadline to have logged again. time.Sleep(10 * eventsOnly.Deadline) stopErr := stop() if !errors.Is(stopErr, context.Canceled) { t.Fatalf("run ended with %v; a path past the cap must be skipped, not fatal", stopErr) } if got := logs.count("past the 4095-byte cap"); got != 1 { t.Fatalf("logged %d times, want once", got) } m, _, err := Load(context.Background(), s, pfx) if err != nil { t.Fatal(err) } if _, ok := m.Entries[past]; ok { t.Fatal("the watcher published a path past the cap") } if err := ValidateManifest(m, []string{pfx}); err != nil { t.Fatalf("the watcher committed a manifest a reader refuses: %v", err) } }