Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
*/
package org.eclipse.lemminx.services;

import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
Expand Down Expand Up @@ -190,7 +189,7 @@ public List<Diagnostic> doDiagnostics(DOMDocument xmlDocument, XMLValidationSett
return diagnostics.doDiagnostics(xmlDocument, validationSettings, validationArgs, cancelChecker);
}

public CompletableFuture<Path> publishDiagnostics(DOMDocument xmlDocument,
public CompletableFuture<Void> publishDiagnostics(DOMDocument xmlDocument,
Consumer<PublishDiagnosticsParams> publishDiagnostics, Consumer<TextDocument> triggerValidation,
XMLValidationRootSettings validationSettings, Map<String, Object> validationArgs,
CancelChecker cancelChecker) {
Expand Down Expand Up @@ -218,6 +217,7 @@ public CompletableFuture<Path> publishDiagnostics(DOMDocument xmlDocument,
triggerValidation.accept(document);
return null;
});
return allFutures;
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import org.eclipse.lemminx.customservice.ActionableNotification;
import org.eclipse.lemminx.customservice.XMLLanguageClientAPI;
Expand Down Expand Up @@ -98,6 +99,25 @@ public List<PublishDiagnosticsParams> getPublishDiagnostics() {
return publishDiagnostics;
}

/**
* Wait until the total number of published diagnostics reaches the expected
* count, or the timeout expires.
*/
public void waitForDiagnosticCount(int expectedCount, long timeoutMs) {
long deadline = System.currentTimeMillis() + timeoutMs;
while (publishDiagnostics.size() < expectedCount) {
if (System.currentTimeMillis() >= deadline) {
break;
}
try {
Thread.sleep(20);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}

public List<MessageParams> getLogMessages() {
return logMessages;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ public List<PublishDiagnosticsParams> getPublishDiagnostics() {
return getLanguageClient().getPublishDiagnostics();
}

public void waitForDiagnosticCount(int expectedCount, long timeoutMs) {
getLanguageClient().waitForDiagnosticCount(expectedCount, timeoutMs);
}

@Override
public MockXMLLanguageClient getLanguageClient() {
return (MockXMLLanguageClient) super.getLanguageClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -912,21 +911,41 @@ public static void publishDiagnostics(DOMDocument xmlDocument, List<PublishDiagn

public static void publishDiagnostics(DOMDocument xmlDocument, XMLValidationRootSettings validationSettings,
List<PublishDiagnosticsParams> actual, XMLLanguageService languageService) {
CompletableFuture<Path> error = languageService.publishDiagnostics(xmlDocument, params -> {
languageService.publishDiagnostics(xmlDocument, params -> {
actual.add(params);
}, (doc) -> {
// Retrigger validation
publishDiagnostics(xmlDocument, actual, languageService);
}, validationSettings, Collections.emptyMap(), () -> {
});
}

/**
* Await completion of any in-progress resource downloads (XSD, DTD) for the
* given XML content. This replaces Thread.sleep() calls in tests that need to
* wait for async downloads to complete before re-validating.
*/
public static void awaitDownloads(XMLLanguageService ls, String xml, String fileURI) {
awaitDownloads(ls, xml, fileURI, null);
}

if (error != null) {
/**
* Await completion of any in-progress resource downloads (XSD, DTD) for the
* given XML content. This replaces Thread.sleep() calls in tests that need to
* wait for async downloads to complete before re-validating.
*/
public static void awaitDownloads(XMLLanguageService ls, String xml, String fileURI,
XMLValidationRootSettings validationSettings) {
DOMDocument xmlDocument = DOMParser.getInstance().parse(xml, fileURI, ls.getResolverExtensionManager());
ls.setDocumentProvider((uri) -> xmlDocument);
CompletableFuture<Void> downloadsFuture = ls.publishDiagnostics(xmlDocument,
params -> {
}, (doc) -> {
}, validationSettings, Collections.emptyMap(), () -> {
});
if (downloadsFuture != null) {
try {
error.join();
// Wait for 500 ms to collect the last params
Thread.sleep(200);
downloadsFuture.get(10, java.util.concurrent.TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
// Expected - downloads may fail
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.FileTime;
import java.time.Instant;

import org.eclipse.lemminx.AbstractCacheBasedTest;

Expand All @@ -39,16 +41,12 @@ protected static void updateFile(String fileName, String contents) throws IOExce
updateFile(fileURI, contents);
}
protected static void updateFile(URI fileURI, String contents) throws IOException {
// For Mac OS, Linux OS, the call of Files.getLastModifiedTime is working for 1
// second.
// Here we wait for > 1s to be sure that call of Files.getLastModifiedTime will
// work.
try {
Thread.sleep(1050);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
createFile(fileURI, contents);
// Set the last modified time 2 seconds into the future to ensure
// Files.getLastModifiedTime detects the change (filesystem timestamp
// resolution on macOS/Linux is 1 second).
Path path = Paths.get(fileURI);
Files.setLastModifiedTime(path, FileTime.from(Instant.now().plusSeconds(2)));
}

protected Path getTempDirPath() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
*/
public class XMLExternalTest extends BaseFileTempTest {

private int threadSleepMs = 600;
private MockXMLLanguageServer languageServer;

@BeforeEach
Expand Down Expand Up @@ -79,7 +78,7 @@ public void externalDTDTest() throws InterruptedException, IOException {

clientOpenFile(languageServer, xmlTextDocument);

Thread.sleep(threadSleepMs);
languageServer.waitForDiagnosticCount(1, 5000);

List<PublishDiagnosticsParams> actualDiagnostics = languageServer.getPublishDiagnostics();
assertEquals(1, actualDiagnostics.size());
Expand All @@ -88,7 +87,7 @@ public void externalDTDTest() throws InterruptedException, IOException {
editFile(testDtd, 2, "");
didChangedWatchedFiles(languageServer, testDtd);

Thread.sleep(threadSleepMs);
languageServer.waitForDiagnosticCount(2, 5000);

assertEquals(2, actualDiagnostics.size());
assertFalse(actualDiagnostics.get(1).getDiagnostics().isEmpty());
Expand Down Expand Up @@ -134,7 +133,7 @@ public void externalXSDTest() throws InterruptedException, IOException {

clientOpenFile(languageServer, xmlTextDocument);

Thread.sleep(threadSleepMs);
languageServer.waitForDiagnosticCount(1, 5000);

List<PublishDiagnosticsParams> actualDiagnostics = languageServer.getPublishDiagnostics();
assertEquals(1, actualDiagnostics.size());
Expand All @@ -143,7 +142,7 @@ public void externalXSDTest() throws InterruptedException, IOException {
editFile(testXsd, 12, " maxOccurs=\"2\"/>");
didChangedWatchedFiles(languageServer, testXsd);

Thread.sleep(threadSleepMs);
languageServer.waitForDiagnosticCount(2, 5000);

assertEquals(2, actualDiagnostics.size());
assertEquals("cvc-complex-type.2.4.f", actualDiagnostics.get(1).getDiagnostics().get(0).getCode().getLeft());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import static org.eclipse.lemminx.XMLAssert.r;
import static org.eclipse.lemminx.XMLAssert.d;

import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

import org.eclipse.lemminx.AbstractCacheBasedTest;
Expand Down Expand Up @@ -146,8 +145,6 @@ public void schemaWithUrlWithCache() throws Exception {
"</invoice> \r\n" + //
"";

TimeUnit.SECONDS.sleep(2); // HACK: to make the timing work on slow machines

// Downloading...
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, ls, pd(fileURI,
new Diagnostic(r(2, 32, 2, 50),
Expand All @@ -156,7 +153,7 @@ public void schemaWithUrlWithCache() throws Exception {
new Diagnostic(r(1, 1, 1, 8), "cvc-elt.1.a: Cannot find the declaration of element 'invoice'.",
DiagnosticSeverity.Error, "xml", XMLSchemaErrorCode.cvc_elt_1_a.getCode())));

TimeUnit.SECONDS.sleep(5); // HACK: to make the timing work on slow machines
XMLAssert.awaitDownloads(ls, xml, fileURI);

// Downloaded error
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, ls, pd(fileURI,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import static org.eclipse.lemminx.XMLAssert.r;
import static org.eclipse.lemminx.XMLAssert.testCodeActionsFor;

import java.util.concurrent.TimeUnit;

import org.eclipse.lemminx.AbstractCacheBasedTest;
import org.eclipse.lemminx.XMLAssert;
import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager;
Expand Down Expand Up @@ -96,7 +94,7 @@ public void docTypeDownloadProblem() throws Exception {
new Diagnostic(r(1, 1, 1, 13), "Element type \"root-element\" must be declared.",
DiagnosticSeverity.Error, "xml", DTDErrorCode.MSG_ELEMENT_NOT_DECLARED.getCode())));

TimeUnit.SECONDS.sleep(5); // HACK: to make the timing work on slow machines
XMLAssert.awaitDownloads(ls, xml, fileURI, validation);

// Downloaded error
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls,
Expand Down Expand Up @@ -177,7 +175,7 @@ public void entityRefDownloadProblem() throws Exception {
new Diagnostic(r(6, 1, 6, 7), "The entity \"abcd\" was referenced, but not declared.",
DiagnosticSeverity.Error, "xml", DTDErrorCode.EntityNotDeclared.getCode())));

TimeUnit.SECONDS.sleep(5); // HACK: to make the timing work on slow machines
XMLAssert.awaitDownloads(ls, xml, fileURI, validation);

// Downloaded error
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import static org.eclipse.lemminx.XMLAssert.r;
import static org.eclipse.lemminx.XMLAssert.testCodeActionsFor;

import java.util.concurrent.TimeUnit;

import org.eclipse.lemminx.AbstractCacheBasedTest;
import org.eclipse.lemminx.XMLAssert;
import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager;
Expand Down Expand Up @@ -99,7 +97,7 @@ public void noNamespaceSchemaLocationDownloadProblem() throws Exception {
new Diagnostic(r(0, 1, 0, 13), "cvc-elt.1.a: Cannot find the declaration of element 'root-element'.",
DiagnosticSeverity.Error, "xml", XMLSchemaErrorCode.cvc_elt_1_a.getCode())));

TimeUnit.SECONDS.sleep(5); // HACK: to make the timing work on slow machines
XMLAssert.awaitDownloads(ls, xml, fileURI, validation);

// Downloaded error
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI,
Expand Down Expand Up @@ -173,7 +171,7 @@ public void schemaLocationDownloadProblem() throws Exception {
new Diagnostic(r(0, 1, 0, 13), "cvc-elt.1.a: Cannot find the declaration of element 'root-element'.",
DiagnosticSeverity.Error, "xml", XMLSchemaErrorCode.cvc_elt_1_a.getCode())));

TimeUnit.SECONDS.sleep(5); // HACK: to make the timing work on slow machines
XMLAssert.awaitDownloads(ls, xml, fileURI, validation);

// Downloaded error
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,8 @@ public void validationFileCommand() throws Exception {
// Open the XML document, the validation is triggered asynchronously
TextDocumentIdentifier xmlIdentifier = languageServer.didOpen("test.xml", xml);

// Wait for:
// - downloading of XSD from the HTTP server to lemminx cache
// - validation triggers
Thread.sleep(1000);
// Wait for downloading of XSD and validation to trigger
languageServer.waitForDiagnosticCount(2, 5000);

// 1.1 Validation test

Expand Down Expand Up @@ -141,10 +139,8 @@ public void validationFileCommand() throws Exception {
// Execute command cache
languageServer.executeCommand(XMLValidationFileCommand.COMMAND_ID, xmlIdentifier).get();

// Wait for:
// - downloading of XSD from the HTTP server to lemminx cache
// - validation triggers
Thread.sleep(1000);
// Wait for downloading and validation to trigger
languageServer.waitForDiagnosticCount(2, 5000);

// 3.1 Validation test

Expand Down Expand Up @@ -224,9 +220,8 @@ public void validationAllFilesCommand() throws Exception {
// Open the XML document, the validation is triggered asynchronously
TextDocumentIdentifier xml1Identifier = languageServer.didOpen("test1.xml", xml1);

// Wait for to collect diagnostics in the proper order (XSD diagnostics followed
// by DTD diagnostics)
Thread.sleep(2000);
// Wait for XSD diagnostics before opening second file
languageServer.waitForDiagnosticCount(2, 5000);

// Open the second XML file bound to the DTD
String xml2 = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n" + //
Expand All @@ -238,10 +233,8 @@ public void validationAllFilesCommand() throws Exception {
// Open the XML document, the validation is triggered asynchronously
TextDocumentIdentifier xml2Identifier = languageServer.didOpen("test2.xml", xml2);

// Wait for:
// - downloading of XSD from the HTTP server to lemminx cache
// - validation triggers
Thread.sleep(1000);
// Wait for all 4 diagnostics (2 for each XML file)
languageServer.waitForDiagnosticCount(4, 5000);

// 1.1 Validation test

Expand Down Expand Up @@ -316,13 +309,10 @@ public void validationAllFilesCommand() throws Exception {
XMLAssert.assertCompletion(list2, c("tag", "<tag />"), 5 /* region, endregion, cdata, comment, tag */);

// Execute command cache
Thread.sleep(1000);
languageServer.executeCommand(XMLValidationAllFilesCommand.COMMAND_ID).get();

// Wait for:
// - downloading of XSD from the HTTP server to lemminx cache
// - validation triggers
Thread.sleep(1000);
// Wait for downloading and validation to trigger (4 diagnostics: 2 per file)
languageServer.waitForDiagnosticCount(4, 5000);

// 3.1 Validation test

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import static org.eclipse.lemminx.XMLAssert.r;
import static org.eclipse.lemminx.XMLAssert.testCodeActionsFor;

import java.util.concurrent.TimeUnit;

import org.eclipse.lemminx.AbstractCacheBasedTest;
import org.eclipse.lemminx.XMLAssert;
import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager;
Expand Down Expand Up @@ -121,7 +119,7 @@ public void entityRefDownloadProblem() throws Exception {
DiagnosticSeverity.Information, "xml",
ExternalResourceErrorCode.DownloadingResource.getCode())));

TimeUnit.SECONDS.sleep(5); // HACK: to make the timing work on slow machines
XMLAssert.awaitDownloads(ls, dtd, fileURI, validation);

// Downloaded error
XMLAssert.testPublishDiagnosticsFor(dtd, fileURI, validation, ls,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import static org.eclipse.lemminx.XMLAssert.r;
import static org.eclipse.lemminx.XMLAssert.testCodeActionsFor;

import java.util.concurrent.TimeUnit;

import org.eclipse.lemminx.AbstractCacheBasedTest;
import org.eclipse.lemminx.XMLAssert;
import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager;
Expand Down Expand Up @@ -96,7 +94,7 @@ public void includeSchemaLocationDownloadProblem() throws Exception {
DiagnosticSeverity.Information, "xsd",
ExternalResourceErrorCode.DownloadingResource.getCode())));

TimeUnit.SECONDS.sleep(5); // HACK: to make the timing work on slow machines
XMLAssert.awaitDownloads(ls, xsd, fileURI, validation);

// Downloaded error
XMLAssert.testPublishDiagnosticsFor(xsd, fileURI, validation, ls,
Expand Down
Loading
Loading