// Test operation in singleton mode func TestSingleton(t *testing.T) { gen1 := &state.State{ Generation: 1, Primary: node(1, 1), InitWAL: xlog.Zero, Freeze: state.NewFreezeDetails("singleton"), Singleton: true, } gen1pg := &simulator.PostgresInfo{ Online: true, Config: &state.PgConfig{Role: state.RolePrimary}, XLog: "0/0000000A", } info := &simulator.PeerSimInfo{ Peer: &state.PeerInfo{ ID: node1ID, Role: state.RolePrimary, Peers: []*discoverd.Instance{node(1, 1)}, State: gen1, }, Postgres: gen1pg, } runSteps(t, true, []step{ // Test starting up in singleton mode {Cmd: "echo test: start up as primary in singleton mode"}, {Cmd: "setClusterState", JSON: gen1}, {Cmd: "startPeer"}, {Cmd: "peer", Check: info}, // Test not doing anything when another peer shows up {Cmd: "echo test: do nothing with new peers"}, {Cmd: "addpeer"}, { Cmd: "peer", Check: &simulator.PeerSimInfo{ Peer: &state.PeerInfo{ ID: node1ID, Role: state.RolePrimary, Peers: []*discoverd.Instance{node(1, 1), node(2, 2)}, State: gen1, }, Postgres: gen1pg, }, }, {Cmd: "rmpeer node2"}, {Cmd: "peer", Check: info}, }) }
// Test what happens when we show up as the second node in singleton mode func TestSingletonSecond(t *testing.T) { gen1 := &state.State{ Generation: 1, Primary: node(2, 1), InitWAL: xlog.Zero, Freeze: state.NewFreezeDetails("singleton"), Singleton: true, } runSteps(t, true, []step{ // Test that we don't do anything if we start up in singleton mode when // another peer is the primary {Cmd: "echo test: start in singleton mode"}, {Cmd: "addpeer"}, {Cmd: "setclusterstate", JSON: gen1}, {Cmd: "startpeer"}, { Cmd: "peer", Check: &simulator.PeerSimInfo{ Peer: &state.PeerInfo{ ID: node1ID, Role: state.RoleUnassigned, State: gen1, Peers: []*discoverd.Instance{node(2, 1), node(1, 2)}, }, Postgres: pgOffline, }, }, // Check that we don't do anything even if the primary fails {Cmd: "echo test: do nothing even if primary fails"}, {Cmd: "rmpeer node2"}, { Cmd: "peer", Check: &simulator.PeerSimInfo{ Peer: &state.PeerInfo{ ID: node1ID, Role: state.RoleUnassigned, State: gen1, Peers: []*discoverd.Instance{node(1, 2)}, }, Postgres: pgOffline, }, }, }) }
// Test upgrading from singleton to normal mode func TestSingletonUpgradeToNormal(t *testing.T) { gen1 := &state.State{ Generation: 1, Primary: node(1, 1), InitWAL: xlog.Zero, Freeze: state.NewFreezeDetails("singleton"), Singleton: true, } runSteps(t, false, []step{ // Start in singleton mode {Cmd: "echo test: start up as primary in singleton mode"}, {Cmd: "setclusterstate", JSON: gen1}, {Cmd: "startpeer"}, { Cmd: "peer", Check: &simulator.PeerSimInfo{ Peer: &state.PeerInfo{ ID: node1ID, Role: state.RolePrimary, State: gen1, Peers: []*discoverd.Instance{node(1, 1)}, }, Postgres: &simulator.PostgresInfo{ Online: true, Config: &state.PgConfig{Role: state.RolePrimary}, XLog: "0/0000000A", }, }, }, // Unfreeze the cluster and make sure we do nothing {Cmd: "echo test: unfreeze"}, {Cmd: "unfreeze"}, { Cmd: "peer", Check: &simulator.PeerSimInfo{ Peer: &state.PeerInfo{ ID: node1ID, Role: state.RolePrimary, State: &state.State{ Generation: 1, Primary: node(1, 1), InitWAL: xlog.Zero, Singleton: true, }, Peers: []*discoverd.Instance{node(1, 1)}, }, Postgres: &simulator.PostgresInfo{ Online: true, Config: &state.PgConfig{Role: state.RolePrimary}, XLog: "0/0000000A", }, }, }, // Add another peer and see that we transition to normal mode {Cmd: "echo test: transition to normal mode"}, {Cmd: "addpeer"}, { Cmd: "peer", Check: &simulator.PeerSimInfo{ Peer: &state.PeerInfo{ ID: node1ID, Role: state.RolePrimary, State: &state.State{ Generation: 2, Primary: node(1, 1), Sync: node(2, 2), InitWAL: "0/0000000A", }, Peers: []*discoverd.Instance{node(1, 1), node(2, 2)}, }, Postgres: &simulator.PostgresInfo{ Online: true, Config: &state.PgConfig{ Role: state.RolePrimary, Downstream: node(2, 2), }, XLog: "0/00000014", }, }, }, // Add another peer, fail the sync, and make sure we reconfigure // appropriately. {Cmd: "echo test: reconfiguration in normal mode"}, {Cmd: "addpeer"}, {Cmd: "rmpeer node2"}, { Cmd: "peer", Check: &simulator.PeerSimInfo{ Peer: &state.PeerInfo{ ID: node1ID, Role: state.RolePrimary, State: &state.State{ Generation: 3, Primary: node(1, 1), Sync: node(3, 3), InitWAL: "0/00000014", }, Peers: []*discoverd.Instance{node(1, 1), node(3, 3)}, }, Postgres: &simulator.PostgresInfo{ Online: true, Config: &state.PgConfig{ Role: state.RolePrimary, Downstream: node(3, 3), }, XLog: "0/0000001E", }, }, }, {Cmd: "addpeer node2"}, { Cmd: "peer", Check: &simulator.PeerSimInfo{ Peer: &state.PeerInfo{ ID: node1ID, Role: state.RolePrimary, State: &state.State{ Generation: 3, Primary: node(1, 1), Sync: node(3, 3), Async: []*discoverd.Instance{node(2, 4)}, InitWAL: "0/00000014", }, Peers: []*discoverd.Instance{node(1, 1), node(3, 3), node(2, 4)}, }, Postgres: &simulator.PostgresInfo{ Online: true, Config: &state.PgConfig{ Role: state.RolePrimary, Downstream: node(3, 3), }, XLog: "0/0000001E", }, }, }, }) }