/wsmaster/wsmaster-local/src/test/java/org/eclipse/che/api/local/LocalToJpaDataMigratorTest.java
Java | 300 lines | 261 code | 24 blank | 15 comment | 0 complexity | 038242c413f01e8f10d82d4b2c30e7cd MD5 | raw file
1/*******************************************************************************
2 * Copyright (c) 2012-2016 Codenvy, S.A.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Codenvy, S.A. - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.che.api.local;
12
13import com.google.common.collect.ImmutableMap;
14import com.google.gson.Gson;
15import com.google.gson.JsonElement;
16import com.google.gson.JsonObject;
17import com.google.gson.JsonPrimitive;
18import com.google.gson.JsonSerializationContext;
19import com.google.gson.JsonSerializer;
20import com.google.inject.AbstractModule;
21import com.google.inject.Guice;
22import com.google.inject.Injector;
23import com.google.inject.Stage;
24import com.google.inject.name.Names;
25import com.google.inject.persist.jpa.JpaPersistModule;
26
27import org.eclipse.che.account.shared.model.Account;
28import org.eclipse.che.api.local.storage.LocalStorageFactory;
29import org.eclipse.che.api.local.storage.stack.StackLocalStorage;
30import org.eclipse.che.api.machine.server.jpa.MachineJpaModule;
31import org.eclipse.che.api.machine.server.model.impl.SnapshotImpl;
32import org.eclipse.che.api.machine.server.recipe.RecipeImpl;
33import org.eclipse.che.api.machine.server.spi.RecipeDao;
34import org.eclipse.che.api.machine.server.spi.SnapshotDao;
35import org.eclipse.che.api.ssh.server.jpa.SshJpaModule;
36import org.eclipse.che.api.ssh.server.model.impl.SshPairImpl;
37import org.eclipse.che.api.ssh.server.spi.SshDao;
38import org.eclipse.che.api.user.server.jpa.UserJpaModule;
39import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
40import org.eclipse.che.api.user.server.model.impl.UserImpl;
41import org.eclipse.che.api.user.server.spi.PreferenceDao;
42import org.eclipse.che.api.user.server.spi.ProfileDao;
43import org.eclipse.che.api.user.server.spi.UserDao;
44import org.eclipse.che.api.workspace.server.WorkspaceConfigJsonAdapter;
45import org.eclipse.che.api.workspace.server.WorkspaceManager;
46import org.eclipse.che.api.workspace.server.jpa.WorkspaceJpaModule;
47import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
48import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
49import org.eclipse.che.api.workspace.server.model.impl.stack.StackComponentImpl;
50import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
51import org.eclipse.che.api.workspace.server.model.impl.stack.StackSourceImpl;
52import org.eclipse.che.api.workspace.server.spi.StackDao;
53import org.eclipse.che.api.workspace.server.spi.WorkspaceDao;
54import org.eclipse.che.api.workspace.server.stack.StackJsonAdapter;
55import org.eclipse.che.api.workspace.server.stack.image.StackIcon;
56import org.eclipse.che.commons.lang.IoUtil;
57import org.eclipse.che.core.db.DBInitializer;
58import org.eclipse.che.core.db.schema.SchemaInitializer;
59import org.eclipse.che.core.db.schema.impl.flyway.FlywaySchemaInitializer;
60import org.mockito.Mockito;
61import org.testng.annotations.AfterMethod;
62import org.testng.annotations.BeforeMethod;
63import org.testng.annotations.DataProvider;
64import org.testng.annotations.Test;
65
66import javax.persistence.EntityManagerFactory;
67import java.lang.reflect.Type;
68import java.nio.file.Files;
69import java.nio.file.Path;
70import java.nio.file.Paths;
71import java.util.HashMap;
72import java.util.Map;
73
74import static java.util.Arrays.asList;
75import static java.util.Collections.singletonList;
76import static java.util.Collections.singletonMap;
77import static org.eclipse.che.commons.test.db.H2TestHelper.inMemoryDefault;
78
79/**
80 * Tests migration from local json based storage to jpa.
81 *
82 * @author Yevhenii Voevodin
83 */
84public class LocalToJpaDataMigratorTest {
85
86 private Injector injector;
87 private LocalDataMigrator migrator;
88 private Path workingDir;
89 private UserDao userDao;
90 private ProfileDao profileDao;
91 private PreferenceDao preferenceDao;
92 private WorkspaceDao workspaceDao;
93 private SnapshotDao snapshotDao;
94 private SshDao sshDao;
95 private RecipeDao recipeDao;
96 private StackDao stackDao;
97 private LocalStorageFactory factory;
98 private StackJsonAdapter stackJsonAdapter;
99 private WorkspaceConfigJsonAdapter workspaceCfgJsonAdapter;
100
101 @BeforeMethod
102 private void setUp() throws Exception {
103 workingDir = Files.createTempDirectory(Paths.get("/tmp"), "test");
104 factory = new LocalStorageFactory(workingDir.toString());
105 injector = Guice.createInjector(Stage.PRODUCTION, new AbstractModule() {
106 @Override
107 protected void configure() {
108 bindConstant().annotatedWith(Names.named("che.database")).to(workingDir.toString());
109 FlywaySchemaInitializer initializer = new FlywaySchemaInitializer(inMemoryDefault(), "che-schema");
110 bind(SchemaInitializer.class).toInstance(initializer);
111 bind(DBInitializer.class).asEagerSingleton();
112 install(new JpaPersistModule("test"));
113 install(new UserJpaModule());
114 install(new SshJpaModule());
115 install(new WorkspaceJpaModule());
116 install(new MachineJpaModule());
117 bind(StackJsonAdapter.class);
118 bind(WorkspaceManager.class).toInstance(Mockito.mock(WorkspaceManager.class));
119 }
120 });
121 userDao = injector.getInstance(UserDao.class);
122 preferenceDao = injector.getInstance(PreferenceDao.class);
123 profileDao = injector.getInstance(ProfileDao.class);
124 sshDao = injector.getInstance(SshDao.class);
125 snapshotDao = injector.getInstance(SnapshotDao.class);
126 workspaceDao = injector.getInstance(WorkspaceDao.class);
127 recipeDao = injector.getInstance(RecipeDao.class);
128 stackDao = injector.getInstance(StackDao.class);
129 stackJsonAdapter = injector.getInstance(StackJsonAdapter.class);
130 workspaceCfgJsonAdapter = injector.getInstance(WorkspaceConfigJsonAdapter.class);
131 migrator = new LocalDataMigrator();
132 storeTestData();
133 }
134
135 @AfterMethod
136 public void cleanup() {
137 IoUtil.deleteRecursive(workingDir.toFile());
138 injector.getInstance(EntityManagerFactory.class).close();
139 }
140
141 @Test
142 public void shouldSuccessfullyPerformMigration() throws Exception {
143 migrator.performMigration(workingDir.toString(),
144 userDao,
145 profileDao,
146 preferenceDao,
147 sshDao,
148 workspaceDao,
149 snapshotDao,
150 recipeDao,
151 stackDao,
152 stackJsonAdapter,
153 workspaceCfgJsonAdapter);
154 }
155
156 @Test(expectedExceptions = Exception.class, dataProvider = "failFilenames")
157 public void shouldFailIfEntitiesAreInconsistent(String filename) throws Exception {
158 Files.delete(workingDir.resolve(filename));
159 migrator.performMigration(workingDir.toString(),
160 userDao,
161 profileDao,
162 preferenceDao,
163 sshDao,
164 workspaceDao,
165 snapshotDao,
166 recipeDao,
167 stackDao,
168 stackJsonAdapter,
169 workspaceCfgJsonAdapter);
170 }
171
172 @DataProvider(name = "failFilenames")
173 private Object[][] failFilenames() {
174 return new String[][] {
175 {LocalUserDaoImpl.FILENAME},
176 {LocalWorkspaceDaoImpl.FILENAME}
177 };
178 }
179
180 private void storeTestData() throws Exception {
181 final UserImpl user = createUser("user123");
182 final ProfileImpl profile = createProfile(user.getId());
183 final Map<String, String> preferences = createPreferences();
184 final SshPairImpl pair = createSshPair(user.getId(), "service", "name");
185 final WorkspaceImpl workspace = createWorkspace("id", user.getAccount());
186 final SnapshotImpl snapshot = createSnapshot("snapshot123", workspace.getId());
187 final RecipeImpl recipe = createRecipe("recipe123");
188 final StackImpl stack = createStack("stack123", "stack-name");
189 factory.create(LocalUserDaoImpl.FILENAME).store(singletonMap(user.getId(), user));
190 factory.create(LocalProfileDaoImpl.FILENAME).store(singletonMap(profile.getUserId(), profile));
191 factory.create(LocalPreferenceDaoImpl.FILENAME).store(singletonMap(user.getId(), preferences));
192 factory.create(LocalSshDaoImpl.FILENAME, singletonMap(SshPairImpl.class, new SshSerializer()))
193 .store(singletonMap(pair.getOwner(), singletonList(pair)));
194 factory.create(LocalWorkspaceDaoImpl.FILENAME, singletonMap(WorkspaceImpl.class, new WorkspaceSerializer()))
195 .store(singletonMap(workspace.getId(), workspace));
196 factory.create(LocalSnapshotDaoImpl.FILENAME).store(singletonMap(snapshot.getId(), snapshot));
197 factory.create(LocalRecipeDaoImpl.FILENAME).store(singletonMap(recipe.getId(), recipe));
198 factory.create(StackLocalStorage.STACK_STORAGE_FILE).store(singletonMap(stack.getId(), stack));
199 }
200
201 public static class WorkspaceSerializer implements JsonSerializer<WorkspaceImpl> {
202 @Override
203 public JsonElement serialize(WorkspaceImpl src, Type typeOfSrc, JsonSerializationContext context) {
204 JsonElement result = new Gson().toJsonTree(src, WorkspaceImpl.class);
205 result.getAsJsonObject().addProperty("namespace", src.getNamespace());
206 result.getAsJsonObject().remove("account");
207 return result;
208 }
209 }
210
211 public static class SshSerializer implements JsonSerializer<SshPairImpl> {
212 @Override
213 public JsonElement serialize(SshPairImpl sshPair, Type type, JsonSerializationContext context) {
214 JsonObject result = new JsonObject();
215 result.add("service", new JsonPrimitive(sshPair.getService()));
216 result.add("name", new JsonPrimitive(sshPair.getName()));
217 result.add("privateKey", new JsonPrimitive(sshPair.getPublicKey()));
218 result.add("publicKey", new JsonPrimitive(sshPair.getPrivateKey()));
219 return result;
220 }
221 }
222
223 public static UserImpl createUser(String id) {
224 return new UserImpl(id,
225 id + "@eclipse.org",
226 id + "_name",
227 "password",
228 asList(id + "_alias1", id + "_alias2"));
229 }
230
231 public static ProfileImpl createProfile(String userId) {
232 return new ProfileImpl(userId, new HashMap<>(ImmutableMap.of("attribute1", "value1",
233 "attribute2", "value2",
234 "attribute3", "value3")));
235 }
236
237 public static Map<String, String> createPreferences() {
238 return new HashMap<>(ImmutableMap.of("preference1", "value1",
239 "preference2", "value2",
240 "preference3", "value3"));
241 }
242
243 public static WorkspaceConfigImpl createWorkspaceConfig(String id) {
244 return new WorkspaceConfigImpl(id + "_name",
245 id + "description",
246 "default-env",
247 null,
248 null,
249 null);
250 }
251
252 public static WorkspaceImpl createWorkspace(String id, Account account) {
253 return new WorkspaceImpl(id, account, createWorkspaceConfig(id));
254 }
255
256 public static SshPairImpl createSshPair(String owner, String service, String name) {
257 return new SshPairImpl(owner, service, name, "public-key", "private-key");
258 }
259
260 public static SnapshotImpl createSnapshot(String snapshotId, String workspaceId) {
261 return new SnapshotImpl(snapshotId,
262 "type",
263 null,
264 System.currentTimeMillis(),
265 workspaceId,
266 snapshotId + "_description",
267 true,
268 "dev-machine",
269 snapshotId + "env-name");
270 }
271
272 public static RecipeImpl createRecipe(String id) {
273 return new RecipeImpl(id,
274 "recipe-name-" + id,
275 "recipe-creator",
276 "recipe-type",
277 "recipe-script",
278 asList("recipe-tag1", "recipe-tag2"),
279 "recipe-description");
280 }
281
282 public static StackImpl createStack(String id, String name) {
283 return StackImpl.builder()
284 .setId(id)
285 .setName(name)
286 .setCreator("user123")
287 .setDescription(id + "-description")
288 .setScope(id + "-scope")
289 .setWorkspaceConfig(createWorkspaceConfig("test"))
290 .setTags(asList(id + "-tag1", id + "-tag2"))
291 .setComponents(asList(new StackComponentImpl(id + "-component1", id + "-component1-version"),
292 new StackComponentImpl(id + "-component2", id + "-component2-version")))
293 .setSource(new StackSourceImpl(id + "-type", id + "-origin"))
294 .setStackIcon(new StackIcon(id + "-icon",
295 id + "-media-type",
296 "0x1234567890abcdef".getBytes()))
297 .build();
298 }
299
300}