package jetbrains.mps.ide.vcs.test.merge; /*Generated by MPS */ import jetbrains.mps.testbench.BaseMpsTest; import java.util.regex.Pattern; import jetbrains.mps.smodel.adapter.structure.concept.SConceptAdapterById; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.tool.environment.Environment; import java.io.File; import jetbrains.mps.util.FileUtil; import jetbrains.mps.project.Project; import org.jetbrains.mps.openapi.module.ModelAccess; import org.jetbrains.mps.openapi.module.SRepository; import jetbrains.mps.smodel.DefaultSModel; import org.jetbrains.mps.openapi.persistence.StreamDataSource; import com.intellij.openapi.ui.TestDialog; import org.junit.BeforeClass; import jetbrains.mps.tool.environment.IdeaEnvironment; import jetbrains.mps.tool.environment.EnvironmentConfig; import org.junit.Assert; import org.junit.AfterClass; import org.junit.Before; import org.jetbrains.mps.openapi.model.SModel; import jetbrains.mps.smodel.CopyUtil; import jetbrains.mps.smodel.DefaultSModelDescriptor; import jetbrains.mps.vcs.platform.integration.ModelStorageProblemsListener; import org.junit.After; import org.junit.Test; import jetbrains.mps.project.Solution; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; import org.jetbrains.mps.openapi.model.EditableSModel; import jetbrains.mps.smodel.ModuleRepositoryFacade; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.smodel.behaviour.BHReflection; import jetbrains.mps.core.aspects.behaviour.SMethodTrimmedId; import jetbrains.mps.util.Reference; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import java.util.List; import java.util.ArrayList; import java.util.Scanner; import java.util.regex.Matcher; import java.io.PrintWriter; import java.io.FileNotFoundException; import org.jetbrains.annotations.Nullable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.newvfs.RefreshSession; import com.intellij.openapi.vfs.newvfs.RefreshQueue; import jetbrains.mps.smodel.persistence.def.ModelPersistence; import java.io.IOException; /** * * @author Evgeny Gerashchenko * @since 3/23/11 */ public class DiskMemoryConflictsTest extends BaseMpsTest { private static Pattern FIELD_DECLARATION_CONCEPT_ENTRY_MATCHING_PATTERN = Pattern.compile("\\s*<concept id=\"" + ((SConceptAdapterById) MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca68L, "jetbrains.mps.baseLanguage.structure.FieldDeclaration")).getId().getIdValue() + "\"([^\\/]+)/>"); private static Pattern CONCEPT_INDEX_MATCHING_PATTERN = Pattern.compile(".*index=\"([^/]+)\".*"); private static Pattern PROPERTY_VALUE_MATCHING_PATTERN = Pattern.compile(".*<property.*value=\"([^\"]+)\".*"); private static Environment ENV; private static final File DESTINATION_PROJECT_DIR = new File(FileUtil.getTempDir(), "testConflicts"); private static final File PROJECT_LOCATION = new File("testbench/modules/simpleProject"); private static final File MODEL_FILE = getModelFile(); private static final String FIELD_DEFAULT_NAME = "theField"; private static final String FIELD_NAME_IN_FILE = "theFieldInFile"; private static final String FIELD_NAME_IN_MODEL = "theFieldInModel"; private static Project ourProject; private static ModelAccess ourModelAccess; private static SRepository ourRepository; private DefaultSModel myModelBackup; private StreamDataSource myOriginalModelDataSource; private DiskMemoryConflictsTest.TestDialogImpl myMockDialog = null; private TestDialog myOriginalDialog; public DiskMemoryConflictsTest() { } @BeforeClass public static void setup() { ENV = IdeaEnvironment.getOrCreate(EnvironmentConfig.defaultConfig().withVcsPlugin()); ourProject = BaseMpsTest.openClonedProject(PROJECT_LOCATION, DESTINATION_PROJECT_DIR); ourModelAccess = ourProject.getModelAccess(); Assert.assertNotNull(ourModelAccess); ourRepository = ourProject.getRepository(); Assert.assertNotNull(ourRepository); } @AfterClass public static void tearDown() { BaseMpsTest.closeClonedProject(ourProject, DESTINATION_PROJECT_DIR); ENV.release(); } @Before public void beforeTest() { ourModelAccess.runReadAction(new Runnable() { public void run() { SModel model = getModel(); myModelBackup = (DefaultSModel) CopyUtil.copyModel(((DefaultSModelDescriptor) model).getSModel()); myOriginalModelDataSource = (StreamDataSource) model.getSource(); } }); Assert.assertNotNull(myModelBackup); Assert.assertNotNull(myOriginalModelDataSource); myOriginalDialog = ModelStorageProblemsListener.setTestDialog(myMockDialog = new DiskMemoryConflictsTest.TestDialogImpl()); } @After public void afterTest() { ModelStorageProblemsListener.setTestDialog(myOriginalDialog); myMockDialog = null; restoreModel(); checkInitialState(); myModelBackup = null; myOriginalModelDataSource = null; } @Test public void modifyDisk_chooseMemory() { setFieldNameInModel(FIELD_NAME_IN_MODEL); setFieldNameInFile(FIELD_NAME_IN_FILE); myMockDialog.waitForShow(1); refreshVfs(); Assert.assertTrue(myMockDialog.wasExecuted()); checkSynchronizedState(FIELD_NAME_IN_MODEL); } @Test public void modifyDisk_chooseDisk() { setFieldNameInModel(FIELD_NAME_IN_MODEL); setFieldNameInFile(FIELD_NAME_IN_FILE); myMockDialog.waitForShow(0); refreshVfs(); Assert.assertTrue(myMockDialog.wasExecuted()); checkSynchronizedState(FIELD_NAME_IN_FILE); } @Test public void deleteDisk_chooseMemory() { setFieldNameInModel(FIELD_NAME_IN_MODEL); DiskMemoryConflictsTest.delete(); myMockDialog.waitForShow(0); refreshVfs(); Assert.assertTrue(myMockDialog.wasExecuted()); checkSynchronizedState(FIELD_NAME_IN_MODEL); } @Test public void deleteDisk_chooseDisk() { setFieldNameInModel(FIELD_NAME_IN_MODEL); DiskMemoryConflictsTest.delete(); myMockDialog.waitForShow(1); refreshVfs(); Assert.assertTrue(myMockDialog.wasExecuted()); } private Solution getSolution() { return (Solution) PersistenceFacade.getInstance().createModuleReference("c0209407-bdbc-42e5-9368-04e272725dd0(simpleProject)").resolve(ourRepository); } private EditableSModel getModel() { return (EditableSModel) new ModuleRepositoryFacade(ourRepository).getModelByName("simpleModel"); } private SNode getField() { SNode node = SNodeOperations.getNode("r:21cf9f47-5464-40f2-9509-d94ba20bfe82(simpleModel)", "6010389230754495463"); SNode theField = Sequence.fromIterable(((Iterable<SNode>) BHReflection.invoke(node, SMethodTrimmedId.create("fields", MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept"), "4_LVZ3pC27C")))).first(); return theField; } private String processFieldNameInModel(final String nameToWrite) { final String[] result = new String[1]; final Reference<Throwable> refThrowable = new Reference<Throwable>(); ourModelAccess.executeCommandInEDT(new Runnable() { @Override public void run() { try { SNode theField = getField(); Assert.assertNotNull(theField); if (nameToWrite == null) { result[0] = SPropertyOperations.getString(theField, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")); } else { SPropertyOperations.set(theField, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"), nameToWrite); } } catch (Throwable t) { refThrowable.set(t); } } }); DiskMemoryConflictsTest.waitEDT(); if (!(refThrowable.isNull())) { throw new RuntimeException(refThrowable.get()); } return result[0]; } private void setFieldNameInModel(String value) { processFieldNameInModel(value); } private String getFieldNameFromModel() { return processFieldNameInModel(null); } private String processFieldNameInFile(final String nameToWrite) { // File stuff if (!(DiskMemoryConflictsTest.MODEL_FILE.exists())) { return null; } List<String> lines = new ArrayList<String>(); try { Scanner scanner = new Scanner(DiskMemoryConflictsTest.MODEL_FILE); boolean fieldFound = false; boolean nameFound = false; Pattern fieldStartPattern = null; try { while (scanner.hasNextLine()) { String line = scanner.nextLine(); if (fieldStartPattern == null) { fieldStartPattern = parseFieldStartPattern(line); } else if (!(fieldFound)) { fieldFound = fieldStartPattern.matcher(line).matches(); } else if (!(nameFound)) { Matcher matcher = PROPERTY_VALUE_MATCHING_PATTERN.matcher(line); if (matcher.matches()) { nameFound = true; String fieldName = matcher.group(1); if (nameToWrite == null) { return fieldName; } line = line.replace(fieldName, nameToWrite); } } lines.add(line); } } finally { scanner.close(); } long lastModifiedBefore = DiskMemoryConflictsTest.MODEL_FILE.lastModified(); PrintWriter w = new PrintWriter(DiskMemoryConflictsTest.MODEL_FILE); for (String line : lines) { w.println(line); } w.close(); if (DiskMemoryConflictsTest.MODEL_FILE.lastModified() == lastModifiedBefore) { DiskMemoryConflictsTest.setLastModified(lastModifiedBefore + 1000); } DiskMemoryConflictsTest.setLastModified(lastModifiedBefore + 2000 + (int) (Math.random() * 100000)); } catch (FileNotFoundException e) { Assert.fail(); } return null; } private Pattern parseFieldStartPattern(String line) { Matcher matcher = FIELD_DECLARATION_CONCEPT_ENTRY_MATCHING_PATTERN.matcher(line); if (matcher.matches()) { String conceptEntryContent = matcher.group(1); Matcher conceptIndexMatcher = CONCEPT_INDEX_MATCHING_PATTERN.matcher(conceptEntryContent); if (conceptIndexMatcher.matches()) { String fdConceptIndex = conceptIndexMatcher.group(1); return Pattern.compile(".*<node.*concept=\"" + fdConceptIndex + "\".*"); } } return null; } private String getFieldNameFromFile() { return processFieldNameInFile(null); } private void setFieldNameInFile(String name) { processFieldNameInFile(name); } private void checkInitialState() { checkSynchronizedState(DiskMemoryConflictsTest.FIELD_DEFAULT_NAME); } private void checkSynchronizedState(@Nullable final String fieldName) { Assert.assertEquals(fieldName, getFieldNameFromModel()); Assert.assertEquals(fieldName, getFieldNameFromFile()); final Reference<Throwable> refThrowable = new Reference<Throwable>(); ourModelAccess.runReadAction(new Runnable() { public void run() { try { EditableSModel model = getModel(); if (fieldName == null) { Assert.assertNull(model); } else { Assert.assertFalse(model.isChanged()); } } catch (Throwable t) { refThrowable.set(t); } } }); if (!(refThrowable.isNull())) { throw new RuntimeException(refThrowable.get()); } } private void refreshVfs() { // AP: simple IFile#refresh will do, won't it? VirtualFile vf = LocalFileSystem.getInstance().findFileByIoFile(DiskMemoryConflictsTest.MODEL_FILE); if (vf == null || !(vf.exists())) { vf = LocalFileSystem.getInstance().findFileByIoFile(DiskMemoryConflictsTest.MODEL_FILE.getParentFile()); } RefreshSession rs = RefreshQueue.getInstance().createSession(false, true, null); assert vf != null; rs.addFile(vf); rs.launch(); waitEDT(); } private void restoreModel() { final Reference<Throwable> refThrowable = new Reference<Throwable>(); // Restore model ourModelAccess.executeCommandInEDT(new Runnable() { @Override public void run() { try { try { ModelPersistence.saveModel(myModelBackup, myOriginalModelDataSource, myModelBackup.getSModelHeader().getPersistenceVersion()); } catch (IOException e) { e.printStackTrace(); Assert.fail(); } getSolution().updateModelsSet(); getModel().reloadFromSource(); } catch (Throwable t) { refThrowable.set(t); } } }); waitEDT(); if (!(refThrowable.isNull())) { throw new RuntimeException(refThrowable.get()); } } private static File getModelFile() { File modelFile = new File(DiskMemoryConflictsTest.DESTINATION_PROJECT_DIR, "solutions/simpleProject/simpleModel.mps"); try { return modelFile.getCanonicalFile(); } catch (IOException ex) { ex.printStackTrace(); } return modelFile; } private static void setLastModified(long timeStamp) { if (!(MODEL_FILE.setLastModified(timeStamp))) { Assert.fail(); } } private static void delete() { if (!(MODEL_FILE.delete())) { Assert.fail(); } } private static void waitEDT() { BaseMpsTest.getEnvironment().flushAllEvents(); } private class TestDialogImpl implements TestDialog { private boolean myExecuted; private int myReturnValue; public int show(String string) { assert !(myExecuted); myExecuted = true; return myReturnValue; } public boolean wasExecuted() { return myExecuted; } public void waitForShow(int nextShowValue) { myReturnValue = nextShowValue; myExecuted = false; } } }