You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: migrate_data_test.go
    path of file: ./repos/portainer/api/datastore
    
    the code of the file until where you have to start completion: package datastore

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"testing"

	"github.com/Masterminds/semver"
	portainer "github.com/portainer/portainer/api"
	"github.com/portainer/portainer/api/database/boltdb"
	"github.com/portainer/portainer/api/database/models"
	"github.com/portainer/portainer/api/datastore/migrator"

	"github.com/google/go-cmp/cmp"
	"github.com/rs/zerolog/log"
)

func TestMigrateData(t *testing.T) {
	tests := []struct {
		testName           string
		srcPath            string
		wantPath           string
		overrideInstanceId bool
	}{
		{
			testName:           "migrate version 24 to latest",
			srcPath:            "test_data/input_24.json",
			wantPath:           "test_data/output_24_to_latest.json",
			overrideInstanceId: true,
		},
	}
	for _, test := range tests {
		t.Run(test.testName, func(t *testing.T) {
			err := migrateDBTestHelper(t, test.srcPath, test.wantPath, test.overrideInstanceId)
			if err != nil {
				t.Errorf(
					"Failed migratin
    
func TestMigrateData(t *testing.T) {
	tests := []struct {
		testName           string
		srcPath            string
		wantPath           string
		overrideInstanceId bool
	}{
		{
			testName:           "migrate version 24 to latest",
			srcPath:            "test_data/input_24.json",
			wantPath:           "test_data/output_24_to_latest.json",
			overrideInstanceId: true,
		},
	}
	for _, test := range tests {
		t.Run(test.testName, func(t *testing.T) {
			err := migrateDBTestHelper(t, test.srcPath, test.wantPath, test.overrideInstanceId)
			if err != nil {
				t.Errorf(
					"Failed migrating mock database %v: %v",
					test.srcPath,
					err,
				)
			}
		})
	}

	t.Run("MigrateData for New Store & Re-Open Check", func(t *testing.T) {
		newStore, store := MustNewTestStore(t, true, false)
		if !newStore {
			t.Error("Expect a new DB")
		}

		testVersion(store, portainer.APIVersion, t)
		store.Close()

		newStore, _ = store.Open()
		if newStore {
			t.Error("Expect store to NOT be new DB")
		}
	})

	t.Run("MigrateData should create backup file upon update", func(t *testing.T) {
		_, store := MustNewTestStore(t, true, false)
		store.VersionService.UpdateVersion(&models.Version{SchemaVersion: "1.0", Edition: int(portainer.PortainerCE)})
		store.MigrateData()

		backupfilename := store.backupFilename()
		if exists, _ := store.fileService.FileExists(backupfilename); !exists {
			t.Errorf("Expect backup file to be created %s", backupfilename)
		}
	})

	t.Run("MigrateData should recover and restore backup during migration critical failure", func(t *testing.T) {
		os.Setenv("PORTAINER_TEST_MIGRATE_FAIL", "FAIL")

		version := "2.15"
		_, store := MustNewTestStore(t, true, false)
		store.VersionService.UpdateVersion(&models.Version{SchemaVersion: version, Edition: int(portainer.PortainerCE)})
		store.MigrateData()

		store.Open()
		testVersion(store, version, t)
	})

	t.Run("MigrateData should fail to create backup if database file is set to updating", func(t *testing.T) {
		_, store := MustNewTestStore(t, true, false)
		store.VersionService.StoreIsUpdating(true)
		store.MigrateData()

		// If you get an error, it usually means that the backup folder doesn't exist (no backups). Expected!
		// If the backup file is not blank, then it means a backup was created.  We don't want that because we
		// only create a backup when the version changes.
		backupfilename := store.backupFilename()
		if exists, _ := store.fileService.FileExists(backupfilename); exists {
			t.Errorf("Backup file should not exist for dirty database")
		}
	})

	t.Run("MigrateData should not create backup on startup if portainer version matches db", func(t *testing.T) {
		_, store := MustNewTestStore(t, true, false)

		// Set migrator the count to match our migrations array (simulate no changes).
		// Should not create a backup
		v, err := store.VersionService.Version()
		if err != nil {
			t.Errorf("Unable to read version from db: %s", err)
			t.FailNow()
		}

		migratorParams := store.newMigratorParameters(v)
		m := migrator.NewMigrator(migratorParams)
		latestMigrations := m.LatestMigrations()

		if latestMigrations.Version.Equal(semver.MustParse(portainer.APIVersion)) {
			v.MigratorCount = len(latestMigrations.MigrationFuncs)
			store.VersionService.UpdateVersion(v)
		}

		store.MigrateData()

		// If you get an error, it usually means that the backup folder doesn't exist (no backups). Expected!
		// If the backup file is not blank, then it means a backup was created.  We don't want that because we
		// only create a backup when the version changes.
		backupfilename := store.backupFilename()
		if exists, _ := store.fileService.FileExists(backupfilename); exists {
			t.Errorf("Backup file should not exist for dirty database")
		}
	})

	t.Run("MigrateData should create backup on startup if portainer version matches db and migrationFuncs counts differ", func(t *testing.T) {
		_, store := MustNewTestStore(t, true, false)

		// Set migrator count very large to simulate changes
		// Should not create a backup
		v, err := store.VersionService.Version()
		if err != nil {
			t.Errorf("Unable to read version from db: %s", err)
			t.FailNow()
		}

		v.MigratorCount = 1000
		store.VersionService.UpdateVersion(v)
		store.MigrateData()

		// If you get an error, it usually means that the backup folder doesn't exist (no backups). Expected!
		// If the backup file is not blank, then it means a backup was created.  We don't want that because we
		// only create a backup when the version changes.
		backupfilename := store.backupFilename()
		if exists, _ := store.fileService.FileExists(backupfilename); !exists {
			t.Errorf("DB backup should exist and there should be no error")
		}
	})
}