diff options
Diffstat (limited to 'python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCRunTests.java')
-rw-r--r-- | python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCRunTests.java | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCRunTests.java b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCRunTests.java new file mode 100644 index 000000000000..d078972e3f56 --- /dev/null +++ b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCRunTests.java @@ -0,0 +1,284 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * 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 org.jetbrains.plugins.coursecreator; + +import com.intellij.execution.*; +import com.intellij.execution.actions.ConfigurationContext; +import com.intellij.execution.configurations.ConfigurationFactory; +import com.intellij.execution.executors.DefaultRunExecutor; +import com.intellij.icons.AllIcons; +import com.intellij.ide.projectView.ProjectView; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.util.containers.HashMap; +import com.jetbrains.python.run.PythonConfigurationType; +import com.jetbrains.python.run.PythonRunConfiguration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.coursecreator.actions.CreateCourseArchive; +import org.jetbrains.plugins.coursecreator.format.*; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Map; + +public class CCRunTests extends AnAction { + private static final Logger LOG = Logger.getInstance(CCRunTests.class.getName()); + + public CCRunTests() { + getTemplatePresentation().setIcon(AllIcons.Actions.Lightning); + } + + @Override + public void update(@NotNull AnActionEvent e) { + Presentation presentation = e.getPresentation(); + final ConfigurationContext context = ConfigurationContext.getFromContext(e.getDataContext()); + Location location = context.getLocation(); + if (location == null) { + return; + } + PsiElement psiElement = location.getPsiElement(); + PsiFile psiFile = psiElement.getContainingFile(); + if (psiFile != null && psiFile.getName().contains(".answer")) { + presentation.setEnabled(true); + presentation.setText("Run tests from '" + psiFile.getName() + "'"); + } + else { + presentation.setEnabled(false); + } + } + + public void actionPerformed(@NotNull AnActionEvent e) { + final ConfigurationContext context = ConfigurationContext.getFromContext(e.getDataContext()); + run(context); + } + + public static void run(final @NotNull ConfigurationContext context) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + final Project project = context.getProject(); + PsiElement location = context.getPsiLocation(); + final Course course = CCProjectService.getInstance(project).getCourse(); + if (course == null || location == null) { + return; + } + PsiFile psiFile = location.getContainingFile(); + final VirtualFile virtualFile = psiFile.getVirtualFile(); + final VirtualFile taskDir = virtualFile.getParent(); + if (taskDir == null) { + return; + } + final Task task = getTask(course, taskDir); + if (task == null) { + return; + } + for (final Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) { + final String name = entry.getKey(); + createTestEnvironment(taskDir, name, entry.getValue(), project); + VirtualFile testFile = taskDir.findChild("tests.py"); + if (testFile == null) { + return; + } + executeTests(project, virtualFile, taskDir, testFile); + clearTestEnvironment(taskDir, project); + } + } + }); + } + + private static void createTestEnvironment(@NotNull final VirtualFile taskDir, final String fileName, @NotNull final TaskFile taskFile, + @NotNull final Project project) { + try { + String answerFileName = FileUtil.getNameWithoutExtension(fileName) + ".answer"; + final VirtualFile answerFile = taskDir.findChild(answerFileName); + if (answerFile == null) { + LOG.debug("could not find answer file " + answerFileName); + return; + } + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + final FileDocumentManager documentManager = FileDocumentManager.getInstance(); + documentManager.saveAllDocuments(); + } + }); + answerFile.copy(project, taskDir, fileName); + flushWindows(taskFile, answerFile); + createResourceFiles(answerFile, project); + } + catch (IOException e) { + LOG.error(e); + } + } + + private static void clearTestEnvironment(@NotNull final VirtualFile taskDir, @NotNull final Project project) { + try { + VirtualFile ideaDir = project.getBaseDir().findChild(".idea"); + if (ideaDir == null) { + LOG.debug("idea directory doesn't exist"); + return; + } + VirtualFile courseResourceDir = ideaDir.findChild("course"); + if (courseResourceDir == null) { + return; + } + courseResourceDir.delete(project); + VirtualFile[] taskDirChildren = taskDir.getChildren(); + for (VirtualFile file : taskDirChildren) { + if (file.getName().contains("_windows")) { + file.delete(project); + } + if (CCProjectService.getInstance(project).isTaskFile(file)) { + file.delete(project); + } + } + } + catch (IOException e) { + LOG.error(e); + } + } + + private static void executeTests(@NotNull final Project project, + @NotNull final VirtualFile virtualFile, + @NotNull final VirtualFile taskDir, + @NotNull final VirtualFile testFile) { + final ConfigurationFactory factory = PythonConfigurationType.getInstance().getConfigurationFactories()[0]; + final RunnerAndConfigurationSettings settings = + RunManager.getInstance(project).createRunConfiguration("test", factory); + + final PythonRunConfiguration configuration = (PythonRunConfiguration)settings.getConfiguration(); + configuration.setScriptName(testFile.getPath()); + VirtualFile userFile = taskDir.findChild(virtualFile.getNameWithoutExtension() + ".py"); + if (userFile == null) { + return; + } + VirtualFile ideaDir = project.getBaseDir().findChild(".idea"); + if (ideaDir == null) { + return; + } + VirtualFileManager.getInstance().refreshWithoutFileWatcher(true); + ProjectView.getInstance(project).refresh(); + VirtualFile courseDir = ideaDir.findChild("course"); + if (courseDir == null) { + return; + } + configuration.setScriptParameters(courseDir.getPath() + " " + userFile.getPath()); + Executor executor = DefaultRunExecutor.getRunExecutorInstance(); + ProgramRunnerUtil.executeConfiguration(project, settings, executor); + } + + @Nullable + private static Task getTask(@NotNull final Course course, @NotNull final VirtualFile taskDir) { + if (!taskDir.getName().contains("task")) { + return null; + } + VirtualFile lessonDir = taskDir.getParent(); + if (lessonDir == null || !lessonDir.getName().contains("lesson")) { + return null; + } + Lesson lesson = course.getLesson(lessonDir.getName()); + if (lesson == null) { + return null; + } + return lesson.getTask(taskDir.getName()); + } + + + //some tests could compare task files after user modifications with initial task files + private static void createResourceFiles(@NotNull final VirtualFile file, @NotNull final Project project) { + VirtualFile taskDir = file.getParent(); + int index = CCProjectService.getIndex(taskDir.getName(), "task"); + VirtualFile lessonDir = taskDir.getParent(); + int lessonIndex = CCProjectService.getIndex(lessonDir.getName(), "lesson"); + Course course = CCProjectService.getInstance(project).getCourse(); + if (course == null) { + return; + } + VirtualFile ideaDir = project.getBaseDir().findChild(".idea"); + assert ideaDir != null; + try { + VirtualFile taskResourceDir = ideaDir.createChildDirectory(project, "course").createChildDirectory(project, lessonDir.getName()) + .createChildDirectory(project, taskDir.getName()); + if (CCProjectService.indexIsValid(lessonIndex, course.getLessons())) { + Lesson lesson = course.getLessons().get(lessonIndex); + if (CCProjectService.indexIsValid(index, lesson.getTaskList())) { + Task task = lesson.getTaskList().get(index); + HashMap<TaskFile, TaskFile> taskFilesCopy = new HashMap<TaskFile, TaskFile>(); + for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) { + CreateCourseArchive.createUserFile(project, taskFilesCopy, taskResourceDir, taskDir, entry); + CreateCourseArchive.resetTaskFiles(taskFilesCopy); + } + } + } + } + catch (IOException e) { + LOG.error(e); + } + } + + @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") + public static VirtualFile flushWindows(TaskFile taskFile, VirtualFile file) { + VirtualFile taskDir = file.getParent(); + VirtualFile fileWindows = null; + final Document document = FileDocumentManager.getInstance().getDocument(file); + if (document == null) { + LOG.debug("Couldn't flush windows"); + return null; + } + if (taskDir != null) { + String name = file.getNameWithoutExtension() + "_windows"; + PrintWriter printWriter = null; + try { + fileWindows = taskDir.createChildData(taskFile, name); + printWriter = new PrintWriter(new FileOutputStream(fileWindows.getPath())); + for (TaskWindow taskWindow : taskFile.getTaskWindows()) { + int start = taskWindow.getRealStartOffset(document); + String windowDescription = document.getText(new TextRange(start, start + taskWindow.getReplacementLength())); + printWriter.println("#study_plugin_window = " + windowDescription); + } + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + FileDocumentManager.getInstance().saveDocument(document); + } + }); + } + catch (IOException e) { + LOG.error(e); + } + finally { + if (printWriter != null) { + printWriter.close(); + } + } + } + return fileWindows; + } +} |