MCPcopy Index your code
hub / github.com/dnote/dnote / TestSync_FreshClientConcurrent

Function TestSync_FreshClientConcurrent

pkg/e2e/sync/basic_test.go:3610–3713  ·  view source on GitHub ↗
(t *testing.T)

Source from the content-addressed store, hash-verified

3608}
3609
3610func TestSync_FreshClientConcurrent(t *testing.T) {
3611 // Test the core issue: Fresh client (never synced, lastMaxUSN=0) syncing to a server
3612 // that already has data uploaded by another client.
3613 //
3614 // Scenario:
3615 // 1. Client A creates local notes (never synced, lastMaxUSN=0, lastSyncAt=0)
3616 // 2. Client B uploads same book names to server first
3617 // 3. Client A syncs
3618 //
3619 // Expected: Client A should pull server data first, detect duplicate book names,
3620 // rename local books to avoid conflicts (js→js_2), then upload successfully.
3621
3622 env := setupTestEnv(t)
3623
3624 user := setupUserAndLogin(t, env)
3625
3626 // Client A: Create local data (never sync)
3627 clitest.RunDnoteCmd(t, env.CmdOpts, cliBinaryName, "add", "js", "-c", "js1")
3628 clitest.RunDnoteCmd(t, env.CmdOpts, cliBinaryName, "add", "css", "-c", "css1")
3629
3630 // Client B: Upload same book names to server via API
3631 jsBookUUID := apiCreateBook(t, env, user, "js", "client B creating js book")
3632 cssBookUUID := apiCreateBook(t, env, user, "css", "client B creating css book")
3633 apiCreateNote(t, env, user, jsBookUUID, "js2", "client B note")
3634 apiCreateNote(t, env, user, cssBookUUID, "css2", "client B note")
3635
3636 // Client A syncs - should handle the conflict gracefully
3637 // Expected: pulls server data, renames local books to js_2/css_2, uploads successfully
3638 clitest.RunDnoteCmd(t, env.CmdOpts, cliBinaryName, "sync")
3639
3640 // Verify: Should have 4 books and 4 notes on both client and server
3641 // USN breakdown: 2 books + 2 notes from Client B (USN 1-4), then 2 books + 2 notes from Client A (USN 5-8)
3642 checkState(t, env.DB, user, env.ServerDB, systemState{
3643 clientNoteCount: 4,
3644 clientBookCount: 4,
3645 clientLastMaxUSN: 8,
3646 clientLastSyncAt: serverTime.Unix(),
3647 serverNoteCount: 4,
3648 serverBookCount: 4,
3649 serverUserMaxUSN: 8,
3650 })
3651
3652 // Verify server has all 4 books with correct names
3653 var svrBookJS, svrBookCSS, svrBookJS2, svrBookCSS2 database.Book
3654 apitest.MustExec(t, env.ServerDB.Where("label = ?", "js").First(&svrBookJS), "finding server book 'js'")
3655 apitest.MustExec(t, env.ServerDB.Where("label = ?", "css").First(&svrBookCSS), "finding server book 'css'")
3656 apitest.MustExec(t, env.ServerDB.Where("label = ?", "js_2").First(&svrBookJS2), "finding server book 'js_2'")
3657 apitest.MustExec(t, env.ServerDB.Where("label = ?", "css_2").First(&svrBookCSS2), "finding server book 'css_2'")
3658
3659 assert.Equal(t, svrBookJS.Label, "js", "server should have book 'js' (Client B)")
3660 assert.Equal(t, svrBookCSS.Label, "css", "server should have book 'css' (Client B)")
3661 assert.Equal(t, svrBookJS2.Label, "js_2", "server should have book 'js_2' (Client A renamed)")
3662 assert.Equal(t, svrBookCSS2.Label, "css_2", "server should have book 'css_2' (Client A renamed)")
3663
3664 // Verify server has all 4 notes with correct content
3665 var svrNoteJS1, svrNoteJS2, svrNoteCSS1, svrNoteCSS2 database.Note
3666 apitest.MustExec(t, env.ServerDB.Where("body = ?", "js1").First(&svrNoteJS1), "finding server note 'js1'")
3667 apitest.MustExec(t, env.ServerDB.Where("body = ?", "js2").First(&svrNoteJS2), "finding server note 'js2'")

Callers

nothing calls this directly

Calls 8

EqualFunction · 0.92
NotEqualFunction · 0.92
setupUserAndLoginFunction · 0.85
apiCreateBookFunction · 0.85
apiCreateNoteFunction · 0.85
checkStateFunction · 0.85
setupTestEnvFunction · 0.70
QueryRowMethod · 0.65

Tested by

no test coverage detected