@Override public synchronized void close() throws IOException { if (openSearchers.isEmpty() == false) { AssertionError error = new AssertionError("Unreleased searchers found"); for (RuntimeException ex : openSearchers.values()) { error.addSuppressed(ex); } throw error; } }
/** * Prepares and throws an AssertionError exception based on the message, cause, the active state * and the potential errors so far. * * @param message the message * @param cause the optional Throwable cause * @throws AssertionError as expected */ protected final void assertionError(String message, Throwable cause) { StringBuilder b = new StringBuilder(); if (cdl.getCount() != 0) { b.append("(active) "); } b.append(message); List<Throwable> err = errors; if (!err.isEmpty()) { b.append(" (+ ").append(err.size()).append(" errors)"); } AssertionError e = new AssertionError(b.toString(), cause); for (Throwable t : err) { e.addSuppressed(t); } throw e; }
@Test public void testRestoreInvalidations() throws Exception { DocumentModel doc = new DocumentModelImpl("/", "myfile", "File"); doc.setPropertyValue("dc:title", "t1"); doc = session.createDocument(doc); final DocumentRef docRef = doc.getRef(); DocumentRef v1 = session.checkIn(docRef, null, null); session.checkOut(docRef); doc.setPropertyValue("dc:title", "t2"); session.saveDocument(doc); session.save(); waitForFulltextIndexing(); // we need 2 threads to get 2 different sessions that send each other invalidations final CyclicBarrier barrier = new CyclicBarrier(2); Throwable[] throwables = new Throwable[2]; Thread t1 = new Thread() { @Override public void run() { TransactionHelper.startTransaction(); try (CoreSession session = openSessionAs(SecurityConstants.ADMINISTRATOR)) { DocumentModel doc = session.getDocument(docRef); assertEquals("t2", doc.getPropertyValue("dc:title")); // 1. sync barrier.await(30, TimeUnit.SECONDS); // (throws on timeout) // 2. restore and next tx to send invalidations DocumentModel restored = session.restoreToVersion(docRef, v1); assertEquals("t1", restored.getPropertyValue("dc:title")); session.save(); nextTransaction(); // 3. sync barrier.await(30, TimeUnit.SECONDS); // (throws on timeout) // 4. wait } catch (InterruptedException | BrokenBarrierException | TimeoutException | RuntimeException | AssertionError t) { throwables[0] = t; } finally { TransactionHelper.commitOrRollbackTransaction(); } } }; Thread t2 = new Thread() { @Override public void run() { TransactionHelper.startTransaction(); try (CoreSession session = openSessionAs(SecurityConstants.ADMINISTRATOR)) { DocumentModel doc = session.getDocument(docRef); assertEquals("t2", doc.getPropertyValue("dc:title")); // 1. sync barrier.await(30, TimeUnit.SECONDS); // (throws on timeout) // 2. nop // 3. sync barrier.await(30, TimeUnit.SECONDS); // (throws on timeout) // 4. next tx to get invalidations and check nextTransaction(); DocumentModel restored = session.getDocument(docRef); assertEquals("t1", restored.getPropertyValue("dc:title")); } catch (InterruptedException | BrokenBarrierException | TimeoutException | RuntimeException | AssertionError t) { throwables[1] = t; } finally { TransactionHelper.commitOrRollbackTransaction(); } } }; t1.start(); t2.start(); t1.join(); t2.join(); AssertionError assertionError = null; for (Throwable t : throwables) { if (t != null) { if (assertionError == null) { assertionError = new AssertionError("Exceptions in threads"); } assertionError.addSuppressed(t); } } if (assertionError != null) { throw assertionError; } }
public static synchronized void assertCoverage(boolean includeInnerClasses, Class<?>... classes) { if (!_dynamicallyInstrumented) { return; } _instrumentation.removeTransformer(_coberturaClassFileTransformer); _coberturaClassFileTransformer = null; try { ProjectData projectData = ProjectDataUtil.captureProjectData(); List<AssertionError> assertionErrors = new ArrayList<>(); for (Class<?> clazz : classes) { ClassData classData = projectData.getClassData(clazz.getName()); _assertClassDataCoverage(assertionErrors, clazz, classData); if (includeInnerClasses) { Class<?>[] declaredClasses = clazz.getDeclaredClasses(); declaredClass: for (Class<?> declaredClass : declaredClasses) { for (Class<?> clazz2 : classes) { if (clazz2.equals(declaredClass)) { continue declaredClass; } } classData = projectData.getClassData(declaredClass.getName()); _assertClassDataCoverage(assertionErrors, declaredClass, classData); } } } if (!assertionErrors.isEmpty()) { AssertionError assertionError = assertionErrors.get(0); for (int i = 1; i < assertionErrors.size(); i++) { assertionError.addSuppressed(assertionErrors.get(i)); } throw assertionError; } } finally { System.clearProperty("junit.code.coverage"); _dynamicallyInstrumented = false; if (_originalClassDefinitions != null) { try { List<ClassDefinition> classDefinitions = new ArrayList<>(_originalClassDefinitions.size()); for (int i = 0; i < _originalClassDefinitions.size(); i++) { OriginalClassDefinition originalClassDefinition = _originalClassDefinitions.get(i); ClassDefinition classDefinition = originalClassDefinition.toClassDefinition(); if (classDefinition != null) { classDefinitions.add(classDefinition); } } _originalClassDefinitions = null; _instrumentation.redefineClasses( classDefinitions.toArray(new ClassDefinition[classDefinitions.size()])); } catch (Exception e) { throw new RuntimeException("Unable to uninstrument classes", e); } } } }