func TestUpgradeNewVersion(t *testing.T) {
	t.Parallel()
	versions := []migration.Version{
		{
			Number:    0,
			Migration: nil,
		},
		{
			Number: 1,
			Migration: func(walletdb.ReadWriteBucket) error {
				return nil
			},
		},
	}
	m := &mockMigrationManager{
		currentVersion: 0,
		versions:       versions,
	}
	if err := migration.Upgrade(m); err != nil {
		t.Fatalf("unable to upgrade: %v", err)
	}
	latestVersion := migration.GetLatestVersion(versions)
	if m.currentVersion != latestVersion {
		t.Fatalf("expected current version to match latest: "+
			"current=%d vs latest=%d", m.currentVersion,
			latestVersion)
	}
}
TestUpgradeNewVersion ensures that we can properly upgrade to a newer version
if available.
package migration_test
import (
	"errors"
	"fmt"
	"reflect"
	"testing"
	"github.com/davecgh/go-spew/spew"
	"github.com/gcash/bchwallet/walletdb"
	"github.com/gcash/bchwallet/walletdb/migration"
)
type mockMigrationManager struct {
	currentVersion uint32
	versions       []migration.Version
}
var _ migration.Manager = (*mockMigrationManager)(nil)
func (m *mockMigrationManager) Name() string {
	return "mock"
}
func (m *mockMigrationManager) Namespace() walletdb.ReadWriteBucket {
	return nil
}
func (m *mockMigrationManager) CurrentVersion(_ walletdb.ReadBucket) (uint32, error) {
	return m.currentVersion, nil
}
func (m *mockMigrationManager) SetVersion(_ walletdb.ReadWriteBucket, version uint32) error {
	m.currentVersion = version
	return nil
}
func (m *mockMigrationManager) Versions() []migration.Version {
	return m.versions
}
func TestGetLatestVersion(t *testing.T) {
	t.Parallel()
	tests := []struct {
		versions      []migration.Version
		latestVersion uint32
	}{
		{
			versions:      []migration.Version{},
			latestVersion: 0,
		},
		{
			versions: []migration.Version{
				{
					Number:    1,
					Migration: nil,
				},
			},
			latestVersion: 1,
		},
		{
			versions: []migration.Version{
				{
					Number:    1,
					Migration: nil,
				},
				{
					Number:    2,
					Migration: nil,
				},
			},
			latestVersion: 2,
		},
		{
			versions: []migration.Version{
				{
					Number:    2,
					Migration: nil,
				},
				{
					Number:    0,
					Migration: nil,
				},
				{
					Number:    1,
					Migration: nil,
				},
			},
			latestVersion: 2,
		},
	}
	for i, test := range tests {
		latestVersion := migration.GetLatestVersion(test.versions)
		if latestVersion != test.latestVersion {
			t.Fatalf("test %d: expected latest version %d, got %d",
				i, test.latestVersion, latestVersion)
		}
	}
}
func TestVersionsToApply(t *testing.T) {
	t.Parallel()
	tests := []struct {
		currentVersion  uint32
		versions        []migration.Version
		versionsToApply []migration.Version
	}{
		{
			currentVersion: 0,
			versions: []migration.Version{
				{
					Number:    0,
					Migration: nil,
				},
			},
			versionsToApply: nil,
		},
		{
			currentVersion: 1,
			versions: []migration.Version{
				{
					Number:    0,
					Migration: nil,
				},
			},
			versionsToApply: nil,
		},
		{
			currentVersion: 0,
			versions: []migration.Version{
				{
					Number:    0,
					Migration: nil,
				},
				{
					Number:    1,
					Migration: nil,
				},
				{
					Number:    2,
					Migration: nil,
				},
			},
			versionsToApply: []migration.Version{
				{
					Number:    1,
					Migration: nil,
				},
				{
					Number:    2,
					Migration: nil,
				},
			},
		},
		{
			currentVersion: 0,
			versions: []migration.Version{
				{
					Number:    2,
					Migration: nil,
				},
				{
					Number:    0,
					Migration: nil,
				},
				{
					Number:    1,
					Migration: nil,
				},
			},
			versionsToApply: []migration.Version{
				{
					Number:    1,
					Migration: nil,
				},
				{
					Number:    2,
					Migration: nil,
				},
			},
		},
	}
	for i, test := range tests {
		versionsToApply := migration.VersionsToApply(
			test.currentVersion, test.versions,
		)
		if !reflect.DeepEqual(versionsToApply, test.versionsToApply) {
			t.Fatalf("test %d: versions to apply mismatch\n"+
				"expected: %v\ngot: %v", i,
				spew.Sdump(test.versionsToApply),
				spew.Sdump(versionsToApply))
		}
	}
}
func TestUpgradeRevert(t *testing.T) {
	t.Parallel()
	m := &mockMigrationManager{
		currentVersion: 1,
		versions: []migration.Version{
			{
				Number:    0,
				Migration: nil,
			},
		},
	}
	if err := migration.Upgrade(m); err != migration.ErrReversion {
		t.Fatalf("expected Upgrade to fail with ErrReversion, got %v",
			err)
	}
}
func TestUpgradeSameVersion(t *testing.T) {
	t.Parallel()
	m := &mockMigrationManager{
		currentVersion: 1,
		versions: []migration.Version{
			{
				Number:    0,
				Migration: nil,
			},
			{
				Number: 1,
				Migration: func(walletdb.ReadWriteBucket) error {
					return errors.New("migration should " +
						"not happen due to already " +
						"being on the latest version")
				},
			},
		},
	}
	if err := migration.Upgrade(m); err != nil {
		t.Fatalf("unable to upgrade: %v", err)
	}
}