Artifact b9da1a1fabc6dc3bc914ce89c4220a0f888b91a11c9d55f1e4e8aa8ef6ebee90:
- File
internal/sync/shun_send_oracle_test.go
— part of check-in
[a402aa5cc6]
at
2026-10-21 01:03:53
on branch feat/submanifest-reader
— fix(sync): withhold shunned payloads and clone delta bases
Match Fossil 2.28 send_file and send_compressed_file payload gates. A source-first clone must expand a dependent when its stored basis is shunned rather than forwarding that withheld basis. Preserve private notices, authorization and SHA3 refusal ordering.
Exercise real encoded requests through the ordinary handler and Fossil HTTP oracle. Canonical compressed clone can name a shunned public basis without sending it; this server expands instead to preserve its source-first guarantee. (user: [email protected], size: 2802) [annotate] [blame] [check-ins using] [more...]
package sync import ( "bufio" "bytes" "context" "fmt" "io" "net/http" "os" "os/exec" "path/filepath" "testing" "time" "github.com/danmestas/go-libfossil/internal/xfer" "github.com/danmestas/go-libfossil/testutil" ) // Fossil 2.28 withholds shunned payloads in both clone and gimme responses. // Its compressed clone may still name a shunned public delta basis; unlike // this server's source-first clone, it does not promise to send bases first. func TestShunSendFossilOracle(t *testing.T) { bin := testutil.FossilBinary() if bin == "" { t.Skip("Fossil oracle unavailable") } for _, private := range []bool{false, true} { for _, requested := range []bool{false, true} { t.Run(fmt.Sprintf("private=%v/gimme=%v", private, requested), func(t *testing.T) { r, baseUUID, targetUUID := shunSendFixture(t, private) if _, err := r.DB().Exec("INSERT INTO shun(uuid,mtime) VALUES(?,0)", baseUUID); err != nil { t.Fatal(err) } path := r.Path() if err := r.Close(); err != nil { t.Fatal(err) } resp := shunOracleRound(t, bin, path, shunSendCards(private, requested, baseUUID, targetUUID)) if shunHasFile(resp, baseUUID) { t.Fatal("Fossil emitted shunned payload") } if !shunHasFile(resp, targetUUID) { t.Fatal("Fossil withheld public dependent") } for _, card := range resp.Cards { if c, ok := card.(*xfer.CFileCard); ok && c.UUID == targetUUID { t.Logf("canonical compressed dependent names shunned basis: %v", c.DeltaSrc == baseUUID) } } }) } } } func shunOracleRound(t *testing.T, bin, path string, cards []xfer.Card) *xfer.Message { t.Helper() wire, err := (&xfer.Message{Cards: cards}).Encode() if err != nil { t.Fatal(err) } head := fmt.Sprintf("POST /xfer HTTP/1.0\r\nHost: localhost\r\n"+ "Content-Type: %s\r\nContent-Length: %d\r\n\r\n", xfer.ContentTypeCompressed, len(wire)) dir := t.TempDir() request := filepath.Join(dir, "request") if err := os.WriteFile(request, append([]byte(head), wire...), 0600); err != nil { t.Fatal(err) } ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() cmd := exec.CommandContext(ctx, bin, "http", path, "--in", request, "--ipaddr", "127.0.0.1") cmd.Dir = dir cmd.Env = append(os.Environ(), "HOME="+dir, "FOSSIL_HOME="+dir, "XDG_CONFIG_HOME="+dir, "USER=u") out, err := cmd.Output() if err != nil { t.Fatal(err) } httpResp, err := http.ReadResponse(bufio.NewReader(bytes.NewReader(out)), nil) if err != nil { t.Fatal(err) } defer httpResp.Body.Close() body, err := io.ReadAll(httpResp.Body) if err != nil { t.Fatal(err) } resp, err := xfer.Decode(body, httpResp.Header.Get("Content-Type")) if err != nil { t.Fatalf("oracle decode: %v body=%q", err, body) } return resp }