Artifact 16ca0eb0f2f96ba15d3f8f168868a88fbd0f8d58dc00f699214bb58959b01923:
- File
internal/sync/links_test.go
— part of check-in
[a565d1c467]
at
2026-10-13 14:49:38
on branch feat/425-share-links
— feat(sync): add share-links mode for pragma req-links and link
sync-protocol-01 Section 9.5 makes share-links mode OPTIONAL. With SyncOpts.ShareLinks a pulling session sends pragma req-links in its first request, as fossil's --share-links does, unless SyncOpts.ProjectCode names another project. It keeps each pragma link URL ARG MTIME as config link:URL = ARG, defossilized and otherwise verbatim, replacing an existing link only with a strictly newer MTIME. A wrong token count, a URL that is not HTTP(S) or an MTIME that is not a positive decimal drops the link.
Where fossil 2.28 differs the draft is followed: fossil fails fatally on a link URL its parser rejects and reads MTIME with strtoll base 0.
New sync.9.5 client cases run against fossil sync --share-links as well. SP-9.5-4 loses its scope note and is covered; SP-9.5-5 and SP-9.5-6 are new rows for which links a client keeps and when it sends req-links.
Tracked in #425. (user: [email protected], size: 2177) [annotate] [blame] [check-ins using] [more...]
package sync import "testing" func TestLinkURLIsHTTP(t *testing.T) { for url, want := range map[string]bool{ "http://example.com": true, "https://example.com/r": true, "https://example.com:8080/r": true, "https://example.com:": true, // fossil reads an empty port as 0 "https://u:[email protected]:443/r": true, "https://[::1]:8080/r": true, "https://[::1]/r": true, "https://": true, // an empty host still parses "https://example.com:8x/r": false, "https://[email protected]:x": false, "HTTP://example.com/r": false, "ssh://example.com/r": false, "file:/r": false, "example.com/r": false, "": false, } { if got := linkURLIsHTTP(url); got != want { t.Errorf("linkURLIsHTTP(%q) = %v, want %v", url, got, want) } } } func TestLinkMTime(t *testing.T) { for field, want := range map[string]int64{ "1767225600": 1767225600, "1": 1, "007": 7, "0": 0, "-5": 0, "+5": 0, "0x10": 0, "12z": 0, "": 0, " 5": 0, "99999999999999999999": 0, } { got, ok := linkMTime(field) if ok != (want > 0) || (ok && got != want) { t.Errorf("linkMTime(%q) = %d, %v; want %d", field, got, ok, want) } } } // TestSendsReqLinks checks the cases fossil's client_sync leaves out: a // push-only session, a later round, and another project's code. func TestSendsReqLinks(t *testing.T) { for _, tc := range []struct { name string opts SyncOpts cycle int want bool }{ {"off", SyncOpts{Pull: true}, 0, false}, {"pull", SyncOpts{Pull: true, ShareLinks: true}, 0, true}, {"later round", SyncOpts{Pull: true, ShareLinks: true}, 1, false}, {"push only", SyncOpts{Push: true, ShareLinks: true}, 0, false}, {"own code", SyncOpts{Pull: true, ShareLinks: true, ProjectCode: testPC}, 0, true}, {"other code", SyncOpts{Pull: true, ShareLinks: true, ProjectCode: "abc"}, 0, false}, } { s, _ := newTestSession(t, tc.opts) if got := s.sendsReqLinks(tc.cycle); got != tc.want { t.Errorf("%s: sendsReqLinks(%d) = %v, want %v", tc.name, tc.cycle, got, tc.want) } } }