/* * Copyright 2015 Robert von Burg <eitch@eitchnet.ch> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package li.strolch.migrations; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; import java.util.Arrays; import java.util.List; import java.util.Map; import li.strolch.agent.api.ComponentContainer; import li.strolch.command.AddOrderCommand; import li.strolch.command.RemoveOrderCommand; import li.strolch.model.ModelGenerator; import li.strolch.model.Order; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.privilege.model.Certificate; import li.strolch.runtime.StrolchConstants; import li.strolch.testbase.runtime.RuntimeMock; import li.strolch.utils.Version; import li.strolch.utils.collections.MapOfLists; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class MigrationsTest { public static final String RUNTIME_PATH = "target/migrationstest/"; //$NON-NLS-1$ public static final String CONFIG_SRC = "src/test/resources/migrationstest"; //$NON-NLS-1$ protected static RuntimeMock runtimeMock; protected static Certificate certificate; @BeforeClass public static void beforeClass() throws Exception { File rootPath = new File(RUNTIME_PATH); File configSrc = new File(CONFIG_SRC); runtimeMock = new RuntimeMock(); runtimeMock.mockRuntime(rootPath, configSrc); runtimeMock.startContainer(); certificate = runtimeMock.getPrivilegeHandler().authenticate("test", "test".getBytes()); } @AfterClass public static void afterClass() { if (runtimeMock != null) runtimeMock.destroyRuntime(); } @Test public void shouldRunMigrations() { MigrationsHandler migrationsHandler = runtimeMock.getContainer().getComponent(MigrationsHandler.class); Map<String, MigrationVersion> currentVersions = migrationsHandler.getCurrentVersions(certificate); String defRealm = StrolchConstants.DEFAULT_REALM; assertEquals("1.1.1", currentVersions.get(defRealm).getDataVersion().toString()); assertEquals("0.0.0", currentVersions.get("other").getCodeVersion().toString()); MapOfLists<String, Version> lastMigrations = migrationsHandler.getLastMigrations(); List<Version> expectedMigrations = Arrays.asList(Version.valueOf("0.1.0"), Version.valueOf("0.1.1"), Version.valueOf("0.5.2"), Version.valueOf("1.0.0"), Version.valueOf("1.0.5"), Version.valueOf("1.1.1")); assertEquals(expectedMigrations, lastMigrations.getList(defRealm)); assertEquals(null, lastMigrations.getList("other")); MapOfLists<String, Version> migrationsToRun = migrationsHandler.queryMigrationsToRun(certificate); assertTrue("Expected to have all migrations run", migrationsToRun.isEmpty()); // assert new current version currentVersions = migrationsHandler.getCurrentVersions(certificate); assertEquals("1.1.1", currentVersions.get(defRealm).getDataVersion().toString()); assertEquals("0.0.0", currentVersions.get("other").getCodeVersion().toString()); MapOfLists<String, CodeMigration> codeMigrationsByRealm = new MapOfLists<>(); // add migrations in wrong sequence - should be fixed by migration handler codeMigrationsByRealm.addElement(defRealm, new MyMigration2(defRealm)); codeMigrationsByRealm.addElement(defRealm, new MyMigration1(defRealm)); codeMigrationsByRealm.addElement(defRealm, new MyMigration0(defRealm)); migrationsHandler.runCodeMigrations(certificate, codeMigrationsByRealm); lastMigrations = migrationsHandler.getLastMigrations(); assertEquals(1, lastMigrations.keySet().size()); assertEquals(Arrays.asList(Version.valueOf("1.0.0"),Version.valueOf("1.2.0"), Version.valueOf("1.2.0.a")), lastMigrations.getList(defRealm)); // assert new current version currentVersions = migrationsHandler.getCurrentVersions(certificate); assertEquals("1.2.0.a", currentVersions.get(defRealm).getCodeVersion().toString()); assertEquals("0.0.0", currentVersions.get("other").getDataVersion().toString()); } private static class MyMigration0 extends CodeMigration { private static final Version version = Version.valueOf("1.0.0"); public MyMigration0(String realm) { super(realm, version); } @Override public void migrate(ComponentContainer container, Certificate cert) { logger.info("[" + this.realm + "] Running migration " + this.getVersion()); try (StrolchTransaction tx = openTx(container, cert)) { Order fooOrder = ModelGenerator.createOrder("foo", "Foo", "Foo"); AddOrderCommand addOrderCommand = new AddOrderCommand(container, tx); addOrderCommand.setOrder(fooOrder); tx.addCommand(addOrderCommand); buildMigrationVersionChangeCommand(container, tx); tx.commitOnClose(); } } } private static class MyMigration1 extends CodeMigration { private static final Version version = Version.valueOf("1.2.0"); public MyMigration1(String realm) { super(realm, version); } @Override public void migrate(ComponentContainer container, Certificate cert) { logger.info("[" + this.realm + "] Running migration " + this.getVersion()); try (StrolchTransaction tx = openTx(container, cert)) { Order fooOrder = ModelGenerator.createOrder("foo1", "Foo", "Foo"); AddOrderCommand addOrderCommand = new AddOrderCommand(container, tx); addOrderCommand.setOrder(fooOrder); tx.addCommand(addOrderCommand); buildMigrationVersionChangeCommand(container, tx); tx.commitOnClose(); } } } private static class MyMigration2 extends CodeMigration { private static final Version version = Version.valueOf("1.2.0.a"); public MyMigration2(String realm) { super(realm, version); } @Override public void migrate(ComponentContainer container, Certificate cert) { logger.info("[" + this.realm + "] Running migration " + this.getVersion()); try (StrolchTransaction tx = openTx(container, cert)) { Order fooOrder = tx.getOrderBy("Foo", "foo"); RemoveOrderCommand removeOrderCommand = new RemoveOrderCommand(container, tx); removeOrderCommand.setOrder(fooOrder); tx.addCommand(removeOrderCommand); buildMigrationVersionChangeCommand(container, tx); tx.commitOnClose(); } } } }