tests to specify when modification count for file is advanced and when it isn't advanced
[idea/community.git] / platform / platform-tests / testSrc / com / intellij / openapi / vfs / local / PersistentFsTest.java
1 /*
2  * Copyright 2000-2015 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.vfs.local;
17
18 import com.intellij.openapi.application.ApplicationManager;
19 import com.intellij.openapi.util.SystemInfo;
20 import com.intellij.openapi.util.ThrowableComputable;
21 import com.intellij.openapi.util.io.FileUtil;
22 import com.intellij.openapi.util.io.IoTestUtil;
23 import com.intellij.openapi.util.text.StringUtil;
24 import com.intellij.openapi.vfs.*;
25 import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
26 import com.intellij.openapi.vfs.newvfs.FileAttribute;
27 import com.intellij.openapi.vfs.newvfs.ManagingFS;
28 import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
29 import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
30 import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
31 import com.intellij.testFramework.LoggedErrorProcessor;
32 import com.intellij.testFramework.PlatformTestCase;
33 import com.intellij.util.io.DataInputOutputUtil;
34 import org.apache.log4j.Logger;
35 import org.jetbrains.annotations.NotNull;
36
37 import java.io.DataOutputStream;
38 import java.io.File;
39 import java.io.IOException;
40 import java.nio.charset.Charset;
41 import java.util.jar.JarFile;
42
43 public class PersistentFsTest extends PlatformTestCase {
44   private PersistentFS myFs;
45   private LocalFileSystem myLocalFs;
46
47   @Override
48   public void setUp() throws Exception {
49     super.setUp();
50     myFs = PersistentFS.getInstance();
51     myLocalFs = LocalFileSystem.getInstance();
52   }
53
54   @Override
55   protected void tearDown() throws Exception {
56     myLocalFs = null;
57     myFs = null;
58     super.tearDown();
59   }
60
61   public void testAccessingFileByID() throws Exception {
62     File dir = createTempDirectory();
63     File file = new File(dir, "test.txt");
64     assertTrue(file.createNewFile());
65
66     VirtualFile vFile = myLocalFs.refreshAndFindFileByIoFile(file);
67     assertNotNull(vFile);
68
69     int id = ((VirtualFileWithId)vFile).getId();
70     assertEquals(vFile, myFs.findFileById(id));
71
72     delete(vFile);
73     assertNull(myFs.findFileById(id));
74   }
75
76   public void testFindRootShouldNotBeFooledByRelativePath() throws Exception {
77     File tmp = createTempDirectory();
78     File x = new File(tmp, "x.jar");
79     assertTrue(x.createNewFile());
80
81     VirtualFile vx = myLocalFs.refreshAndFindFileByIoFile(x);
82     assertNotNull(vx);
83
84     JarFileSystem jfs = JarFileSystem.getInstance();
85     VirtualFile root = jfs.getJarRootForLocalFile(vx);
86     String path = vx.getPath() + "/../" + vx.getName() + JarFileSystem.JAR_SEPARATOR;
87     assertSame(myFs.findRoot(path, jfs), root);
88   }
89
90   public void testFindRootMustCreateFileWithCanonicalPath() throws Exception {
91     File tmp = createTempDirectory();
92     File x = new File(tmp, "x.jar");
93     assertTrue(x.createNewFile());
94
95     JarFileSystem jfs = JarFileSystem.getInstance();
96     String path = x.getPath() + "/../" + x.getName() + JarFileSystem.JAR_SEPARATOR;
97     NewVirtualFile root = myFs.findRoot(path, jfs);
98     assertFalse(root.getPath().contains(".."));
99   }
100
101   public void testDeleteSubstRoots() throws Exception {
102     if (!SystemInfo.isWindows) return;
103
104     File tempDirectory = FileUtil.createTempDirectory(getTestName(false), null);
105     File substRoot = IoTestUtil.createSubst(tempDirectory.getPath());
106     VirtualFile subst = myLocalFs.refreshAndFindFileByIoFile(substRoot);
107     assertNotNull(subst);
108
109     try {
110       final File[] children = substRoot.listFiles();
111       assertNotNull(children);
112     }
113     finally {
114       IoTestUtil.deleteSubst(substRoot.getPath());
115     }
116     subst.refresh(false, true);
117
118     VirtualFile[] roots = myFs.getRoots(myLocalFs);
119     for (VirtualFile root : roots) {
120       String rootPath = root.getPath();
121       String prefix = StringUtil.commonPrefix(rootPath, substRoot.getPath());
122       assertEmpty(prefix);
123     }
124   }
125
126   public void testLocalRoots() {
127     VirtualFile tempRoot = VirtualFileManager.getInstance().findFileByUrl("temp:///");
128     assertNotNull(tempRoot);
129
130     VirtualFile[] roots = myFs.getLocalRoots();
131     for (VirtualFile root : roots) {
132       assertTrue("root=" + root, root.isInLocalFileSystem());
133       VirtualFileSystem fs = root.getFileSystem();
134       assertTrue("fs=" + fs, fs instanceof LocalFileSystem);
135       assertFalse("fs=" + fs, fs instanceof TempFileSystem);
136     }
137   }
138
139   public void testInvalidJarRootsIgnored() throws Exception {
140     File file = IoTestUtil.createTestFile("file.txt");
141     String url = "jar://" + FileUtil.toSystemIndependentName(file.getPath()) + "!/";
142     assertNull(VirtualFileManager.getInstance().findFileByUrl(url));
143   }
144
145   public void testBrokenJarRoots() throws Exception {
146     final File jarFile = IoTestUtil.createTestFile("empty.jar");
147
148     final int[] logCount = {0};
149     LoggedErrorProcessor.setNewInstance(new LoggedErrorProcessor() {
150       @Override
151       public void processWarn(String message, Throwable t, @NotNull Logger logger) {
152         super.processWarn(message, t, logger);
153         if (message.contains(jarFile.getName())) logCount[0]++;
154       }
155     });
156
157     try {
158       String rootUrl = "jar://" + FileUtil.toSystemIndependentName(jarFile.getPath()) + "!/";
159       String entryUrl = rootUrl + JarFile.MANIFEST_NAME;
160       assertNotNull(getVirtualFile(jarFile));
161       VirtualFile jarRoot = VirtualFileManager.getInstance().findFileByUrl(rootUrl);
162       assertNotNull(jarRoot);
163       assertTrue(jarRoot.isValid());
164       assertEquals(0, jarRoot.getChildren().length);
165       assertNull(VirtualFileManager.getInstance().findFileByUrl(entryUrl));
166
167       VirtualFile local = JarFileSystem.getInstance().getVirtualFileForJar(jarRoot);
168       assertNotNull(local);
169       IoTestUtil.createTestJar(jarFile);
170       local.refresh(false, false);
171       assertTrue(jarRoot.isValid());
172       assertEquals(1, jarRoot.getChildren().length);
173       assertNotNull(VirtualFileManager.getInstance().findFileByUrl(entryUrl));
174     }
175     finally {
176       LoggedErrorProcessor.restoreDefaultProcessor();
177     }
178
179     assertEquals(1, logCount[0]);
180   }
181
182   public void testModCountIncreases() throws IOException {
183     VirtualFile vFile = setupFile();
184     ManagingFS managingFS = ManagingFS.getInstance();
185     int globalModCount = managingFS.getFilesystemModificationCount();
186     final int parentModCount = managingFS.getModificationCount(vFile.getParent());
187
188     ApplicationManager.getApplication().runWriteAction((ThrowableComputable<Object, IOException>)() -> {
189       vFile.setWritable(false);
190       return null;
191     });
192
193     assertEquals(globalModCount + 1, managingFS.getModificationCount(vFile));
194     assertEquals(globalModCount + 1, managingFS.getFilesystemModificationCount());
195     assertEquals(parentModCount, managingFS.getModificationCount(vFile.getParent()));
196
197     FSRecords.force();
198     assertTrue(!FSRecords.isDirty());
199     ++globalModCount;
200
201     ApplicationManager.getApplication().runWriteAction((ThrowableComputable<Object, IOException>)() -> {
202       vFile.setWritable(true);  // 1
203       vFile.setBinaryContent("foo".getBytes(Charset.defaultCharset())); // 1 + timestamp + length
204       return null;
205     });
206
207     assertEquals(globalModCount + 4, managingFS.getModificationCount(vFile));
208     assertEquals(globalModCount + 4, managingFS.getFilesystemModificationCount());
209     assertEquals(parentModCount, managingFS.getModificationCount(vFile.getParent()));
210   }
211
212   @NotNull
213   private static VirtualFile setupFile() throws IOException {
214     File file = IoTestUtil.createTestFile("file.txt");
215     VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
216     assertNotNull(vFile);
217     return vFile;
218   }
219
220   public void testModCountNotIncreases() throws IOException {
221     VirtualFile vFile = setupFile();
222     ManagingFS managingFS = ManagingFS.getInstance();
223     final int globalModCount = managingFS.getFilesystemModificationCount();
224     final int parentModCount = managingFS.getModificationCount(vFile.getParent());
225
226     FSRecords.force();
227     assertTrue(!FSRecords.isDirty());
228
229     FileAttribute attribute = new FileAttribute("test.attribute", 1, true);
230     ApplicationManager.getApplication().runWriteAction((ThrowableComputable<Object, IOException>)() -> {
231       try(DataOutputStream output = attribute.writeAttribute(vFile)) {
232         DataInputOutputUtil.writeINT(output, 1);
233       }
234       return null;
235     });
236
237     assertEquals(globalModCount, managingFS.getModificationCount(vFile));
238     assertEquals(globalModCount, managingFS.getFilesystemModificationCount());
239     assertEquals(parentModCount, managingFS.getModificationCount(vFile.getParent()));
240
241     assertTrue(FSRecords.isDirty());
242     FSRecords.force();
243     assertTrue(!FSRecords.isDirty());
244
245     //
246     int fileId = ((VirtualFileWithId)vFile).getId();
247     FSRecords.setTimestamp(fileId, FSRecords.getTimestamp(fileId));
248     FSRecords.setLength(fileId, FSRecords.getLength(fileId));
249
250     assertEquals(globalModCount, managingFS.getModificationCount(vFile));
251     assertEquals(globalModCount, managingFS.getFilesystemModificationCount());
252     assertEquals(parentModCount, managingFS.getModificationCount(vFile.getParent()));
253     assertTrue(!FSRecords.isDirty());
254   }
255 }