Repository: etcd-io/etcd
File: tests/e2e/ctl_v3_member_test.go (Go)

Code before:
			}()
			require.Len(t, promotedMembers, 1)
			t.Logf("Promoted member: %+v", promotedMembers[0])

			if tc.snapshotCount != 0 {
				t.Logf("Write %d keys to trigger a snapshot", tc.snapshotCount)
				for i := 0; i < int(tc.snapshotCount); i++ {
					err := epc.Etcdctl().Put(ctx, fmt.Sprintf("key_%d", i), fmt.Sprintf("value_%d", i), config.PutOptions{})
					require.NoError(t, err)
				}
			}

			if tc.writeToV3StoreSuccess {
				t.Log("Skip manually changing the already promoted member to a learner in v3store")
			} else {
				t.Logf("Stopping all members")
				require.NoError(t, epc.Stop())

				t.Log("Manually changing the already promoted member to a learner again in the v3store of all members to simulate the issue https://github.com/etcd-io/etcd/issues/19557")
				promotedMembers[0].IsLearner = true
				for i := 0; i < len(epc.Procs); i++ {
					mustSaveMemberIntoBbolt(t, epc.Procs[i].Config().DataDirPath, promotedMembers[0])
				}
			}

			t.Log("Upgrading the cluster")
			currentVersion, err := e2e.GetVersionFromBinary(e2e.BinPath.Etcd)
			require.NoError(t, err)
			lastVersion, err := e2e.GetVersionFromBinary(e2e.BinPath.EtcdLastRelease)
			require.NoError(t, err)
			err = e2e.DowngradeUpgradeMembers(t, nil, epc, len(epc.Procs), false, lastVersion, currentVersion)
			require.NoError(t, err)

			for _, proc := range epc.Procs {
				if tc.snapshotCount != 0 {
					e2e.AssertProcessLogs(t, proc, "Syncing member in v3store")
				} else {
					if tc.writeToV3StoreSuccess {
						e2e.AssertProcessLogs(t, proc, "ignore already promoted member")
					} else {
						e2e.AssertProcessLogs(t, proc, "Forcibly apply member promotion request")
					}
				}
			}

			t.Log("Checking all members are ready to serve client requests")
			for i := 0; i < len(epc.Procs); i++ {
				e2e.AssertProcessLogs(t, epc.Procs[i], e2e.EtcdServerReadyLines[0])
			}

			t.Log("Ensure all members in v3store are voting members again")

Review comment (refactor):
we can move this assignment to the beginning of the test 

```go
func TestCtlV3PromotingLearner(t *testing.T) {
  -- here
```

Code after:
			}()
			require.Len(t, promotedMembers, 1)
			t.Logf("Promoted member: %+v", promotedMembers[0])

			if tc.snapshotCount != 0 {
				t.Logf("Write %d keys to trigger a snapshot", tc.snapshotCount)
				for i := 0; i < int(tc.snapshotCount); i++ {
					err := epc.Etcdctl().Put(ctx, fmt.Sprintf("key_%d", i), fmt.Sprintf("value_%d", i), config.PutOptions{})
					require.NoError(t, err)
				}
			}

			if tc.writeToV3StoreSuccess {
				t.Log("Skip manually changing the already promoted member to a learner in v3store")
			} else {
				t.Logf("Stopping all members")
				require.NoError(t, epc.Stop())

				t.Log("Manually changing the already promoted member to a learner again in the v3store of all members to simulate the issue https://github.com/etcd-io/etcd/issues/19557")
				promotedMembers[0].IsLearner = true
				for i := 0; i < len(epc.Procs); i++ {
					mustSaveMemberIntoBbolt(t, epc.Procs[i].Config().DataDirPath, promotedMembers[0])
				}
			}

			t.Log("Upgrading the cluster")
			currentVersion, err := e2e.GetVersionFromBinary(e2e.BinPath.Etcd)
			require.NoError(t, err)
			lastVersion, err := e2e.GetVersionFromBinary(e2e.BinPath.EtcdLastRelease)
			require.NoError(t, err)
			err = e2e.DowngradeUpgradeMembers(t, nil, epc, len(epc.Procs), false, lastVersion, currentVersion)
			require.NoError(t, err)

			t.Log("Check the expected log message")
			for _, proc := range epc.Procs {
				if tc.snapshotCount != 0 {
					e2e.AssertProcessLogs(t, proc, "Syncing member in v3store")
				} else {
					if tc.writeToV3StoreSuccess {
						e2e.AssertProcessLogs(t, proc, "ignore already promoted member")
					} else {
						e2e.AssertProcessLogs(t, proc, "Forcibly apply member promotion request")
					}
				}
			}

			t.Log("Checking all members are ready to serve client requests")
			for i := 0; i < len(epc.Procs); i++ {
				e2e.AssertProcessLogs(t, epc.Procs[i], e2e.EtcdServerReadyLines[0])
			}