| /******************************************************************************* |
| * Copyright (c) 2011, 2017 EclipseSource and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * EclipseSource - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.p2.tests.artifact.repository; |
| |
| import java.io.File; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.equinox.internal.p2.artifact.repository.Activator; |
| import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactDescriptor; |
| import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository; |
| import org.eclipse.equinox.internal.p2.metadata.ArtifactKey; |
| import org.eclipse.equinox.p2.core.ProvisionException; |
| import org.eclipse.equinox.p2.metadata.IArtifactKey; |
| import org.eclipse.equinox.p2.metadata.Version; |
| import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor; |
| import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager; |
| import org.eclipse.equinox.p2.tests.AbstractProvisioningTest; |
| |
| public class ArtifactLockingTest extends AbstractProvisioningTest { |
| |
| private File targetLocation; |
| private SimpleArtifactRepository repo1 = null; |
| private SimpleArtifactRepository repo2 = null; |
| private boolean lockingValue = false; |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| lockingValue = Activator.getInstance().enableArtifactLocking(); |
| System.setProperty(Activator.ENABLE_ARTIFACT_LOCKING, "true"); |
| |
| targetLocation = File.createTempFile("bundlepool", ".repo"); |
| targetLocation.delete(); |
| targetLocation.mkdirs(); |
| repo1 = new SimpleArtifactRepository(getAgent(), "TargetRepo", targetLocation.toURI(), null); |
| Thread.sleep(1000); |
| repo2 = new SimpleArtifactRepository(getAgent(), "TargetRepo", targetLocation.toURI(), null); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| System.setProperty(Activator.ENABLE_ARTIFACT_LOCKING, "" + lockingValue); |
| targetLocation.delete(); |
| super.tearDown(); |
| } |
| |
| boolean canContinue = false; |
| |
| public void testCancelLoad() throws InterruptedException, ProvisionException { |
| this.canContinue = false; |
| final IProgressMonitor progressMonitor = new NullProgressMonitor(); |
| new Thread(() -> status = repo1.executeBatch(monitor -> { |
| try { |
| canContinue = true; |
| Thread.sleep(3 * 1000); |
| repo1.addDescriptor(new SimpleArtifactDescriptor(new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0"))), new NullProgressMonitor()); |
| progressMonitor.setCanceled(true); |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| // Do nothing |
| } |
| }, new NullProgressMonitor())).start(); |
| |
| while (!canContinue) { |
| Thread.sleep(100); |
| } |
| |
| IArtifactRepositoryManager artifactManager = getAgent().getService(IArtifactRepositoryManager.class); |
| boolean expected = false; |
| try { |
| artifactManager.loadRepository(targetLocation.toURI(), progressMonitor); |
| } catch (OperationCanceledException e) { |
| expected = true; |
| } |
| assertTrue("Expected an Operation Cancled Exception", expected); |
| |
| } |
| |
| public void testWaitForLoad() throws InterruptedException, ProvisionException { |
| this.canContinue = false; |
| new Thread(() -> status = repo1.executeBatch(monitor -> { |
| try { |
| canContinue = true; |
| Thread.sleep(6 * 1000); |
| repo1.addDescriptor(new SimpleArtifactDescriptor(new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0"))), new NullProgressMonitor()); |
| |
| } catch (InterruptedException e) { |
| // Do nothing |
| } |
| }, new NullProgressMonitor())).start(); |
| |
| while (!canContinue) { |
| Thread.sleep(100); |
| } |
| IArtifactRepositoryManager artifactManager = getAgent().getService(IArtifactRepositoryManager.class); |
| SimpleArtifactRepository artifactRepository = (SimpleArtifactRepository) artifactManager.loadRepository(targetLocation.toURI(), new NullProgressMonitor()); |
| assertEquals(1, artifactRepository.getDescriptors().size()); |
| |
| } |
| |
| // Helper variables for the following test case |
| private boolean keepRunning = true; |
| IStatus status = null; |
| |
| /** |
| * Creates 1 thread that does a long running execute batch. We then try to add descriptors to another |
| * instance of the same repository. This will block. We then cancel the progress monitor to test |
| * that the block terminates. |
| * @throws InterruptedException |
| */ |
| public void testCancel() throws InterruptedException { |
| final IProgressMonitor progressMonitor = new NullProgressMonitor(); |
| this.keepRunning = true; |
| |
| new Thread(() -> status = repo1.executeBatch(monitor -> { |
| long start = System.currentTimeMillis(); |
| while (keepRunning) { |
| long current = System.currentTimeMillis(); |
| if (current - start > 1000 * 10) { |
| fail("Test case never finished. Likely keep running was never set to false."); |
| return; |
| } |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| // Do nothing |
| } |
| } |
| }, new NullProgressMonitor())).start(); |
| |
| // Give the execute batch thread a chance to start |
| Thread.sleep(1000); |
| |
| // Create a thread that will stop our progress monitor |
| Thread t = new Thread(() -> { |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| // Do nothing |
| } |
| progressMonitor.setCanceled(true); |
| }); |
| t.start(); |
| |
| // This should block |
| repo2.addDescriptor(new SimpleArtifactDescriptor(new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0"))), progressMonitor); |
| keepRunning = false; |
| if (status != null && !status.isOK()) { |
| fail(status.getMessage()); |
| } |
| assertEquals(0, repo2.getDescriptors().size()); // The descriptor should not have been added |
| } |
| |
| public void testCancelRead() throws InterruptedException { |
| final IProgressMonitor progressMonitor = new NullProgressMonitor(); |
| this.keepRunning = true; |
| |
| new Thread(() -> status = repo1.executeBatch(monitor -> { |
| long start = System.currentTimeMillis(); |
| while (keepRunning) { |
| long current = System.currentTimeMillis(); |
| if (current - start > 1000 * 10) { |
| fail("Test case never finished. Likely keep running was never set to false."); |
| return; |
| } |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| // Do nothing |
| } |
| } |
| }, new NullProgressMonitor())).start(); |
| |
| // Give the execute batch thread a chance to start |
| Thread.sleep(1000); |
| |
| // Create a thread that will stop our progress monitor |
| Thread t = new Thread(() -> { |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| // Do nothing |
| } |
| progressMonitor.setCanceled(true); |
| }); |
| t.start(); |
| |
| // This should block |
| repo2.getDescriptors(); |
| keepRunning = false; |
| if (status != null && !status.isOK()) { |
| fail(status.getMessage()); |
| } |
| } |
| |
| // The following variables are used in the following test case |
| |
| IStatus status1 = null; |
| IStatus status2 = null; |
| boolean lockAcquired = false; |
| |
| /** |
| * This tests that two 'executeBatch' operations are not executed in |
| * parallel, but rather, the second one waits for the first to complete. |
| * @throws InterruptedException |
| */ |
| public void testMultipleExecuteBatch() throws InterruptedException { |
| this.lockAcquired = false; |
| Thread t1 = new Thread(() -> status1 = repo1.executeBatch(monitor -> { |
| try { |
| if (lockAcquired) |
| throw new RuntimeException("Lock already acquired"); |
| lockAcquired = true; |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| // Do nothing |
| } |
| } finally { |
| lockAcquired = false; |
| } |
| }, new NullProgressMonitor())); |
| t1.start(); |
| |
| Thread t2 = new Thread(() -> status2 = repo2.executeBatch(monitor -> { |
| try { |
| if (lockAcquired) |
| throw new RuntimeException("Lock already acquired"); |
| lockAcquired = true; |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| // Do nothing |
| } |
| } finally { |
| lockAcquired = false; |
| } |
| }, new NullProgressMonitor())); |
| t2.start(); |
| |
| t1.join(); |
| t2.join(); |
| |
| if (!status1.isOK() || !status2.isOK()) |
| fail("Test failed, a lock acquired simultaneously by both execute batch operations"); |
| } |
| |
| /** |
| * This tests that we wait for the lock to come off, we then add a descriptor |
| * @throws InterruptedException |
| */ |
| public void testWait() throws InterruptedException { |
| |
| new Thread(() -> status = repo1.executeBatch(monitor -> { |
| try { |
| Thread.sleep(5000); |
| } catch (InterruptedException e) { |
| // Do nothing |
| } |
| |
| }, new NullProgressMonitor())).start(); |
| |
| // Give the execute batch thread a chance to start |
| Thread.sleep(1000); |
| |
| // This should block for 5 seconds, and then add the descriptor |
| repo2.addDescriptor(new SimpleArtifactDescriptor(new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0"))), new NullProgressMonitor()); |
| assertEquals(1, repo2.getDescriptors().size()); // The descriptor should not have been added |
| } |
| |
| public void testMultipleAddDescriptors() throws InterruptedException { |
| Thread.sleep(1000); |
| repo1.addDescriptor(new SimpleArtifactDescriptor(new ArtifactKey("org.eclipse.test", "test1", Version.create("1.0.0"))), new NullProgressMonitor()); |
| assertEquals(1, repo1.getDescriptors().size()); |
| Thread.sleep(1000); |
| repo2.addDescriptor(new SimpleArtifactDescriptor(new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0"))), new NullProgressMonitor()); |
| assertEquals(2, repo2.getDescriptors().size()); |
| } |
| |
| public void testContainsDescriptor() throws InterruptedException { |
| ArtifactKey k = new ArtifactKey("org.eclipse.test", "test1", Version.create("1.0.0")); |
| SimpleArtifactDescriptor d = new SimpleArtifactDescriptor(k); |
| Thread.sleep(1000); |
| repo1.addDescriptor(d, new NullProgressMonitor()); |
| Thread.sleep(1000); |
| assertTrue(repo2.contains(d)); |
| } |
| |
| public void testContainsKey() throws InterruptedException { |
| ArtifactKey k = new ArtifactKey("org.eclipse.test", "test1", Version.create("1.0.0")); |
| SimpleArtifactDescriptor d = new SimpleArtifactDescriptor(k); |
| Thread.sleep(1000); |
| repo1.addDescriptor(d, new NullProgressMonitor()); |
| Thread.sleep(1000); |
| assertTrue(repo2.contains(k)); |
| } |
| |
| public void testMultipleRemoveDescriptors() throws InterruptedException { |
| SimpleArtifactDescriptor d1 = new SimpleArtifactDescriptor(new ArtifactKey("org.eclipse.test", "test1", Version.create("1.0.0"))); |
| SimpleArtifactDescriptor d2 = new SimpleArtifactDescriptor(new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0"))); |
| |
| Thread.sleep(1000); |
| repo1.addDescriptor(d1, new NullProgressMonitor()); |
| repo1.addDescriptor(d2, new NullProgressMonitor()); |
| assertEquals(2, repo1.getDescriptors().size()); |
| Thread.sleep(1000); |
| repo1.removeDescriptor(d1, new NullProgressMonitor()); |
| assertEquals(1, repo1.getDescriptors().size()); |
| Thread.sleep(1000); |
| repo2.removeDescriptor(d2, new NullProgressMonitor()); |
| assertEquals(0, repo2.getDescriptors().size()); |
| } |
| |
| public void testMultipleRemoveKeys() throws InterruptedException { |
| ArtifactKey k1 = new ArtifactKey("org.eclipse.test", "test1", Version.create("1.0.0")); |
| ArtifactKey k2 = new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0")); |
| SimpleArtifactDescriptor d1 = new SimpleArtifactDescriptor(k1); |
| SimpleArtifactDescriptor d2 = new SimpleArtifactDescriptor(k2); |
| |
| Thread.sleep(1000); |
| repo1.addDescriptor(d1, new NullProgressMonitor()); |
| repo1.addDescriptor(d2, new NullProgressMonitor()); |
| assertEquals(2, repo1.getDescriptors().size()); |
| Thread.sleep(1000); |
| repo1.removeDescriptor(k1, new NullProgressMonitor()); |
| assertEquals(1, repo1.getDescriptors().size()); |
| Thread.sleep(1000); |
| assertEquals(1, repo2.getDescriptors().size()); |
| repo2.removeDescriptor(k2, new NullProgressMonitor()); |
| assertEquals(0, repo2.getDescriptors().size()); |
| } |
| |
| public void testRemoveBulkKeys() throws InterruptedException { |
| ArtifactKey k1 = new ArtifactKey("org.eclipse.test", "test1", Version.create("1.0.0")); |
| ArtifactKey k2 = new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0")); |
| ArtifactKey k3 = new ArtifactKey("org.eclipse.test", "test3", Version.create("1.0.0")); |
| SimpleArtifactDescriptor d1 = new SimpleArtifactDescriptor(k1); |
| SimpleArtifactDescriptor d2 = new SimpleArtifactDescriptor(k2); |
| SimpleArtifactDescriptor d3 = new SimpleArtifactDescriptor(k3); |
| |
| Thread.sleep(1000); |
| repo1.addDescriptor(d1, new NullProgressMonitor()); |
| repo1.addDescriptor(d2, new NullProgressMonitor()); |
| repo1.addDescriptor(d3, new NullProgressMonitor()); |
| assertEquals(3, repo1.getDescriptors().size()); |
| Thread.sleep(1000); |
| repo2.removeDescriptors(new IArtifactKey[] {k1, k2}, new NullProgressMonitor()); |
| Thread.sleep(1000); |
| assertEquals(1, repo2.getDescriptors().size()); |
| assertEquals(1, repo1.getDescriptors().size()); |
| } |
| |
| public void testRemoveBulkDescriptors() throws InterruptedException { |
| ArtifactKey k1 = new ArtifactKey("org.eclipse.test", "test1", Version.create("1.0.0")); |
| ArtifactKey k2 = new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0")); |
| ArtifactKey k3 = new ArtifactKey("org.eclipse.test", "test3", Version.create("1.0.0")); |
| SimpleArtifactDescriptor d1 = new SimpleArtifactDescriptor(k1); |
| SimpleArtifactDescriptor d2 = new SimpleArtifactDescriptor(k2); |
| SimpleArtifactDescriptor d3 = new SimpleArtifactDescriptor(k3); |
| |
| Thread.sleep(1000); |
| repo1.addDescriptor(d1, new NullProgressMonitor()); |
| repo1.addDescriptor(d2, new NullProgressMonitor()); |
| repo1.addDescriptor(d3, new NullProgressMonitor()); |
| assertEquals(3, repo1.getDescriptors().size()); |
| Thread.sleep(1000); |
| repo2.removeDescriptors(new IArtifactDescriptor[] {d1, d2}, new NullProgressMonitor()); |
| Thread.sleep(1000); |
| assertEquals(1, repo2.getDescriptors().size()); |
| assertEquals(1, repo1.getDescriptors().size()); |
| } |
| |
| public void testRemoveAll() throws InterruptedException { |
| ArtifactKey k1 = new ArtifactKey("org.eclipse.test", "test1", Version.create("1.0.0")); |
| ArtifactKey k2 = new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0")); |
| SimpleArtifactDescriptor d1 = new SimpleArtifactDescriptor(k1); |
| SimpleArtifactDescriptor d2 = new SimpleArtifactDescriptor(k2); |
| |
| Thread.sleep(1000); |
| repo1.addDescriptor(d1, new NullProgressMonitor()); |
| repo1.addDescriptor(d2, new NullProgressMonitor()); |
| assertEquals(2, repo1.getDescriptors().size()); |
| Thread.sleep(1000); |
| repo2.removeAll(new NullProgressMonitor()); |
| Thread.sleep(1000); |
| assertEquals(0, repo2.getDescriptors().size()); |
| assertEquals(0, repo1.getDescriptors().size()); |
| } |
| |
| public void testReloadAdds() throws InterruptedException { |
| // Delay 1 second because some operating systems only give 1 second precision |
| Thread.sleep(1000); |
| repo1.addDescriptor(new SimpleArtifactDescriptor(new ArtifactKey("org.eclipse.test", "test1", Version.create("1.0.0"))), new NullProgressMonitor()); |
| Thread.sleep(1000); |
| repo2.addDescriptor(new SimpleArtifactDescriptor(new ArtifactKey("org.eclipse.test", "test2", Version.create("1.0.0"))), new NullProgressMonitor()); |
| |
| assertEquals(2, repo2.getDescriptors().size()); |
| // Does the fist repo get reloaded when reading the descriptors |
| assertEquals(2, repo1.getDescriptors().size()); |
| } |
| |
| public void _testSetProperty() throws InterruptedException { |
| // Delay 1 second because some operating systems only give 1 second precision |
| Thread.sleep(1000); |
| repo1.setProperty("foo", "bar", new NullProgressMonitor()); |
| Thread.sleep(1000); |
| assertEquals("bar", repo1.getProperty("foo")); |
| assertEquals("bar", repo2.getProperty("foo")); |
| } |
| |
| public void _testGetProperties() throws InterruptedException { |
| // Delay 1 second because some operating systems only give 1 second precision |
| Thread.sleep(1000); |
| repo1.setProperty("foo", "bar", new NullProgressMonitor()); |
| Thread.sleep(1000); |
| assertEquals("bar", repo1.getProperties().get("foo")); |
| assertEquals("bar", repo2.getProperties().get("foo")); |
| } |
| |
| public void _testSetName() throws InterruptedException { |
| // Delay 1 second because some operating systems only give 1 second precision |
| Thread.sleep(1000); |
| repo1.setName("Foo"); |
| Thread.sleep(1000); |
| assertEquals("Foo", repo1.getName()); |
| assertEquals("Foo", repo2.getName()); |
| } |
| |
| public void _testSetDescription() throws InterruptedException { |
| // Delay 1 second because some operating systems only give 1 second precision |
| Thread.sleep(1000); |
| repo1.setDescription("Foo Bar"); |
| Thread.sleep(1000); |
| assertEquals("Foo Bar", repo1.getDescription()); |
| assertEquals("Foo Bar", repo2.getDescription()); |
| } |
| |
| } |