578e2084f7fba1d0b3c8da4d5e07f8a08aeee70c
[idea/community.git] / platform / platform-tests / testSrc / com / intellij / openapi / fileTypes / impl / FileTypesTest.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.fileTypes.impl;
17
18 import com.intellij.ide.highlighter.ArchiveFileType;
19 import com.intellij.ide.highlighter.ModuleFileType;
20 import com.intellij.ide.highlighter.ProjectFileType;
21 import com.intellij.ide.highlighter.custom.SyntaxTable;
22 import com.intellij.openapi.application.ApplicationManager;
23 import com.intellij.openapi.command.WriteCommandAction;
24 import com.intellij.openapi.diagnostic.FrequentEventDetector;
25 import com.intellij.openapi.editor.Document;
26 import com.intellij.openapi.extensions.Extensions;
27 import com.intellij.openapi.fileEditor.FileDocumentManager;
28 import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
29 import com.intellij.openapi.fileTypes.*;
30 import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
31 import com.intellij.openapi.util.*;
32 import com.intellij.openapi.util.io.ByteSequence;
33 import com.intellij.openapi.util.io.FileUtil;
34 import com.intellij.openapi.util.text.StringUtil;
35 import com.intellij.openapi.vfs.CharsetToolkit;
36 import com.intellij.openapi.vfs.LocalFileSystem;
37 import com.intellij.openapi.vfs.PersistentFSConstants;
38 import com.intellij.openapi.vfs.VirtualFile;
39 import com.intellij.psi.PsiBinaryFile;
40 import com.intellij.psi.PsiDocumentManager;
41 import com.intellij.psi.PsiFile;
42 import com.intellij.psi.PsiPlainTextFile;
43 import com.intellij.psi.impl.PsiManagerEx;
44 import com.intellij.testFramework.PlatformTestCase;
45 import com.intellij.testFramework.PlatformTestUtil;
46 import com.intellij.testFramework.VfsTestUtil;
47 import com.intellij.util.PatternUtil;
48 import com.intellij.util.containers.ContainerUtil;
49 import com.intellij.util.ui.UIUtil;
50 import junit.framework.TestCase;
51 import org.jdom.Element;
52 import org.jetbrains.annotations.NotNull;
53 import org.jetbrains.annotations.Nullable;
54
55 import javax.swing.*;
56 import java.io.File;
57 import java.io.IOException;
58 import java.util.*;
59 import java.util.concurrent.atomic.AtomicReference;
60 import java.util.regex.Pattern;
61
62 @SuppressWarnings("ConstantConditions")
63 public class FileTypesTest extends PlatformTestCase {
64   private FileTypeManagerImpl myFileTypeManager;
65   private String myOldIgnoredFilesList;
66
67   @Override
68   protected void setUp() throws Exception {
69     super.setUp();
70     myFileTypeManager = (FileTypeManagerImpl)FileTypeManagerEx.getInstanceEx();
71     myOldIgnoredFilesList = myFileTypeManager.getIgnoredFilesList();
72     FileTypeManagerImpl.reDetectAsync(true);
73   }
74
75   @Override
76   protected void tearDown() throws Exception {
77     FileTypeManagerImpl.reDetectAsync(false);
78     ApplicationManager.getApplication().runWriteAction(() -> myFileTypeManager.setIgnoredFilesList(myOldIgnoredFilesList));
79     super.tearDown();
80   }
81
82   public void testMaskExclude() {
83     final String pattern1 = "a*b.c?d";
84     final String pattern2 = "xxx";
85     ApplicationManager.getApplication().runWriteAction(() -> myFileTypeManager.setIgnoredFilesList(pattern1 + ";" + pattern2));
86     checkIgnored("ab.cxd");
87     checkIgnored("axb.cxd");
88     checkIgnored("xxx");
89     checkNotIgnored("ax.cxx");
90     checkNotIgnored("ab.cd");
91     checkNotIgnored("ab.c__d");
92     checkNotIgnored("xxxx");
93     checkNotIgnored("xx");
94     assertTrue(myFileTypeManager.isIgnoredFilesListEqualToCurrent(pattern2 + ";" + pattern1));
95     assertFalse(myFileTypeManager.isIgnoredFilesListEqualToCurrent(pattern2 + ";" + "ab.c*d"));
96   }
97
98   public void testExcludePerformance() {
99     ApplicationManager.getApplication().runWriteAction(() -> myFileTypeManager.setIgnoredFilesList("1*2;3*4;5*6;7*8;9*0;*1;*3;*5;*6;7*;*8*"));
100     final String[] names = new String[100];
101     for (int i = 0; i < names.length; i++) {
102       String name = String.valueOf(i % 10 * 10 + i * 100 + i + 1);
103       names[i] = name + name + name + name;
104     }
105     PlatformTestUtil.startPerformanceTest("ignore perf", 700, () -> {
106       for (int i=0;i<1000;i++) {
107         for (String name : names) {
108           myFileTypeManager.isFileIgnored(name);
109         }
110       }
111     }).assertTiming();
112   }
113
114   public void testMaskToPattern() {
115     for (char i = 0; i < 256; i++) {
116       if (i == '?' || i == '*') continue;
117       String str = "x" + i + "y";
118       assertTrue("char: " + i + "(" + (int)i + ")", PatternUtil.fromMask(str).matcher(str).matches());
119     }
120     String allSymbols = "+.\\*/^?$[]()";
121     assertTrue(PatternUtil.fromMask(allSymbols).matcher(allSymbols).matches());
122     Pattern pattern = PatternUtil.fromMask("?\\?/*");
123     assertTrue(pattern.matcher("a\\b/xyz").matches());
124     assertFalse(pattern.matcher("x/a\\b").matches());
125   }
126
127   public void testAddNewExtension() throws Exception {
128     FileTypeAssocTable<FileType> associations = new FileTypeAssocTable<>();
129     associations.addAssociation(FileTypeManager.parseFromString("*.java"), FileTypes.ARCHIVE);
130     associations.addAssociation(FileTypeManager.parseFromString("*.xyz"), StdFileTypes.XML);
131     associations.addAssociation(FileTypeManager.parseFromString("SomeSpecial*.java"), StdFileTypes.XML); // patterns should have precedence over extensions
132     assertEquals(StdFileTypes.XML, associations.findAssociatedFileType("sample.xyz"));
133     assertEquals(StdFileTypes.XML, associations.findAssociatedFileType("SomeSpecialFile.java"));
134     checkNotAssociated(StdFileTypes.XML, "java", associations);
135     checkNotAssociated(StdFileTypes.XML, "iws", associations);
136   }
137
138   public void testIgnoreOrder() {
139     final FileTypeManagerEx manager = FileTypeManagerEx.getInstanceEx();
140     ApplicationManager.getApplication().runWriteAction(() -> manager.setIgnoredFilesList("a;b;"));
141     assertEquals("a;b;", manager.getIgnoredFilesList());
142     ApplicationManager.getApplication().runWriteAction(() -> manager.setIgnoredFilesList("b;a;"));
143     assertEquals("b;a;", manager.getIgnoredFilesList());
144   }
145
146   public void testIgnoredFiles() throws IOException {
147     File file = createTempFile(".svn", "");
148     VirtualFile vFile = getVirtualFile(file);
149     assertTrue(FileTypeManager.getInstance().isFileIgnored(vFile));
150     VfsTestUtil.deleteFile(vFile);
151
152     file = createTempFile("a.txt", "");
153     vFile = getVirtualFile(file);
154     assertFalse(FileTypeManager.getInstance().isFileIgnored(vFile));
155   }
156
157
158   @SuppressWarnings("deprecation")
159   private static void checkNotAssociated(FileType fileType, String extension, FileTypeAssocTable<FileType> associations) {
160     assertFalse(Arrays.asList(associations.getAssociatedExtensions(fileType)).contains(extension));
161   }
162
163   private void checkNotIgnored(String fileName) {
164     assertFalse(myFileTypeManager.isFileIgnored(fileName));
165   }
166
167   private void checkIgnored(String fileName) {
168     assertTrue(myFileTypeManager.isFileIgnored(fileName));
169   }
170
171   public void testAutoDetected() throws IOException {
172     File dir = createTempDirectory();
173     File file = FileUtil.createTempFile(dir, "x", "xxx_xx_xx", true);
174     FileUtil.writeToFile(file, "xxx xxx xxx xxx");
175     VirtualFile virtualFile = getVirtualFile(file);
176     assertNotNull(virtualFile);
177     PsiFile psi = getPsiManager().findFile(virtualFile);
178     assertTrue(psi instanceof PsiPlainTextFile);
179     assertEquals(FileTypes.PLAIN_TEXT, virtualFile.getFileType());
180   }
181
182   public void testAutoDetectedWhenDocumentWasCreated() throws IOException {
183     File dir = createTempDirectory();
184     File file = FileUtil.createTempFile(dir, "x", "xxx_xx_xx", true);
185     FileUtil.writeToFile(file, "xxx xxx xxx xxx");
186     VirtualFile virtualFile = getVirtualFile(file);
187     assertNotNull(virtualFile);
188     Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
189     assertNotNull(document);
190     assertEquals(FileTypes.PLAIN_TEXT, virtualFile.getFileType());
191   }
192
193   public void testAutoDetectionShouldNotBeOverEager() throws IOException {
194     File dir = createTempDirectory();
195     File file = FileUtil.createTempFile(dir, "x", "xxx_xx_xx", true);
196     FileUtil.writeToFile(file, "xxx xxx xxx xxx");
197     VirtualFile virtualFile = getVirtualFile(file);
198     assertNotNull(virtualFile);
199     TestCase.assertEquals(PlainTextFileType.INSTANCE, virtualFile.getFileType());
200   }
201
202   public void testAutoDetectEmptyFile() throws IOException {
203     File dir = createTempDirectory();
204     File file = FileUtil.createTempFile(dir, "x", "xxx_xx_xx", true);
205     VirtualFile virtualFile = getVirtualFile(file);
206     assertNotNull(virtualFile);
207     assertEquals(FileTypes.UNKNOWN, virtualFile.getFileType());
208     PsiFile psi = getPsiManager().findFile(virtualFile);
209     assertTrue(psi instanceof PsiBinaryFile);
210     assertEquals(FileTypes.UNKNOWN, virtualFile.getFileType());
211
212     setBinaryContent(virtualFile, "xxxxxxx".getBytes(CharsetToolkit.UTF8_CHARSET));
213     assertEquals(FileTypes.PLAIN_TEXT, virtualFile.getFileType());
214     PsiFile after = getPsiManager().findFile(virtualFile);
215     assertNotSame(psi, after);
216     assertFalse(psi.isValid());
217     assertTrue(after.isValid());
218     assertTrue(after instanceof PsiPlainTextFile);
219   }
220
221   public void testAutoDetectTextFileFromContents() throws IOException {
222     File dir = createTempDirectory();
223     VirtualFile vDir = getVirtualFile(dir);
224     VirtualFile vFile = createChildData(vDir, "test.xxxxxxxx");
225     setFileText(vFile, "text");
226     PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
227
228     assertEquals(PlainTextFileType.INSTANCE, vFile.getFileType()); // type autodetected during indexing
229
230     PsiFile psiFile = PsiManagerEx.getInstanceEx(getProject()).getFileManager().findFile(vFile); // autodetect text file if needed
231     assertNotNull(psiFile);
232     assertEquals(PlainTextFileType.INSTANCE, psiFile.getFileType());
233   }
234
235   public void testAutoDetectTextFileEvenOutsideTheProject() throws IOException {
236     File d = createTempDirectory();
237     File f = new File(d, "xx.asfdasdfas");
238     FileUtil.writeToFile(f, "asdasdasdfafds");
239     VirtualFile vFile = getVirtualFile(f);
240
241     assertEquals(PlainTextFileType.INSTANCE, vFile.getFileType());
242   }
243
244   public void test7BitBinaryIsNotText() throws IOException {
245     File d = createTempDirectory();
246     File f = new File(d, "xx.asfdasdfas");
247     byte[] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'x', 'a', 'b'};
248     assertEquals(CharsetToolkit.GuessedEncoding.BINARY, new CharsetToolkit(bytes).guessFromContent(bytes.length));
249     FileUtil.writeToFile(f, bytes);
250
251     VirtualFile vFile = getVirtualFile(f);
252
253     assertEquals(UnknownFileType.INSTANCE, vFile.getFileType());
254   }
255
256   public void test7BitIsText() throws IOException {
257     File d = createTempDirectory();
258     File f = new File(d, "xx.asfdasdfas");
259     byte[] bytes = {9, 10, 13, 'x', 'a', 'b'};
260     assertEquals(CharsetToolkit.GuessedEncoding.SEVEN_BIT, new CharsetToolkit(bytes).guessFromContent(bytes.length));
261     FileUtil.writeToFile(f, bytes);
262     VirtualFile vFile = getVirtualFile(f);
263
264     assertEquals(PlainTextFileType.INSTANCE, vFile.getFileType());
265   }
266
267   public void testReDetectOnContentsChange() throws IOException {
268     final FileTypeRegistry fileTypeManager = FileTypeRegistry.getInstance();
269     assertTrue(fileTypeManager.getClass().getName(), fileTypeManager instanceof FileTypeManagerImpl);
270     FileType fileType = fileTypeManager.getFileTypeByFileName("x" + ModuleFileType.DOT_DEFAULT_EXTENSION);
271     assertTrue(fileType.toString(), fileType instanceof ModuleFileType);
272     fileType = fileTypeManager.getFileTypeByFileName("x" + ProjectFileType.DOT_DEFAULT_EXTENSION);
273     assertTrue(fileType.toString(), fileType instanceof ProjectFileType);
274     FileType module = fileTypeManager.findFileTypeByName("IDEA_MODULE");
275     assertNotNull(module);
276     assertFalse(module.equals(PlainTextFileType.INSTANCE));
277     FileType project = fileTypeManager.findFileTypeByName("IDEA_PROJECT");
278     assertNotNull(project);
279     assertFalse(project.equals(PlainTextFileType.INSTANCE));
280
281     final Set<VirtualFile> detectorCalled = ContainerUtil.newConcurrentSet();
282     FileTypeRegistry.FileTypeDetector detector = new FileTypeRegistry.FileTypeDetector() {
283       @Nullable
284       @Override
285       public FileType detect(@NotNull VirtualFile file, @NotNull ByteSequence firstBytes, @Nullable CharSequence firstCharsIfText) {
286         detectorCalled.add(file);
287         String text = firstCharsIfText.toString();
288         FileType result = text.startsWith("TYPE:") ? fileTypeManager.findFileTypeByName(StringUtil.trimStart(text, "TYPE:")) : null;
289         log("T: my detector run for "+file.getName()+"; result: "+(result == null ? null : result.getName()));
290         return result;
291       }
292
293       @Override
294       public int getVersion() {
295         return 0;
296       }
297     };
298     Extensions.getRootArea().getExtensionPoint(FileTypeRegistry.FileTypeDetector.EP_NAME).registerExtension(detector);
299     myFileTypeManager.toLog = true;
300
301     try {
302       log("T: ------ akjdhfksdjgf");
303       File f = createTempFile("xx.asfdasdfas", "akjdhfksdjgf");
304       VirtualFile vFile = getVirtualFile(f);
305       ensureRedetected(vFile, detectorCalled);
306       assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof PlainTextFileType);
307
308       log("T: ------ TYPE:IDEA_MODULE");
309       setFileText(vFile,  "TYPE:IDEA_MODULE");
310       ensureRedetected(vFile, detectorCalled);
311       assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof ModuleFileType);
312
313       log("T: ------ TYPE:IDEA_PROJECT");
314       setFileText(vFile, "TYPE:IDEA_PROJECT");
315       ensureRedetected(vFile, detectorCalled);
316       assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof ProjectFileType);
317       log("T: ------");
318     }
319     finally {
320       Extensions.getRootArea().getExtensionPoint(FileTypeRegistry.FileTypeDetector.EP_NAME).unregisterExtension(detector);
321       myFileTypeManager.toLog = false;
322     }
323   }
324
325   private static void log(String message) {
326     System.out.println(message);
327   }
328
329   private void ensureRedetected(VirtualFile vFile, Set<VirtualFile> detectorCalled) {
330     PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
331     log("T: ensureRedetected: commit. re-detect queue: "+myFileTypeManager.dumpReDetectQueue());
332     UIUtil.dispatchAllInvocationEvents();
333     log("T: ensureRedetected: dispatch. re-detect queue: "+ myFileTypeManager.dumpReDetectQueue());
334     myFileTypeManager.drainReDetectQueue();
335     log("T: ensureRedetected: drain. re-detect queue: "+myFileTypeManager.dumpReDetectQueue());
336     UIUtil.dispatchAllInvocationEvents();
337     log("T: ensureRedetected: dispatch");
338     FileType type = vFile.getFileType();
339     log("T: ensureRedetected: getFileType ("+type.getName()+")");
340     assertTrue(detectorCalled.contains(vFile));
341     detectorCalled.clear();
342     log("T: ensureRedetected: clear");
343   }
344
345   public void testReassignedPredefinedFileType() throws Exception {
346     final FileType perlFileType = myFileTypeManager.getFileTypeByFileName("foo.pl");
347     assertEquals("Perl", perlFileType.getName());
348     assertEquals(PlainTextFileType.INSTANCE, myFileTypeManager.getFileTypeByFileName("foo.cgi"));
349     ApplicationManager.getApplication().runWriteAction(() -> myFileTypeManager.associatePattern(perlFileType, "*.cgi"));
350
351     assertEquals(perlFileType, myFileTypeManager.getFileTypeByFileName("foo.cgi"));
352
353     Element element = myFileTypeManager.getState();
354     myFileTypeManager.loadState(element);
355     myFileTypeManager.initComponent();
356     assertEquals(perlFileType, myFileTypeManager.getFileTypeByFileName("foo.cgi"));
357
358     ApplicationManager.getApplication().runWriteAction(() -> myFileTypeManager.removeAssociatedExtension(perlFileType, "*.cgi"));
359
360     myFileTypeManager.clearForTests();
361     myFileTypeManager.initStandardFileTypes();
362     myFileTypeManager.initComponent();
363   }
364
365   public void testRenamedPropertiesToUnknownAndBack() throws Exception {
366     FileType propFileType = myFileTypeManager.getFileTypeByFileName("xx.properties");
367     assertEquals("Properties", propFileType.getName());
368     File file = createTempFile("xx.properties", "xx=yy");
369     VirtualFile vFile = getVirtualFile(file);
370     assertEquals(propFileType, myFileTypeManager.getFileTypeByFile(vFile));
371
372     rename(vFile, "xx.zxmcnbzmxnbc");
373     UIUtil.dispatchAllInvocationEvents();
374     assertEquals(PlainTextFileType.INSTANCE, myFileTypeManager.getFileTypeByFile(vFile));
375
376     rename(vFile, "xx.properties");
377     myFileTypeManager.drainReDetectQueue();
378     for (int i=0; i<100;i++) {
379       PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
380       UIUtil.dispatchAllInvocationEvents();
381
382       assertEquals(propFileType, myFileTypeManager.getFileTypeByFile(vFile));
383       assertEmpty(myFileTypeManager.dumpReDetectQueue());
384     }
385   }
386
387   // for IDEA-114804 File types mapped to text are not remapped when corresponding plugin is installed
388   public void testRemappingToInstalledPluginExtension() throws WriteExternalException, InvalidDataException {
389     ApplicationManager.getApplication().runWriteAction(() -> myFileTypeManager.associatePattern(PlainTextFileType.INSTANCE, "*.fromPlugin"));
390
391     Element element = myFileTypeManager.getState();
392     //String s = JDOMUtil.writeElement(element);
393
394     final AbstractFileType typeFromPlugin = new AbstractFileType(new SyntaxTable());
395     PlatformTestUtil.registerExtension(FileTypeFactory.FILE_TYPE_FACTORY_EP, new FileTypeFactory() {
396       @Override
397       public void createFileTypes(@NotNull FileTypeConsumer consumer) {
398         consumer.consume(typeFromPlugin, "fromPlugin");
399       }
400     }, getTestRootDisposable());
401     myFileTypeManager.initStandardFileTypes();
402     myFileTypeManager.loadState(element);
403
404     myFileTypeManager.initComponent();
405     Map<FileNameMatcher, Pair<FileType, Boolean>> mappings = myFileTypeManager.getRemovedMappings();
406     assertEquals(1, mappings.size());
407     assertEquals(typeFromPlugin, mappings.values().iterator().next().first);
408   }
409
410   public void testPreserveUninstalledPluginAssociations() throws Exception {
411     final FileType typeFromPlugin = new FileType() {
412       @NotNull
413       @Override
414       public String getName() {
415         return "Foo files";
416       }
417
418       @NotNull
419       @Override
420       public String getDescription() {
421         return "";
422       }
423
424       @NotNull
425       @Override
426       public String getDefaultExtension() {
427         return "fromPlugin";
428       }
429
430       @Nullable
431       @Override
432       public Icon getIcon() {
433         return null;
434       }
435
436       @Override
437       public boolean isBinary() {
438         return false;
439       }
440
441       @Override
442       public boolean isReadOnly() {
443         return false;
444       }
445
446       @Nullable
447       @Override
448       public String getCharset(@NotNull VirtualFile file, @NotNull byte[] content) {
449         return null;
450       }
451     };
452     FileTypeFactory factory = new FileTypeFactory() {
453       @Override
454       public void createFileTypes(@NotNull FileTypeConsumer consumer) {
455         consumer.consume(typeFromPlugin);
456       }
457     };
458     Element element = myFileTypeManager.getState();
459     try {
460       myFileTypeManager.clearForTests();
461       Extensions.getRootArea().getExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP).registerExtension(factory);
462       myFileTypeManager.initStandardFileTypes();
463       myFileTypeManager.loadState(element);
464       myFileTypeManager.initComponent();
465
466       ApplicationManager.getApplication().runWriteAction(() -> myFileTypeManager.associatePattern(typeFromPlugin, "*.foo"));
467
468
469       element = myFileTypeManager.getState();
470       //log(JDOMUtil.writeElement(element));
471
472       Extensions.getRootArea().getExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP).unregisterExtension(factory);
473       myFileTypeManager.clearForTests();
474       myFileTypeManager.initStandardFileTypes();
475       myFileTypeManager.loadState(element);
476       myFileTypeManager.initComponent();
477
478       element = myFileTypeManager.getState();
479       //log(JDOMUtil.writeElement(element));
480
481       Extensions.getRootArea().getExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP).registerExtension(factory);
482       myFileTypeManager.clearForTests();
483       myFileTypeManager.initStandardFileTypes();
484       myFileTypeManager.loadState(element);
485       myFileTypeManager.initComponent();
486
487       //element = myFileTypeManager.getState();
488       //log(JDOMUtil.writeElement(element));
489
490       assertEquals(typeFromPlugin, myFileTypeManager.getFileTypeByFileName("foo.foo"));
491     }
492     finally {
493       Extensions.getRootArea().getExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP).unregisterExtension(factory);
494     }
495   }
496
497   // IDEA-139409 Persistent message "File type recognized: File extension *.vm was reassigned to VTL"
498   public void testReassign() throws Exception {
499     myFileTypeManager.clearForTests();
500     myFileTypeManager.initStandardFileTypes();
501     myFileTypeManager.initComponent();
502
503     Element element = JDOMUtil.loadDocument(
504       "<component name=\"FileTypeManager\" version=\"13\">\n" +
505       "   <extensionMap>\n" +
506       "      <mapping ext=\"zip\" type=\"Velocity Template files\" />\n" +
507       "   </extensionMap>\n" +
508       "</component>").getRootElement();
509
510     myFileTypeManager.loadState(element);
511     myFileTypeManager.initComponent();
512     Map<FileNameMatcher, Pair<FileType, Boolean>> mappings = myFileTypeManager.getRemovedMappings();
513     assertEquals(1, mappings.size());
514     assertEquals(ArchiveFileType.INSTANCE, mappings.values().iterator().next().first);
515     mappings.clear();
516     assertEquals(ArchiveFileType.INSTANCE, myFileTypeManager.getFileTypeByExtension("zip"));
517     Element map = myFileTypeManager.getState().getChild("extensionMap");
518     if (map != null) {
519       List<Element> mapping = map.getChildren("mapping");
520       assertNull(ContainerUtil.find(mapping, o -> "zip".equals(o.getAttributeValue("ext"))));
521     }
522   }
523
524   public void testDefaultFileType() throws Exception {
525     final String extension = "veryRareExtension";
526     final FileType idl = myFileTypeManager.findFileTypeByName("IDL");
527     ApplicationManager.getApplication().runWriteAction(() -> myFileTypeManager.associatePattern(idl, "*." + extension));
528
529     Element element = myFileTypeManager.getState();
530     //log(JDOMUtil.writeElement(element));
531     ApplicationManager.getApplication().runWriteAction(() -> myFileTypeManager.removeAssociatedExtension(idl, extension));
532
533     myFileTypeManager.clearForTests();
534     myFileTypeManager.initStandardFileTypes();
535     myFileTypeManager.loadState(element);
536     myFileTypeManager.initComponent();
537     FileType extensions = myFileTypeManager.getFileTypeByExtension(extension);
538     assertEquals("IDL", extensions.getName());
539     ApplicationManager.getApplication().runWriteAction(() -> {
540       myFileTypeManager.removeAssociatedExtension(idl, extension);
541       myFileTypeManager.clearForTests();
542       myFileTypeManager.initStandardFileTypes();
543       myFileTypeManager.initComponent();
544     });
545   }
546
547   public void testIfDetectorRanThenIdeaReopenedTheDetectorShouldBeReRun() throws IOException {
548     final UserBinaryFileType stuffType = new UserBinaryFileType();
549     stuffType.setName("stuffType");
550
551     final Set<VirtualFile> detectorCalled = ContainerUtil.newConcurrentSet();
552
553     FileTypeRegistry.FileTypeDetector detector = new FileTypeRegistry.FileTypeDetector() {
554       @Nullable
555       @Override
556       public FileType detect(@NotNull VirtualFile file, @NotNull ByteSequence firstBytes, @Nullable CharSequence firstCharsIfText) {
557         detectorCalled.add(file);
558         FileType result = FileUtil.isHashBangLine(firstCharsIfText, "stuff") ? stuffType : null;
559         log("T: my detector for file "+file.getName()+" run. result="+(result == null ? null : result.getName()));
560         return result;
561       }
562
563       @Override
564       public int getVersion() {
565         return 0;
566       }
567     };
568     Extensions.getRootArea().getExtensionPoint(FileTypeRegistry.FileTypeDetector.EP_NAME).registerExtension(detector);
569     myFileTypeManager.toLog = true;
570
571     try {
572       log("T: ------ akjdhfksdjgf");
573       File f = createTempFile("xx.asfdasdfas", "akjdhfksdjgf");
574       VirtualFile file = getVirtualFile(f);
575       ensureRedetected(file, detectorCalled);
576       assertTrue(file.getFileType().toString(), file.getFileType() instanceof PlainTextFileType);
577
578       log("T: ------ my");
579       setFileText(file,  "#!stuff\nxx");
580       ensureRedetected(file, detectorCalled);
581       assertEquals(stuffType, file.getFileType());
582
583       log("T: ------ reload");
584       myFileTypeManager.drainReDetectQueue();
585       myFileTypeManager.clearCaches();
586       file.putUserData(FileTypeManagerImpl.DETECTED_FROM_CONTENT_FILE_TYPE_KEY, null);
587
588       ensureRedetected(file, detectorCalled);
589       assertTrue(file.getFileType().toString(), file.getFileType() == stuffType);
590       log("T: ------");
591     }
592     finally {
593       Extensions.getRootArea().getExtensionPoint(FileTypeRegistry.FileTypeDetector.EP_NAME).unregisterExtension(detector);
594       myFileTypeManager.toLog = false;
595     }
596   }
597
598   public void _testStressPlainTextFileWithEverIncreasingLength() throws IOException, InterruptedException {
599     FrequentEventDetector.disableUntil(getTestRootDisposable());
600
601     File f = createTempFile("xx.lkjlkjlkjlj", "a");
602     VirtualFile virtualFile = getVirtualFile(f);
603     assertEquals(PlainTextFileType.INSTANCE, virtualFile.getFileType());
604     //PsiFile psiFile = getPsiManager().findFile(virtualFile);
605     //assertTrue(psiFile instanceof PsiPlainTextFile);
606
607     int NThreads = 8;
608     int N = 1000;
609     Random random = new Random();
610     AtomicReference<Exception> exception = new AtomicReference<>();
611     List<Thread> threads = ContainerUtil.map(new Object[NThreads], o -> new Thread(() -> {
612       try {
613         for (int i = 0; i < N; i++) {
614           boolean isText = ApplicationManager.getApplication().runReadAction((Computable<Boolean>)() -> {
615             if (virtualFile.getFileType().isBinary()) {
616               return false;
617             }
618             else {
619               LoadTextUtil.loadText(virtualFile);
620               return true;
621             }
622           });
623
624           if (random.nextInt(3) == 0) {
625             new WriteCommandAction.Simple(getProject()) {
626               @Override
627               protected void run() throws Throwable {
628                 byte[] bytes = new byte[(int)PersistentFSConstants.FILE_LENGTH_TO_CACHE_THRESHOLD + (isText ? 1 : 0)];
629                 Arrays.fill(bytes, (byte)' ');
630                 virtualFile.setBinaryContent(bytes);
631               }
632             }.execute().throwException();
633
634
635             //RandomAccessFile ra = new RandomAccessFile(f, "rw");
636             //ra.setLength(ra.length()+(isText ? 1 : -1));
637             //ra.close();
638             //LocalFileSystem.getInstance().refreshFiles(Collections.singletonList(virtualFile));
639             System.out.println(i+"; f = " + f.length()+"; virtualFile="+virtualFile.getLength()+"; type="+virtualFile.getFileType());
640             //Thread.sleep(random.nextInt(100));
641           }
642         }
643       }
644       catch (Exception e) {
645         exception.set(e);
646         e.printStackTrace();
647         throw new RuntimeException(e);
648       }
649     }, "reader"));
650     threads.forEach(Thread::start);
651     for (Thread thread : threads) {
652       while (thread.isAlive()) {
653         if (exception.get() != null) throw new RuntimeException(exception.get());
654         UIUtil.dispatchAllInvocationEvents(); //refresh
655       }
656     }
657     if (exception.get() != null) throw new RuntimeException(exception.get());
658   }
659
660   public void _testStressPlainTextFileWithEverIncreasingLength2() throws IOException, InterruptedException {
661     FrequentEventDetector.disableUntil(getTestRootDisposable());
662
663     File f = createTempFile("xx.asdkjfhlkasjdhf", StringUtil.repeatSymbol(' ', (int)PersistentFSConstants.FILE_LENGTH_TO_CACHE_THRESHOLD - 100));
664     VirtualFile virtualFile = getVirtualFile(f);
665     assertEquals(PlainTextFileType.INSTANCE, virtualFile.getFileType());
666     PsiFile psiFile = getPsiManager().findFile(virtualFile);
667     assertTrue(psiFile instanceof PsiPlainTextFile);
668
669     int NThreads = 1;
670     int N = 10;
671     List<Thread> threads = ContainerUtil.map(new Object[NThreads], o -> new Thread(() -> {
672       for (int i = 0; i < N; i++) {
673         ApplicationManager.getApplication().runReadAction(() -> {
674           String text = psiFile.getText();
675           System.out.println("text = " + text.length());
676           //if (!virtualFile.getFileType().isBinary()) {
677           //  LoadTextUtil.loadText(virtualFile);
678           //}
679         });
680         if (i % 1 == 0) {
681           try {
682             FileUtil.appendToFile(f, StringUtil.repeatSymbol(' ', 50));
683             LocalFileSystem.getInstance().refreshFiles(Collections.singletonList(virtualFile));
684             System.out.println("f = " + f.length()+"; virtualFile="+virtualFile.getLength()+"; psiFile="+psiFile.isValid()+"; type="+virtualFile.getFileType());
685           }
686           catch (IOException e) {
687             throw new RuntimeException(e);
688           }
689         }
690       }
691     }, "reader"));
692     threads.forEach(Thread::start);
693     for (Thread thread : threads) {
694       while (thread.isAlive()) {
695         UIUtil.dispatchAllInvocationEvents(); //refresh
696       }
697     }
698   }
699 }