1 package com.jetbrains.edu.coursecreator;
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;
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;
33 public abstract class CCTestCase extends LightPlatformCodeInsightFixtureTestCase {
34 private static final Logger LOG = Logger.getInstance(CCTestCase.class);
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) {
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));
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));
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));
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();
80 protected void setUp() throws Exception {
82 Course course = new Course();
83 course.setName("test course");
84 StudyTaskManager.getInstance(getProject()).setCourse(course);
86 Lesson lesson = new Lesson();
87 lesson.setName("lesson1");
88 Task task = new Task();
89 task.setName("task1");
93 course.getLessons().add(lesson);
94 course.setCourseMode(CCUtils.COURSE_MODE);
95 course.initCourse(false);
96 ApplicationManager.getApplication().runWriteAction(new Runnable() {
100 VirtualFile lesson1 = myFixture.getProject().getBaseDir().createChildDirectory(this, "lesson1");
101 lesson1.createChildDirectory(this, "task1");
103 catch (IOException e) {
110 protected VirtualFile configureByTaskFile(String name) {
112 myFixture.copyFileToProject(name, FileUtil.join(getProject().getBasePath(), "lesson1", "task1", name));
113 myFixture.configureFromExistingVirtualFile(file);
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);
123 taskFile.sortAnswerPlaceholders();
127 private static List<AnswerPlaceholder> getPlaceholders(Document document, boolean useLength) {
128 final List<AnswerPlaceholder> placeholders = new ArrayList<>();
129 new WriteCommandAction(null) {
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);
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());
146 String possibleAnswer = openingMatcher.group(4);
147 if (possibleAnswer != null) {
148 answerPlaceholder.setPossibleAnswer(possibleAnswer);
150 String hint = openingMatcher.group(6);
152 answerPlaceholder.setHint(hint);
154 answerPlaceholder.setOffset(openingMatcher.start());
155 if (!closingMatcher.find(openingMatcher.end())) {
156 LOG.error("No matching closing tag found");
159 answerPlaceholder.setLength(closingMatcher.start() - openingMatcher.end());
161 if (possibleAnswer == null) {
162 answerPlaceholder.setPossibleAnswer(document.getText(TextRange.create(openingMatcher.end(), closingMatcher.start())));
165 document.deleteString(closingMatcher.start(), closingMatcher.end());
166 document.deleteString(openingMatcher.start(), openingMatcher.end());
167 placeholders.add(answerPlaceholder);
168 pos = answerPlaceholder.getOffset() + answerPlaceholder.getRealLength();
175 public Pair<Document, List<AnswerPlaceholder>> getPlaceholders(String name) {
176 return getPlaceholders(name, true, false);
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());
184 EditorTestUtil.extractCaretAndSelectionMarkers(tempDocument);
186 List<AnswerPlaceholder> placeholders = getPlaceholders(tempDocument, useLength);
187 return Pair.create(tempDocument, placeholders);
191 protected boolean shouldContainTempFiles() {