238 lines
11 KiB
Java
238 lines
11 KiB
Java
package p.studio.vfs;
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.api.io.TempDir;
|
|
import p.studio.vfs.messages.*;
|
|
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.Map;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
final class FilesystemVfsProjectDocumentTest {
|
|
@TempDir
|
|
Path tempDir;
|
|
|
|
@Test
|
|
void snapshotIncludesHiddenFilesOrdersFoldersFirstAndTagsSourceRoots() throws Exception {
|
|
Files.createDirectories(tempDir.resolve("src"));
|
|
Files.createDirectories(tempDir.resolve("assets"));
|
|
Files.writeString(tempDir.resolve(".env"), "TOKEN=1\n");
|
|
Files.writeString(tempDir.resolve("README.md"), "# project\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
|
|
final VfsProjectSnapshot snapshot = vfs.snapshot();
|
|
|
|
assertEquals("Example", snapshot.rootNode().displayName());
|
|
assertEquals("assets", snapshot.rootNode().children().get(0).displayName());
|
|
assertEquals("src", snapshot.rootNode().children().get(1).displayName());
|
|
assertEquals(".env", snapshot.rootNode().children().get(2).displayName());
|
|
assertTrue(snapshot.rootNode().children().get(1).taggedSourceRoot());
|
|
}
|
|
|
|
@Test
|
|
void openDocumentReturnsTextDocumentForUtf8TextFile() throws Exception {
|
|
final Path file = tempDir.resolve("main.pbs");
|
|
Files.writeString(file, "fn main(): void\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
|
|
final VfsDocumentOpenResult result = vfs.openDocument(file);
|
|
final var document = assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, result);
|
|
|
|
assertEquals("main.pbs", document.documentName());
|
|
assertEquals("pbs", document.typeId());
|
|
assertEquals("LF", document.lineSeparator());
|
|
assertEquals(VfsDocumentAccessMode.EDITABLE, document.accessContext().accessMode());
|
|
assertTrue(document.accessContext().frontendDocument());
|
|
assertTrue(document.content().contains("fn main()"));
|
|
}
|
|
|
|
@Test
|
|
void openDocumentClassifiesJsonFilesWithJsonTypeIdentifier() throws Exception {
|
|
final Path file = tempDir.resolve("prometeu.json");
|
|
Files.writeString(file, "{\n \"name\": \"Example\"\n}\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
|
|
final VfsDocumentOpenResult result = vfs.openDocument(file);
|
|
final var document = assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, result);
|
|
|
|
assertEquals(VfsDocumentTypeIds.JSON, document.typeId());
|
|
assertEquals(VfsDocumentAccessMode.EDITABLE, document.accessContext().accessMode());
|
|
}
|
|
|
|
@Test
|
|
void openDocumentClassifiesNdjsonFilesWithJsonTypeIdentifier() throws Exception {
|
|
final Path file = tempDir.resolve("events.ndjson");
|
|
Files.writeString(file, "{\"event\":\"start\"}\n{\"event\":\"done\"}\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
|
|
final VfsDocumentOpenResult result = vfs.openDocument(file);
|
|
final var document = assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, result);
|
|
|
|
assertEquals(VfsDocumentTypeIds.NDJSON, document.typeId());
|
|
}
|
|
|
|
@Test
|
|
void openDocumentClassifiesBashScriptsWithBashTypeIdentifier() throws Exception {
|
|
final Path file = tempDir.resolve("script.sh");
|
|
Files.writeString(file, "#!/usr/bin/env bash\nprintf \"hi\"\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
|
|
final VfsDocumentOpenResult result = vfs.openDocument(file);
|
|
final var document = assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, result);
|
|
|
|
assertEquals(VfsDocumentTypeIds.BASH, document.typeId());
|
|
assertEquals(VfsDocumentAccessMode.EDITABLE, document.accessContext().accessMode());
|
|
}
|
|
|
|
@Test
|
|
void frontendDocumentsUseEditableInMemorySnapshotsUntilSavePersistsThem() throws Exception {
|
|
final Path file = tempDir.resolve("main.pbs");
|
|
Files.writeString(file, "fn main(): void\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
final var updated = vfs.updateDocument(file, "fn main(): int\n");
|
|
|
|
assertTrue(updated.dirty());
|
|
assertEquals("fn main(): int\n", updated.content());
|
|
assertEquals("fn main(): void\n", Files.readString(file));
|
|
assertEquals("fn main(): int\n", assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, vfs.openDocument(file)).content());
|
|
|
|
final VfsDocumentSaveResult saveResult = vfs.saveDocument(file);
|
|
|
|
assertEquals(VfsDocumentSaveStatus.SAVED, saveResult.status());
|
|
assertEquals("fn main(): int\n", Files.readString(file));
|
|
assertFalse(assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, vfs.openDocument(file)).dirty());
|
|
}
|
|
|
|
@Test
|
|
void editableDocumentsUseInMemorySnapshotsUntilSavePersistsThem() throws Exception {
|
|
final Path file = tempDir.resolve("notes.txt");
|
|
Files.writeString(file, "alpha\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
|
|
final var updated = vfs.updateDocument(file, "beta\n");
|
|
|
|
assertTrue(updated.dirty());
|
|
assertEquals("beta\n", updated.content());
|
|
assertEquals("alpha\n", Files.readString(file));
|
|
assertEquals("beta\n", assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, vfs.openDocument(file)).content());
|
|
|
|
final VfsDocumentSaveResult saveResult = vfs.saveDocument(file);
|
|
|
|
assertEquals(VfsDocumentSaveStatus.SAVED, saveResult.status());
|
|
assertEquals("beta\n", Files.readString(file));
|
|
assertFalse(assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, vfs.openDocument(file)).dirty());
|
|
}
|
|
|
|
@Test
|
|
void discardDocumentDropsDirtySnapshotAndRestoresFilesystemState() throws Exception {
|
|
final Path file = tempDir.resolve("notes.txt");
|
|
Files.writeString(file, "alpha\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
vfs.updateDocument(file, "beta\n");
|
|
|
|
final var discarded = vfs.discardDocument(file);
|
|
|
|
assertFalse(discarded.dirty());
|
|
assertEquals("alpha\n", discarded.content());
|
|
assertEquals("alpha\n", Files.readString(file));
|
|
assertEquals("alpha\n", assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, vfs.openDocument(file)).content());
|
|
}
|
|
|
|
@Test
|
|
void saveAllDocumentsPersistsEditableDirtySnapshotsIncludingFrontendDocuments() throws Exception {
|
|
final Path editable = tempDir.resolve("notes.txt");
|
|
final Path frontend = tempDir.resolve("main.pbs");
|
|
Files.writeString(editable, "alpha\n");
|
|
Files.writeString(frontend, "fn main(): void\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
vfs.updateDocument(editable, "beta\n");
|
|
vfs.updateDocument(frontend, "fn main(): int\n");
|
|
|
|
final var results = vfs.saveAllDocuments();
|
|
|
|
assertEquals(2, results.size());
|
|
assertEquals(editable.toAbsolutePath().normalize(), results.get(0).path());
|
|
assertEquals(VfsDocumentSaveStatus.SAVED, results.get(0).status());
|
|
assertEquals(frontend.toAbsolutePath().normalize(), results.get(1).path());
|
|
assertEquals(VfsDocumentSaveStatus.SAVED, results.get(1).status());
|
|
assertEquals("beta\n", Files.readString(editable));
|
|
assertEquals("fn main(): int\n", Files.readString(frontend));
|
|
}
|
|
|
|
@Test
|
|
void accessContextCanBeReadAndMutatedWithoutChangingCanonicalPolicy() throws Exception {
|
|
final Path file = tempDir.resolve("prometeu.json");
|
|
Files.writeString(file, "{\n \"name\": \"Example\"\n}\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
|
|
final VfsDocumentAccessContext initialContext = vfs.accessContext(file);
|
|
final VfsDocumentAccessContext updatedContext = vfs.updateAccessContext(file, Map.of("statusBar", "future-toggle"));
|
|
|
|
assertEquals(VfsDocumentAccessMode.EDITABLE, initialContext.accessMode());
|
|
assertEquals(VfsDocumentTypeIds.JSON, initialContext.typeId());
|
|
assertEquals(Map.of("statusBar", "future-toggle"), updatedContext.attributes());
|
|
assertEquals(initialContext.accessMode(), updatedContext.accessMode());
|
|
assertEquals(initialContext.typeId(), updatedContext.typeId());
|
|
}
|
|
|
|
@Test
|
|
void openDocumentRejectsBinaryLikeFiles() throws Exception {
|
|
final Path file = tempDir.resolve("sprite.bin");
|
|
Files.write(file, new byte[]{0x01, 0x00, 0x02});
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
|
|
final VfsDocumentOpenResult result = vfs.openDocument(file);
|
|
final var unsupported = assertInstanceOf(VfsDocumentOpenResult.VfsUnsupportedDocument.class, result);
|
|
|
|
assertEquals(VfsUnsupportedReason.BINARY_CONTENT, unsupported.reason());
|
|
}
|
|
|
|
@Test
|
|
void openDocumentRejectsPathsOutsideProjectScope() throws Exception {
|
|
final Path outsideFile = tempDir.getParent().resolve("outside.pbs");
|
|
Files.writeString(outsideFile, "fn stray(): void\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
|
|
final VfsDocumentOpenResult result = vfs.openDocument(outsideFile);
|
|
final var unsupported = assertInstanceOf(VfsDocumentOpenResult.VfsUnsupportedDocument.class, result);
|
|
|
|
assertEquals(VfsUnsupportedReason.OUTSIDE_PROJECT, unsupported.reason());
|
|
}
|
|
|
|
@Test
|
|
void targetedRefreshUpdatesOnlyTheRequestedSubtreeInTheSnapshot() throws Exception {
|
|
final Path src = Files.createDirectories(tempDir.resolve("src"));
|
|
Files.createDirectories(tempDir.resolve("assets"));
|
|
Files.writeString(src.resolve("main.pbs"), "fn main(): void\n");
|
|
|
|
final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext());
|
|
Files.writeString(src.resolve("later.pbs"), "fn later(): void\n");
|
|
|
|
final VfsProjectSnapshot refreshedSnapshot = vfs.refresh(new VfsRefreshRequest(src));
|
|
final VfsProjectNode srcNode = refreshedSnapshot.rootNode().children().get(1);
|
|
|
|
assertEquals("src", srcNode.displayName());
|
|
assertEquals(2, srcNode.children().size());
|
|
assertEquals("later.pbs", srcNode.children().get(0).displayName());
|
|
assertEquals("main.pbs", srcNode.children().get(1).displayName());
|
|
}
|
|
|
|
private VfsProjectContext projectContext() {
|
|
return new VfsProjectContext("Example", "pbs", tempDir);
|
|
}
|
|
}
|