Repository: etcd-io/etcd
File: server/storage/schema/schema_test.go (Go)

Code before:
			name:           "Downgrading v3.7 to v3.6 is not supported",
			version:        version.V3_7,
			targetVersion:  version.V3_6,
			expectVersion:  &version.V3_7,
			expectError:    true,
			expectErrorMsg: `cannot create migration plan: version "3.7.0" is not supported`,
		},
		{
			name:          "Downgrading v3.6 to v3.5 works as there are no v3.6 wal entries",
			version:       version.V3_6,
			targetVersion: version.V3_5,
			walEntries: []etcdserverpb.InternalRaftRequest{
				{Range: &etcdserverpb.RangeRequest{Key: []byte("\x00"), RangeEnd: []byte("\xff")}},
			},
			expectVersion: nil,
		},
		{
			name:          "Downgrading v3.6 to v3.5 works even if there is ClusterVersionSetRequest WAL entries with 3.6 clusterVersion",
			version:       version.V3_6,
			targetVersion: version.V3_5,
			walEntries: []etcdserverpb.InternalRaftRequest{
				{ClusterVersionSet: &membershippb.ClusterVersionSetRequest{Ver: "3.6.0"}},
			},
			expectVersion: nil, // 3.5 doesn't have field `storageVersion`, so it should be nil.
			expectError:   false,
		},
		{
			name:           "Downgrading v3.5 to v3.4 is not supported as schema was introduced in v3.6",
			version:        version.V3_5,
			targetVersion:  version.V3_4,
			expectVersion:  nil,
			expectError:    true,
			expectErrorMsg: `cannot create migration plan: version "3.5.0" is not supported`,
		},
	}
	for _, tc := range tcs {
		t.Run(tc.name, func(t *testing.T) {
			lg := zap.NewNop()
			dataPath := setupBackendData(t, tc.version, tc.overrideKeys)
			w, _ := waltesting.NewTmpWAL(t, tc.walEntries)
			defer w.Close()
			walVersion, err := wal.ReadWALVersion(w)
			if err != nil {
				t.Fatal(err)
			}

			b := backend.NewDefaultBackend(lg, dataPath)
			defer b.Close()

			err = Migrate(lg, b.BatchTx(), walVersion, tc.targetVersion)
			if (err != nil) != tc.expectError {

Review comment (suggestion):
I think we should have a test case that confirms that downgrade cannot happen if there is newer WAL entry. This might be tricky for v3.6 -> v3.5 as we don't have such entry. My original idea was to add a fake entry to wal proto definition that can be used for testing.

Code after:
			version:        version.V3_7,
			targetVersion:  version.V3_6,
			expectVersion:  &version.V3_7,
			expectError:    true,
			expectErrorMsg: `cannot create migration plan: version "3.7.0" is not supported`,
		},
		{
			name:          "Downgrading v3.6 to v3.5 works as there are no v3.6 wal entries",
			version:       version.V3_6,
			targetVersion: version.V3_5,
			walEntries: []etcdserverpb.InternalRaftRequest{
				{Range: &etcdserverpb.RangeRequest{Key: []byte("\x00"), RangeEnd: []byte("\xff")}},
			},
			expectVersion: nil,
		},
		/* TODO: add a dedicated request for testing only to cover such case
		{
			name:          "Downgrading v3.6 to v3.5 works even if there is ClusterVersionSetRequest WAL entries with 3.6 clusterVersion",
			version:       version.V3_6,
			targetVersion: version.V3_5,
			walEntries: []etcdserverpb.InternalRaftRequest{
				{ClusterVersionSet: &membershippb.ClusterVersionSetRequest{Ver: "3.6.0"}},
			},
			expectVersion: nil, // 3.5 doesn't have field `storageVersion`, so it should be nil.
			expectError:   false,
		},*/
		{
			name:           "Downgrading v3.5 to v3.4 is not supported as schema was introduced in v3.6",
			version:        version.V3_5,
			targetVersion:  version.V3_4,
			expectVersion:  nil,
			expectError:    true,
			expectErrorMsg: `cannot create migration plan: version "3.5.0" is not supported`,
		},
	}
	for _, tc := range tcs {
		t.Run(tc.name, func(t *testing.T) {
			lg := zap.NewNop()
			dataPath := setupBackendData(t, tc.version, tc.overrideKeys)
			w, _ := waltesting.NewTmpWAL(t, tc.walEntries)
			defer w.Close()
			walVersion, err := wal.ReadWALVersion(w)
			if err != nil {
				t.Fatal(err)
			}

			b := backend.NewDefaultBackend(lg, dataPath)
			defer b.Close()

			err = Migrate(lg, b.BatchTx(), walVersion, tc.targetVersion)
			if (err != nil) != tc.expectError {