9f1fd16ca1731e2dfac10b6ef52d4ef4d7d803e6
[idea/community.git] / python / educational-core / course-creator / testSrc / com / jetbrains / edu / coursecreator / CCTestCase.java
1 package com.jetbrains.edu.coursecreator;
2
3 import com.intellij.openapi.application.ApplicationManager;
4 import com.intellij.openapi.application.PathManager;
5 import com.intellij.openapi.application.Result;
6 import com.intellij.openapi.command.WriteCommandAction;
7 import com.intellij.openapi.diagnostic.Logger;
8 import com.intellij.openapi.editor.Document;
9 import com.intellij.openapi.editor.EditorFactory;
10 import com.intellij.openapi.editor.markup.MarkupModel;
11 import com.intellij.openapi.editor.markup.RangeHighlighter;
12 import com.intellij.openapi.fileEditor.FileDocumentManager;
13 import com.intellij.openapi.util.Pair;
14 import com.intellij.openapi.util.TextRange;
15 import com.intellij.openapi.util.io.FileUtil;
16 import com.intellij.openapi.vfs.LocalFileSystem;
17 import com.intellij.openapi.vfs.VirtualFile;
18 import com.intellij.testFramework.EditorTestUtil;
19 import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
20 import com.jetbrains.edu.learning.StudyTaskManager;
21 import com.jetbrains.edu.learning.courseFormat.*;
22 import org.jetbrains.annotations.NotNull;
23 import org.jetbrains.annotations.Nullable;
24 import org.junit.ComparisonFailure;
25
26 import java.io.File;
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32
33 public abstract class CCTestCase extends LightPlatformCodeInsightFixtureTestCase {
34   private static final Logger LOG = Logger.getInstance(CCTestCase.class);
35
36   @Nullable
37   public static RangeHighlighter getHighlighter(MarkupModel model, AnswerPlaceholder placeholder) {
38     for (RangeHighlighter highlighter : model.getAllHighlighters()) {
39       int endOffset = placeholder.getOffset() + placeholder.getRealLength();
40       if (highlighter.getStartOffset() == placeholder.getOffset() && highlighter.getEndOffset() == endOffset) {
41         return highlighter;
42       }
43     }
44     return null;
45   }
46
47   protected static void checkHighlighters(TaskFile taskFile, MarkupModel markupModel) {
48     for (AnswerPlaceholder answerPlaceholder : taskFile.getAnswerPlaceholders()) {
49       if (getHighlighter(markupModel, answerPlaceholder) == null) {
50         throw new AssertionError("No highlighter for placeholder: " + CCTestsUtil.getPlaceholderPresentation(answerPlaceholder));
51       }
52     }
53   }
54
55   public void checkByFile(TaskFile taskFile, String fileName, boolean useLength) {
56     Pair<Document, List<AnswerPlaceholder>> placeholders = getPlaceholders(fileName, useLength, true);
57     String message = "Placeholders don't match";
58     if (taskFile.getAnswerPlaceholders().size() != placeholders.second.size()) {
59       throw new ComparisonFailure(message,
60                                   CCTestsUtil.getPlaceholdersPresentation(taskFile.getAnswerPlaceholders()),
61                                   CCTestsUtil.getPlaceholdersPresentation(placeholders.second));
62     }
63     for (AnswerPlaceholder answerPlaceholder : placeholders.getSecond()) {
64       AnswerPlaceholder placeholder = taskFile.getAnswerPlaceholder(answerPlaceholder.getOffset());
65       if (!CCTestsUtil.comparePlaceholders(placeholder, answerPlaceholder)) {
66         throw new ComparisonFailure(message,
67                                     CCTestsUtil.getPlaceholdersPresentation(taskFile.getAnswerPlaceholders()),
68                                     CCTestsUtil.getPlaceholdersPresentation(placeholders.second));
69       }
70     }
71   }
72
73   @Override
74   protected String getTestDataPath() {
75     //TODO: rewrite to work for plugin
76     return new File(PathManager.getHomePath(), "community/python/educational-core/course-creator/testData").getPath();
77   }
78
79   @Override
80   protected void setUp() throws Exception {
81     super.setUp();
82     Course course = new Course();
83     course.setName("test course");
84     StudyTaskManager.getInstance(getProject()).setCourse(course);
85
86     Lesson lesson = new Lesson();
87     lesson.setName("lesson1");
88     Task task = new Task();
89     task.setName("task1");
90     task.setIndex(1);
91     lesson.addTask(task);
92     lesson.setIndex(1);
93     course.getLessons().add(lesson);
94     course.setCourseMode(CCUtils.COURSE_MODE);
95     course.initCourse(false);
96     ApplicationManager.getApplication().runWriteAction(new Runnable() {
97       @Override
98       public void run() {
99         try {
100           VirtualFile lesson1 = myFixture.getProject().getBaseDir().createChildDirectory(this, "lesson1");
101           lesson1.createChildDirectory(this, "task1");
102         }
103         catch (IOException e) {
104           //ignore
105         }
106       }
107     });
108   }
109
110   protected VirtualFile configureByTaskFile(String name) {
111     VirtualFile file =
112       myFixture.copyFileToProject(name, FileUtil.join(getProject().getBasePath(), "lesson1", "task1", name));
113     myFixture.configureFromExistingVirtualFile(file);
114
115     Document document = FileDocumentManager.getInstance().getDocument(file);
116     Task task = StudyTaskManager.getInstance(getProject()).getCourse().getLessons().get(0).getTaskList().get(0);
117     TaskFile taskFile = new TaskFile();
118     taskFile.setTask(task);
119     task.getTaskFiles().put(name, taskFile);
120     for (AnswerPlaceholder placeholder : getPlaceholders(document, false)) {
121       taskFile.addAnswerPlaceholder(placeholder);
122     }
123     taskFile.sortAnswerPlaceholders();
124     return file;
125   }
126
127   private static List<AnswerPlaceholder> getPlaceholders(Document document, boolean useLength) {
128     final List<AnswerPlaceholder> placeholders = new ArrayList<>();
129     new WriteCommandAction(null) {
130       @Override
131       protected void run(@NotNull Result result) {
132         final String openingTagRx = "<placeholder( taskText=\"(.+?)\")?( possibleAnswer=\"(.+?)\")?( hint=\"(.+?)\")?>";
133         final String closingTagRx = "</placeholder>";
134         CharSequence text = document.getCharsSequence();
135         final Matcher openingMatcher = Pattern.compile(openingTagRx).matcher(text);
136         final Matcher closingMatcher = Pattern.compile(closingTagRx).matcher(text);
137         int pos = 0;
138         while (openingMatcher.find(pos)) {
139           AnswerPlaceholder answerPlaceholder = new AnswerPlaceholder();
140           answerPlaceholder.setUseLength(useLength);
141           String taskText = openingMatcher.group(2);
142           if (taskText != null) {
143             answerPlaceholder.setTaskText(taskText);
144             answerPlaceholder.setLength(taskText.length());
145           }
146           String possibleAnswer = openingMatcher.group(4);
147           if (possibleAnswer != null) {
148             answerPlaceholder.setPossibleAnswer(possibleAnswer);
149           }
150           String hint = openingMatcher.group(6);
151           if (hint != null) {
152             answerPlaceholder.setHint(hint);
153           }
154           answerPlaceholder.setOffset(openingMatcher.start());
155           if (!closingMatcher.find(openingMatcher.end())) {
156             LOG.error("No matching closing tag found");
157           }
158           if (useLength) {
159             answerPlaceholder.setLength(closingMatcher.start() - openingMatcher.end());
160           } else {
161             if (possibleAnswer == null) {
162               answerPlaceholder.setPossibleAnswer(document.getText(TextRange.create(openingMatcher.end(), closingMatcher.start())));
163             }
164           }
165           document.deleteString(closingMatcher.start(), closingMatcher.end());
166           document.deleteString(openingMatcher.start(), openingMatcher.end());
167           placeholders.add(answerPlaceholder);
168           pos = answerPlaceholder.getOffset() + answerPlaceholder.getRealLength();
169         }
170       }
171     }.execute();
172     return placeholders;
173   }
174
175   public Pair<Document, List<AnswerPlaceholder>> getPlaceholders(String name) {
176     return getPlaceholders(name, true, false);
177   }
178
179   public Pair<Document, List<AnswerPlaceholder>> getPlaceholders(String name, boolean useLength, boolean removeMarkers) {
180     VirtualFile resultFile = LocalFileSystem.getInstance().findFileByPath(getTestDataPath() + "/" + name);
181     Document document = FileDocumentManager.getInstance().getDocument(resultFile);
182     Document tempDocument = EditorFactory.getInstance().createDocument(document.getCharsSequence());
183     if (removeMarkers) {
184       EditorTestUtil.extractCaretAndSelectionMarkers(tempDocument);
185     }
186     List<AnswerPlaceholder> placeholders = getPlaceholders(tempDocument, useLength);
187     return Pair.create(tempDocument, placeholders);
188   }
189
190   @Override
191   protected boolean shouldContainTempFiles() {
192     return false;
193   }
194 }
195
196