Artifact 31241e91bcc75d422a2317761a2505a80665b8fa7571c651ec8a6ce737b0c54f:
- File
conformance/repostate_verify_test.go
— part of check-in
[41e39a41fc]
at
2026-10-19 21:17:29
on branch fix/verify-leaf-rule
— fix(verify): report stray leaf rows and read every parent tag
Review follow-ups for the leaf audit:
- leaf.Audit reports a row for a rid that no recheck reaches, that is a rid with no branch row in no plink row. A file artifact or a rid with no artifact used to pass. - Verify collects the parents named by every parent tag, as well as by P-cards, whose link plink no longer holds. A parent that an earlier, since replaced, reparent linked is then excused. repostate.7.3.reparent-twice-no-recheck covers that order. - The stale finding excuses a child carrying a parent tag row of any type, since a cancelled reparent leaves its link in place until a rebuild. - Every leaf-table case also runs Verify on the tables fossil(1) derives, per artifact and rebuilt, except where the case records fossil departing from the draft.
Tracked in #433. (user: [email protected], size: 3649) [annotate] [blame] [check-ins using]
package conformance import ( "fmt" "slices" "github.com/danmestas/go-libfossil/internal/repo" "github.com/danmestas/go-libfossil/internal/verify" ) // verify.Verify against the leaf table. Section 7.3 lets the table depend on // the order artifacts arrived in, so Verify must accept every table a load // derives -- goConforms runs it on every case that compares leaf, including // repostate.7.3.recheck-untagged-child -- and must still report what the // Section 7.2 test decides whatever the order. // verifyLeafIssues runs verify.Verify on the repository at path and returns // the check-ins its leaf issues name, by label. func verifyLeafIssues(path string, labels map[string]string) ([]string, error) { r, err := repo.Open(path) if err != nil { return nil, err } defer r.Close() report, err := verify.Verify(r) if err != nil { return nil, fmt.Errorf("verify.Verify: %w", err) } var named []string for _, iss := range report.Issues { if iss.Kind != verify.IssueLeafIncorrect { continue } var uuid string if err := r.DB().QueryRow("SELECT uuid FROM blob WHERE rid=?", iss.RID).Scan(&uuid); err != nil { return nil, fmt.Errorf("leaf issue rid=%d: %w", iss.RID, err) } label, ok := labels[uuid] if !ok { label = uuid } named = append(named, label) } slices.Sort(named) return named, nil } // verifyFossilLeaves runs verifyLeafIssues on a repository fossil(1) derived, // for a case comparing leaf: Verify must accept the tables fossil itself // writes. A case whose fossil field is set records fossil departing from the // draft, so Verify, which follows the draft, is not held to fossil's table // there. It returns one problem naming how fossil derived it, or none. func verifyFossilLeaves(c rsCase, path, how string, labels map[string]string) ([]string, error) { if !slices.Contains(c.tables, "leaf") || c.fossil != "" { return nil, nil } issues, err := verifyLeafIssues(path, labels) if err != nil { return nil, fmt.Errorf("%s: %w", how, err) } if len(issues) == 0 { return nil, nil } return []string{fmt.Sprintf("%s: leaf issues on %v", how, issues)}, nil } func verifyLeafCases() []rsAPICase { return []rsAPICase{{ // b1, merged into trunk by m, and m are the leaves of merged(); b1's // only child is on another branch. Verify accepts that table, then // reports b1 once its row is dropped and c1 once one is planted: c1's // child c2 is on trunk with it, by a branch row propagated along the // link, so the recheck that row scheduled removed c1. Case: Case{ID: "repostate.7.2.verify-leaf-table", Req: "RS-7.2-1"}, arts: merged(), run: verifyLeafTable, }} } func verifyLeafTable(e *rsEnv) error { steps := []struct { sql string want []string }{ {"", nil}, {"DELETE FROM leaf WHERE rid=(SELECT rid FROM blob WHERE uuid='%[1]s')", []string{"b1"}}, {"INSERT INTO leaf(rid) SELECT rid FROM blob WHERE uuid='%[2]s'", []string{"b1", "c1"}}, } for _, s := range steps { if s.sql != "" { if err := e.goExec(fmt.Sprintf(s.sql, e.script.hashes["b1"], e.script.hashes["c1"])); err != nil { return err } } got, err := verifyLeafIssues(e.goPath, e.script.labels) if err != nil { return err } if !slices.Equal(got, s.want) { return expectf("after %q: Verify leaf issues %v, want %v", s.sql, got, s.want) } } return nil } // goExec runs one statement against the go-libfossil repository. func (e *rsEnv) goExec(query string) error { r, err := repo.Open(e.goPath) if err != nil { return err } defer r.Close() if _, err := r.DB().Exec(query); err != nil { return fmt.Errorf("%s: %w", query, err) } return nil }