mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-06 06:21:16 +07:00
IDEA-212682 fixed: now projects marked as dirty cannot be reverted before import
Added FSM to control project status GitOrigin-RevId: dd70cc820e71969f7c5dc8314fd9d16f160cd09b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
19b7725ecf
commit
05629e906c
+2
@@ -11,6 +11,7 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType;
|
||||
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
|
||||
import com.intellij.openapi.externalSystem.service.internal.ExternalSystemProcessingManager;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl;
|
||||
import com.intellij.openapi.externalSystem.statistics.ExternalSystemActionsCollector;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
@@ -75,6 +76,7 @@ public class RefreshAllExternalProjectsAction extends AnAction implements AnActi
|
||||
// We save all documents because there is a possible case that there is an external system config file changed inside the ide.
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
|
||||
ExternalProjectsManagerImpl.disableProjectWatcherAutoUpdate(project);
|
||||
for (ProjectSystemId externalSystemId : systemIds) {
|
||||
ExternalSystemActionsCollector.trigger(project, externalSystemId, this, e);
|
||||
ExternalSystemUtil.refreshProjects(
|
||||
|
||||
+106
-58
@@ -61,6 +61,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.intellij.util.ui.update.MergingUpdateQueue.ANY_COMPONENT;
|
||||
@@ -92,8 +93,10 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
private final List<LocalFileSystem.WatchRequest> myWatchedRoots = new ArrayList<>();
|
||||
private final MergingUpdateQueue myRefreshRequestsQueue;
|
||||
|
||||
private final Map<String, Long/*LocalTimeStamp*/> myStartUpdatesTimeStamps = Collections.synchronizedMap(new LinkedHashMap<>());
|
||||
private final Map<String, Long/*LocalTimeStamp*/> myFileModificationTimeStamps = Collections.synchronizedMap(new LinkedHashMap<>());
|
||||
private final Map<ExternalSystemTaskId, String/*ProjectPath*/> myProjectsInSync =
|
||||
Collections.synchronizedMap(new LinkedHashMap<>());
|
||||
private final Map<String/*ProjectPath*/, ProjectStatus> myWatchedProjects =
|
||||
Collections.synchronizedMap(new LinkedHashMap<>());
|
||||
|
||||
private final CompoundParallelOperationTrace<ExternalSystemTaskId> syncTrace = new CompoundParallelOperationTrace<>();
|
||||
|
||||
@@ -138,7 +141,11 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
|
||||
@Override
|
||||
public void markDirtyAllExternalProjects() {
|
||||
findLinkedProjectsSettings().forEach(this::scheduleUpdate);
|
||||
findLinkedProjectsSettings().forEach(linkedProject -> {
|
||||
String projectPath = getExternalProjectPath(linkedProject);
|
||||
updateProjectStatus(projectPath, it -> it.markDirty(LocalTimeCounter.currentTime()));
|
||||
scheduleUpdate(linkedProject);
|
||||
});
|
||||
for (Contributor contributor : EP_NAME.getExtensions()) {
|
||||
contributor.markDirtyAllExternalProjects(myProject);
|
||||
}
|
||||
@@ -146,7 +153,9 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
|
||||
@Override
|
||||
public void markDirty(Module module) {
|
||||
scheduleUpdate(ExternalSystemApiUtil.getExternalProjectPath(module));
|
||||
String projectPath = ExternalSystemApiUtil.getExternalProjectPath(module);
|
||||
updateProjectStatus(projectPath, it -> it.markDirty(LocalTimeCounter.currentTime()));
|
||||
scheduleUpdate(projectPath);
|
||||
for (Contributor contributor : EP_NAME.getExtensions()) {
|
||||
contributor.markDirty(module);
|
||||
}
|
||||
@@ -154,6 +163,7 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
|
||||
@Override
|
||||
public void markDirty(String projectPath) {
|
||||
updateProjectStatus(projectPath, it -> it.markDirty(LocalTimeCounter.currentTime()));
|
||||
scheduleUpdate(projectPath);
|
||||
for (Contributor contributor : EP_NAME.getExtensions()) {
|
||||
contributor.markDirty(projectPath);
|
||||
@@ -182,8 +192,6 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
String externalProjectPath = getRelatedExternalProjectPath(file);
|
||||
if (externalProjectPath == null) return;
|
||||
|
||||
myFileModificationTimeStamps.put(file.getPath(), doc.getModificationStamp());
|
||||
|
||||
debug("Document changed '" + file.getPath() + "' from '" + event.getOldFragment() + "' to '" + event.getNewFragment() + "'");
|
||||
synchronized (myChangedDocuments) {
|
||||
myChangedDocuments.put(doc, Pair.create(externalProjectPath, file));
|
||||
@@ -199,20 +207,29 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
}
|
||||
|
||||
ExternalSystemUtil.invokeLater(myProject, () -> WriteAction.run(
|
||||
() -> copy.forEach((document, pair) -> {
|
||||
if (!pair.second.isValid()) return;
|
||||
|
||||
if (fileWasChanged(pair.second)) {
|
||||
scheduleUpdate(pair.first, false);
|
||||
}
|
||||
else {
|
||||
handleRevertedChanges(externalProjectPath);
|
||||
}
|
||||
})
|
||||
() -> copy.forEach((document, pair) -> handleDocumentChange(document, pair.first, pair.second))
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleDocumentChange(Document document, String externalProjectPath, VirtualFile file) {
|
||||
if (!file.isValid()) return;
|
||||
|
||||
refreshFileCrcInfo(file);
|
||||
if (fileWasChanged(file)) {
|
||||
updateProjectStatus(externalProjectPath, it -> it.markModified(document.getModificationStamp()));
|
||||
}
|
||||
else if (!projectWasChanged(externalProjectPath)) {
|
||||
updateProjectStatus(externalProjectPath, it -> it.markReverted(document.getModificationStamp()));
|
||||
}
|
||||
if (isUpToDate(externalProjectPath)) {
|
||||
handleRevertedChanges(externalProjectPath);
|
||||
}
|
||||
else {
|
||||
scheduleUpdate(externalProjectPath, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
EditorFactory.getInstance().getEventMulticaster().addDocumentListener(myDocumentListener, myChangedDocumentsQueue);
|
||||
ServiceManager.getService(ExternalSystemProgressNotificationManager.class).addNotificationListener(this);
|
||||
@@ -253,7 +270,8 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
if (id.getType() == ExternalSystemTaskType.RESOLVE_PROJECT) {
|
||||
debug("Refresh started for '" + workingDir + "'");
|
||||
|
||||
myStartUpdatesTimeStamps.put(workingDir, LocalTimeCounter.currentTime());
|
||||
myProjectsInSync.put(id, workingDir);
|
||||
updateProjectStatus(workingDir, it -> it.markSynchronized(LocalTimeCounter.currentTime()));
|
||||
|
||||
syncTrace.startTask(id);
|
||||
|
||||
@@ -283,14 +301,41 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull ExternalSystemTaskId id, @NotNull Exception e) {
|
||||
if (id.getType() == ExternalSystemTaskType.RESOLVE_PROJECT) {
|
||||
debug("Refresh failed");
|
||||
syncTrace.finishTask(id);
|
||||
String projectPath = myProjectsInSync.get(id);
|
||||
updateProjectStatus(projectPath, it -> it.markDirty(LocalTimeCounter.currentTime()));
|
||||
}
|
||||
super.onFailure(id, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(@NotNull ExternalSystemTaskId id) {
|
||||
if (id.getType() == ExternalSystemTaskType.RESOLVE_PROJECT) {
|
||||
debug("Refresh cancel");
|
||||
syncTrace.finishTask(id);
|
||||
String projectPath = myProjectsInSync.get(id);
|
||||
updateProjectStatus(projectPath, it -> it.markDirty(LocalTimeCounter.currentTime()));
|
||||
}
|
||||
super.onCancel(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnd(@NotNull ExternalSystemTaskId id) {
|
||||
if (id.getType() == ExternalSystemTaskType.RESOLVE_PROJECT) {
|
||||
syncTrace.finishTask(id);
|
||||
myProjectsInSync.remove(id);
|
||||
}
|
||||
super.onEnd(id);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getExternalProjectPath(@NotNull Pair<ExternalSystemManager, ExternalProjectSettings> linkedProject) {
|
||||
return linkedProject.second.getExternalProjectPath();
|
||||
}
|
||||
|
||||
private void scheduleUpdate(@Nullable String projectPath) {
|
||||
scheduleUpdate(projectPath, true);
|
||||
}
|
||||
@@ -321,11 +366,9 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
debug("Update disabled for '" + projectPath + "'");
|
||||
return;
|
||||
}
|
||||
if (manager instanceof ExternalSystemAutoImportAware) {
|
||||
if (!updateIsNeededFor((ExternalSystemAutoImportAware)manager, projectPath)) {
|
||||
debug("Update skipped for '" + projectPath + "'");
|
||||
return;
|
||||
}
|
||||
if (isUpToDate(projectPath)) {
|
||||
debug("Update skipped for '" + projectPath + "'");
|
||||
return;
|
||||
}
|
||||
debug("Schedule update for '" + projectPath + "'");
|
||||
|
||||
@@ -372,17 +415,9 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRevertedChanges(final String externalProjectPath) {
|
||||
private void handleRevertedChanges(final @NotNull String externalProjectPath) {
|
||||
debug("Handle reverted changes for '" + externalProjectPath + "'");
|
||||
|
||||
for (String filePath : new ArrayList<>(myKnownAffectedFiles.get(externalProjectPath))) {
|
||||
VirtualFile f = VfsUtil.findFileByIoFile(new File(filePath), false);
|
||||
if (f == null ||
|
||||
!Objects.equals(f.getUserData(CRC_WITHOUT_SPACES_BEFORE_LAST_IMPORT), f.getUserData(CRC_WITHOUT_SPACES_CURRENT))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ProjectSystemId systemId = getProjectSystemId(externalProjectPath);
|
||||
if (systemId == null) return;
|
||||
ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(systemId);
|
||||
@@ -402,36 +437,42 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean fileWasChanged(VirtualFile file) {
|
||||
if (!file.isValid()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Long newCrc = calculateCrc(file);
|
||||
file.putUserData(CRC_WITHOUT_SPACES_CURRENT, newCrc);
|
||||
|
||||
Long crc = file.getUserData(CRC_WITHOUT_SPACES_BEFORE_LAST_IMPORT);
|
||||
if (crc == null) {
|
||||
file.putUserData(CRC_WITHOUT_SPACES_BEFORE_LAST_IMPORT, newCrc);
|
||||
return true;
|
||||
}
|
||||
return !newCrc.equals(crc);
|
||||
private static boolean fileWasChanged(@NotNull VirtualFile file) {
|
||||
if (!file.isValid()) return true;
|
||||
Long currentCrc = file.getUserData(CRC_WITHOUT_SPACES_CURRENT);
|
||||
Long oldCrc = file.getUserData(CRC_WITHOUT_SPACES_BEFORE_LAST_IMPORT);
|
||||
return currentCrc == null || !currentCrc.equals(oldCrc);
|
||||
}
|
||||
|
||||
private boolean updateIsNeededFor(@NotNull ExternalSystemAutoImportAware manager, @NotNull String projectPath) {
|
||||
Long lastUpdate = myStartUpdatesTimeStamps.get(projectPath);
|
||||
if (lastUpdate == null) return true;
|
||||
List<File> affectedFiles = manager.getAffectedExternalProjectFiles(projectPath, myProject);
|
||||
for (File affectedFile : affectedFiles) {
|
||||
String affectedFilePath = FileUtil.toCanonicalPath(affectedFile.getPath());
|
||||
Long modificationStamp = myFileModificationTimeStamps.get(affectedFilePath);
|
||||
if (modificationStamp != null && modificationStamp > lastUpdate) {
|
||||
private boolean projectWasChanged(@NotNull String externalProjectPath) {
|
||||
for (String filePath : new ArrayList<>(myKnownAffectedFiles.get(externalProjectPath))) {
|
||||
VirtualFile file = VfsUtil.findFileByIoFile(new File(filePath), false);
|
||||
if (file == null || fileWasChanged(file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void refreshFileCrcInfo(@NotNull VirtualFile file) {
|
||||
if (!file.isValid()) return;
|
||||
Long crc = calculateCrc(file);
|
||||
file.putUserData(CRC_WITHOUT_SPACES_CURRENT, crc);
|
||||
}
|
||||
|
||||
private boolean isUpToDate(@NotNull String projectPath) {
|
||||
return myWatchedProjects.getOrDefault(projectPath, new ProjectStatus()).isUpToDate();
|
||||
}
|
||||
|
||||
private void updateProjectStatus(@Nullable String projectPath, @NotNull Consumer<ProjectStatus> update) {
|
||||
if (projectPath == null) return;
|
||||
myWatchedProjects.compute(projectPath, (path, status) -> {
|
||||
status = status == null ? new ProjectStatus() : status;
|
||||
update.accept(status);
|
||||
return status;
|
||||
});
|
||||
}
|
||||
|
||||
private void addToRefreshQueue(String projectPath, ProjectSystemId systemId, boolean reportRefreshError) {
|
||||
myRefreshRequestsQueue.queue(new Update(Pair.create(systemId, projectPath)) {
|
||||
@Override
|
||||
@@ -720,14 +761,20 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
|
||||
@Override
|
||||
protected void updateFile(VirtualFile file, VFileEvent event) {
|
||||
myFileModificationTimeStamps.put(file.getPath(), file.getModificationStamp());
|
||||
init();
|
||||
init();
|
||||
debug("File changed '" + file.getPath() + "'");
|
||||
refreshFileCrcInfo(file);
|
||||
if (event instanceof VFileContentChangeEvent && fileWasChanged(file)) {
|
||||
for (String externalProjectPath : myKnownFiles.get(file.getPath())) {
|
||||
updateProjectStatus(externalProjectPath, it -> it.markModified(file.getModificationStamp()));
|
||||
}
|
||||
filesToUpdate.add(file);
|
||||
}
|
||||
else {
|
||||
for (String externalProjectPath : myKnownFiles.get(file.getPath())) {
|
||||
if (projectWasChanged(externalProjectPath)) continue;
|
||||
updateProjectStatus(externalProjectPath, it -> it.markReverted(file.getModificationStamp()));
|
||||
if (!isUpToDate(externalProjectPath)) continue;
|
||||
handleRevertedChanges(externalProjectPath);
|
||||
}
|
||||
}
|
||||
@@ -735,12 +782,13 @@ public class ExternalSystemProjectsWatcherImpl extends ExternalSystemTaskNotific
|
||||
|
||||
@Override
|
||||
protected void prepareFileDeletion(VirtualFile file) {
|
||||
myFileModificationTimeStamps.put(file.getPath(), file.getModificationStamp());
|
||||
for (String externalProjectPath : myKnownFiles.get(file.getPath())) {
|
||||
updateProjectStatus(externalProjectPath, it -> it.markModified(file.getModificationStamp()));
|
||||
}
|
||||
init();
|
||||
debug("File removed '" + file.getPath() + "'");
|
||||
filesToRemove.add(file);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void apply() {
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.externalSystem.service.project.autoimport
|
||||
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.externalSystem.service.project.autoimport.ProjectStatus.ProjectEvent.*
|
||||
import com.intellij.openapi.externalSystem.service.project.autoimport.ProjectStatus.ProjectState.*
|
||||
import java.lang.Long.max
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
class ProjectStatus {
|
||||
private val LOG = Logger.getInstance(ProjectStatus::class.java)
|
||||
|
||||
private var state = AtomicReference(Synchronized(-1) as ProjectState)
|
||||
|
||||
fun isUpToDate() = when (state.get()) {
|
||||
is Modified, is Dirty -> false
|
||||
is Synchronized, is Reverted -> true
|
||||
}
|
||||
|
||||
fun markDirty(stamp: Long): ProjectState {
|
||||
return update(Invalidate(stamp))
|
||||
}
|
||||
|
||||
fun markModified(stamp: Long): ProjectState {
|
||||
return update(Modify(stamp))
|
||||
}
|
||||
|
||||
fun markReverted(stamp: Long): ProjectState {
|
||||
return update(Revert(stamp))
|
||||
}
|
||||
|
||||
fun markSynchronized(stamp: Long): ProjectState {
|
||||
return update(Synchronize(stamp))
|
||||
}
|
||||
|
||||
fun update(event: ProjectEvent): ProjectState {
|
||||
if (LOG.isDebugEnabled) {
|
||||
LOG.debug("Event ${event::class.simpleName} is happened at ${event.stamp}")
|
||||
}
|
||||
return state.updateAndGet { currentState ->
|
||||
when (currentState) {
|
||||
is Synchronized -> when (event) {
|
||||
is Synchronize -> event.withFuture(currentState, ::Synchronized)
|
||||
is Invalidate -> event.ifFuture(currentState, ::Dirty)
|
||||
is Modify -> event.ifFuture(currentState, ::Modified)
|
||||
is Revert -> event.ifFuture(currentState, ::Reverted)
|
||||
}
|
||||
is Dirty -> when (event) {
|
||||
is Synchronize -> event.ifFuture(currentState, ::Synchronized)
|
||||
is Invalidate -> event.withFuture(currentState, ::Dirty)
|
||||
is Modify -> event.withFuture(currentState, ::Dirty)
|
||||
is Revert -> event.withFuture(currentState, ::Dirty)
|
||||
}
|
||||
is Modified -> when (event) {
|
||||
is Synchronize -> event.ifFuture(currentState, ::Synchronized)
|
||||
is Invalidate -> event.withFuture(currentState, ::Dirty)
|
||||
is Modify -> event.withFuture(currentState, ::Modified)
|
||||
is Revert -> event.ifFuture(currentState, ::Reverted)
|
||||
}
|
||||
is Reverted -> when (event) {
|
||||
is Synchronize -> event.ifFuture(currentState, ::Synchronized)
|
||||
is Invalidate -> event.withFuture(currentState, ::Dirty)
|
||||
is Modify -> event.ifFuture(currentState, ::Modified)
|
||||
is Revert -> event.withFuture(currentState, ::Reverted)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ProjectEvent.withFuture(state: ProjectState, action: (Long) -> ProjectState): ProjectState {
|
||||
return action(max(stamp, state.stamp))
|
||||
}
|
||||
|
||||
private fun ProjectEvent.ifFuture(state: ProjectState, action: (Long) -> ProjectState): ProjectState {
|
||||
return if (stamp > state.stamp) action(stamp) else state
|
||||
}
|
||||
|
||||
sealed class ProjectEvent(val stamp: Long) {
|
||||
class Synchronize(stamp: Long) : ProjectEvent(stamp)
|
||||
|
||||
class Invalidate(stamp: Long) : ProjectEvent(stamp)
|
||||
|
||||
class Modify(stamp: Long) : ProjectEvent(stamp)
|
||||
|
||||
class Revert(stamp: Long) : ProjectEvent(stamp)
|
||||
}
|
||||
|
||||
sealed class ProjectState(val stamp: Long) {
|
||||
class Synchronized(stamp: Long) : ProjectState(stamp)
|
||||
|
||||
class Dirty(stamp: Long) : ProjectState(stamp)
|
||||
|
||||
class Modified(stamp: Long) : ProjectState(stamp)
|
||||
|
||||
class Reverted(stamp: Long) : ProjectState(stamp)
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.externalSystem.service.project.autoimport.states
|
||||
|
||||
import com.intellij.openapi.externalSystem.service.project.autoimport.ProjectStatus
|
||||
import com.intellij.openapi.externalSystem.service.project.autoimport.ProjectStatus.ProjectState.*
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class ProjectStatusTest {
|
||||
@Test
|
||||
fun `test open project with broken state`() {
|
||||
val status = ProjectStatus()
|
||||
status.markDirty(10) as Dirty
|
||||
status.markModified(20) as Dirty
|
||||
assertFalse(status.isUpToDate())
|
||||
status.markSynchronized(30) as Synchronized
|
||||
assertTrue(status.isUpToDate())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test generate project with broken state`() {
|
||||
val status = ProjectStatus()
|
||||
status.markModified(10) as Modified
|
||||
status.markDirty(20) as Dirty
|
||||
assertFalse(status.isUpToDate())
|
||||
status.markSynchronized(30) as Synchronized
|
||||
assertTrue(status.isUpToDate())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test generate project with lag and broken state`() {
|
||||
val status = ProjectStatus()
|
||||
status.markDirty(10) as Dirty
|
||||
assertFalse(status.isUpToDate())
|
||||
status.markSynchronized(30) as Synchronized
|
||||
assertTrue(status.isUpToDate())
|
||||
status.markModified(20) as Synchronized
|
||||
assertTrue(status.isUpToDate())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test delayed modification event`() {
|
||||
val status = ProjectStatus()
|
||||
status.markSynchronized(20) as Synchronized
|
||||
status.markModified(10) as Synchronized
|
||||
assertTrue(status.isUpToDate())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test delayed invalidation event`() {
|
||||
val status = ProjectStatus()
|
||||
status.markSynchronized(20) as Synchronized
|
||||
status.markDirty(10) as Synchronized
|
||||
assertTrue(status.isUpToDate())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test common sample`() {
|
||||
val status = ProjectStatus()
|
||||
status.markModified(10) as Modified
|
||||
status.markModified(20) as Modified
|
||||
status.markModified(30) as Modified
|
||||
assertFalse(status.isUpToDate())
|
||||
status.markSynchronized(40) as Synchronized
|
||||
assertTrue(status.isUpToDate())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test revert changes`() {
|
||||
val status = ProjectStatus()
|
||||
status.markModified(10) as Modified
|
||||
status.markReverted(20) as Reverted
|
||||
assertTrue(status.isUpToDate())
|
||||
status.markSynchronized(30) as Synchronized
|
||||
assertTrue(status.isUpToDate())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test revert dirty changes`() {
|
||||
val status = ProjectStatus()
|
||||
status.markModified(10) as Modified
|
||||
status.markDirty(20) as Dirty
|
||||
status.markReverted(30) as Dirty
|
||||
assertFalse(status.isUpToDate())
|
||||
status.markSynchronized(40) as Synchronized
|
||||
assertTrue(status.isUpToDate())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test modification after revert event`() {
|
||||
val status = ProjectStatus()
|
||||
status.markModified(10) as Modified
|
||||
status.markReverted(20) as Reverted
|
||||
status.markModified(30) as Modified
|
||||
assertFalse(status.isUpToDate())
|
||||
status.markSynchronized(40) as Synchronized
|
||||
assertTrue(status.isUpToDate())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user