diff --git a/TESTING.md b/TESTING.md
index 0c0e5e9e..b9340741 100644
--- a/TESTING.md
+++ b/TESTING.md
@@ -54,16 +54,50 @@ property or `MANTA_IT_NO_CLEANUP` environment variable.
# Running Tests
-Run `mvn verify` from the project root to run all tests. Some Maven goals will
-not work
+Run `mvn verify` from the project root to run all tests. Some Maven goals will not work.
While the Java Cryptography Extensions are expected to be installed, it is
-possible torun a subset of the test suite by adding
-`-DexcludedGroups=unlimited-crypto`, e.g.:
+possible to run a subset of the test suite by adding
+`-DexcludedGroups=unlimited-crypto` or `-Dgroups=headers,error`, e.g.
```
mvn test -DexcludedGroups=unlimited-crypto
+mvn verify -Dgroups=headers,error
```
+Also, if we are running a defined TestNG group, invoke
+`-Dgroups=headers`, e.g:
+
+```
+mvn clean verify -Dgroups=headers
+```
+
+Note: Since we have transitioned from wildcard to explicit test definition (i.e `package-level`
+to `class-level` hierarchy), engineers are required to add integration-tests in `testng-it.xml` file
+complying with the nature of their corresponding TestNG groups. For instance, if we create a new
+integration-test `ExampleHttpHeadersIT.java` for `headers`, that test will be defined under:
+```
+
+
+
+
+
+
+
+
+
+```
+
+## Dry run
+
+The following invocation will print a list of which integration tests would run and their relevant
+parameters::
+
+```
+mvn verify -Dit.dryRun=true
+```
+
+Note: This feature is invalid for unit tests.
+
# Writing Tests
The `java-manta-client` module contains unit tests. Integration tests generally
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientDirectoriesIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientDirectoriesIT.java
index fbe1c5b6..fa5b74cb 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientDirectoriesIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientDirectoriesIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2015-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -29,10 +29,8 @@
/**
* Tests for verifying the correct functioning of making remote requests
* against Manta directories.
- *
- * @author Elijah Zupancic
*/
-@Test(groups = { "directory" })
+@Test(groups = {"directory"})
public class MantaClientDirectoriesIT {
private static final Logger LOG = LoggerFactory.getLogger(MantaClientDirectoriesIT.class);
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientErrorIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientErrorIT.java
index bc05db91..9fd4037d 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientErrorIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientErrorIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2015-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -16,8 +16,6 @@
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Optional;
-import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.io.IOException;
@@ -31,10 +29,8 @@
/**
* Tests for verifying the correct behavior of error handling from Manta API
* failures.
- *
- * @author Elijah Zupancic
*/
-@Test(groups = { "error" })
+@Test(groups = {"error"})
public class MantaClientErrorIT {
private MantaClient mantaClient;
@@ -43,11 +39,9 @@ public class MantaClientErrorIT {
private String testPathPrefix;
@BeforeClass
- @Parameters({"usingEncryption"})
- public void beforeClass(@Optional Boolean usingEncryption) throws IOException {
-
+ public void beforeClass() throws IOException {
// Let TestNG configuration take precedence over environment variables
- config = new IntegrationTestConfigContext(usingEncryption);
+ config = new IntegrationTestConfigContext();
mantaClient = new MantaClient(config);
testPathPrefix = IntegrationTestConfigContext.generateBasePathWithoutSeparator(config,
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientIT.java
index 6ef7dd79..7330d3fe 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientIT.java
@@ -48,33 +48,31 @@
/**
* Tests the basic functionality of the {@link MantaClient} class.
- *
- * @author Yunong Xiao
- * @author Elijah Zupancic
- * @author Ashwin A Nair
*/
-@Test
+@Test(groups = {"encrypted"})
public class MantaClientIT {
private static final String TEST_DATA = "EPISODEII_IS_BEST_EPISODE";
- private MantaClient mantaClient;
+ private final MantaClient mantaClient;
- private String testPathPrefix;
+ private final String testPathPrefix;
- @BeforeClass
- @Parameters({"usingEncryption", "testType"})
- public void beforeClass(@Optional Boolean usingEncryption,
- @Optional String testType) throws IOException {
+ @ Parameters({"encryptionCipher", "testType"})
+ public MantaClientIT(final @Optional String encryptionCipher) {
// Let TestNG configuration take precedence over environment variables
- ConfigContext config = new IntegrationTestConfigContext(usingEncryption);
+
+ ConfigContext config = new IntegrationTestConfigContext(encryptionCipher);
String testName = this.getClass().getSimpleName();
mantaClient = new MantaClient(config);
testPathPrefix = IntegrationTestHelper.setupTestPath(config, mantaClient,
testName, testType);
+ }
+ @BeforeClass
+ public void beforeClass() throws IOException {
IntegrationTestHelper.createTestBucketOrDirectory(mantaClient, testPathPrefix, testType);
}
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientMetadataIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientMetadataIT.java
index ff584923..535222e6 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientMetadataIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientMetadataIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2015-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -24,26 +24,27 @@
/**
* Tests for verifying the behavior of metadata with {@link MantaClient}.
- *
- * @author Elijah Zupancic
*/
-@Test( groups = { "metadata" })
+@Test(groups = {"metadata"})
public class MantaClientMetadataIT {
private static final String TEST_DATA = "EPISODEII_IS_BEST_EPISODE";
- private MantaClient mantaClient;
+ private final MantaClient mantaClient;
- private String testPathPrefix;
+ private final String testPathPrefix;
- @BeforeClass
- @Parameters({"usingEncryption"})
- public void beforeClass(@Optional Boolean usingEncryption) throws IOException {
+ @Parameters({"encryptionCipher"})
+ public MantaClientMetadataIT(final @Optional String encryptionCipher) {
// Let TestNG configuration take precedence over environment variables
- ConfigContext config = new IntegrationTestConfigContext(usingEncryption);
+ ConfigContext config = new IntegrationTestConfigContext(encryptionCipher);
mantaClient = new MantaClient(config);
testPathPrefix = IntegrationTestConfigContext.generateBasePath(config, this.getClass().getSimpleName());
+ }
+
+ @BeforeClass
+ public void beforeClass() throws IOException {
mantaClient.putDirectory(testPathPrefix, true);
}
@@ -148,7 +149,7 @@ public final void verifyCanRemoveMetadata() throws IOException, CloneNotSupporte
String.format("Actual metadata: %s", get.getMetadata()));
}
- @Test(groups = { "metadata", "directory" })
+ @Test
public void canAddMetadataToDirectory() throws IOException {
String dir = String.format("%s%s", testPathPrefix, UUID.randomUUID());
mantaClient.putDirectory(dir);
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientPutIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientPutIT.java
index 0e560b1a..820c5e2f 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientPutIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientPutIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2016-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -41,7 +41,10 @@
import static com.joyent.manta.exception.MantaErrorCode.RESOURCE_NOT_FOUND_ERROR;
-@Test
+/**
+ * Tests the basic functionality of the put operations in {@link MantaClient} class.
+ */
+@Test(groups = {"put"})
public class MantaClientPutIT {
private static final String TEST_DATA = "EPISODEII_IS_BEST_EPISODE";
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientRangeIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientRangeIT.java
index bc9a963a..3d09df2b 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientRangeIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientRangeIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2017-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -7,7 +7,11 @@
*/
package com.joyent.manta.client;
-import com.joyent.manta.config.*;
+import com.joyent.manta.config.BaseChainedConfigContext;
+import com.joyent.manta.config.ConfigContext;
+import com.joyent.manta.config.EncryptionAuthenticationMode;
+import com.joyent.manta.config.IntegrationTestConfigContext;
+import com.joyent.manta.config.SettableConfigContext;
import com.joyent.manta.http.MantaHttpHeaders;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
@@ -23,6 +27,10 @@
import java.nio.charset.Charset;
import java.util.UUID;
+/**
+ * Tests for verifying the correct behavior of range operations performed by
+ * the {@link MantaClient} class.
+ */
@Test
public class MantaClientRangeIT {
private static final String TEST_DATA =
@@ -49,23 +57,30 @@ public class MantaClientRangeIT {
"Girt with a seint* of silk, with barres small; " +
"Of his array tell I no longer tale.";
- private MantaClient mantaClient;
+ private final MantaClient mantaClient;
- private String testPathPrefix;
+ private final ConfigContext config;
- @BeforeClass
- @Parameters({"usingEncryption"})
- public void beforeClass(@Optional Boolean usingEncryption) throws IOException {
- // Let TestNG configuration take precedence over environment variables
- SettableConfigContext config = new IntegrationTestConfigContext(usingEncryption);
+ private final String testPathPrefix;
+ @Parameters({"encryptionCipher"})
+ public MantaClientRangeIT(final @Optional String encryptionCipher) {
+
+ // Let TestNG configuration take precedence over environment variables
+ SettableConfigContext config = new IntegrationTestConfigContext(encryptionCipher);
// Range request have to be in optional authentication mode
if (config.isClientEncryptionEnabled()) {
config.setEncryptionAuthenticationMode(EncryptionAuthenticationMode.Optional);
}
mantaClient = new MantaClient(config);
+ this.config = config;
testPathPrefix = IntegrationTestConfigContext.generateBasePath(config, this.getClass().getSimpleName());
+
+ }
+
+ @BeforeClass
+ public void beforeClass() throws IOException {
mantaClient.putDirectory(testPathPrefix, true);
}
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientSeekableByteChannelIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientSeekableByteChannelIT.java
index b8ba6630..69de4977 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientSeekableByteChannelIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientSeekableByteChannelIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2015-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -34,24 +34,19 @@
/**
* Tests for verifying the behavior of {@link SeekableByteChannel} with
* {@link MantaClient}.
- *
- * @author Elijah Zupancic
*/
-@Test(groups = { "seekable" })
+@Test(groups = {"seekable", "encrypted"})
public class MantaClientSeekableByteChannelIT {
private static final String TEST_DATA = "EPISODEII_IS_BEST_EPISODE";
- private MantaClient mantaClient;
-
- private String testPathPrefix;
+ private final MantaClient mantaClient;
+ private final String testPathPrefix;
- @BeforeClass
- @Parameters({"usingEncryption"})
- public void beforeClass(@Optional Boolean usingEncryption) throws IOException {
-
+ @Parameters({"encryptionCipher"})
+ public MantaClientSeekableByteChannelIT(final @Optional String encryptionCipher) {
// Let TestNG configuration take precedence over environment variables
- SettableConfigContext config = new IntegrationTestConfigContext(usingEncryption);
+ SettableConfigContext config = new IntegrationTestConfigContext(encryptionCipher);
// Range request have to be in optional authentication mode
if (config.isClientEncryptionEnabled()) {
@@ -60,6 +55,10 @@ public void beforeClass(@Optional Boolean usingEncryption) throws IOException {
mantaClient = new MantaClient(config);
testPathPrefix = IntegrationTestConfigContext.generateBasePath(config, this.getClass().getSimpleName());
+ }
+
+ @BeforeClass
+ public void beforeClass() throws IOException {
mantaClient.putDirectory(testPathPrefix, true);
}
@@ -68,7 +67,6 @@ public void afterClass() throws IOException {
IntegrationTestConfigContext.cleanupTestDirectory(mantaClient, testPathPrefix);
}
- @Test
public final void seekableByteSize() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
@@ -82,7 +80,6 @@ public final void seekableByteSize() throws IOException {
}
}
- @Test
public final void getAllSeekableBytes() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
@@ -94,7 +91,6 @@ public final void getAllSeekableBytes() throws IOException {
}
}
- @Test
public final void getAllSeekableBytesAtPosition() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
@@ -109,7 +105,6 @@ public final void getAllSeekableBytesAtPosition() throws IOException {
}
}
- @Test
public final void readFromDifferentPositions() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
@@ -133,7 +128,6 @@ public final void readFromDifferentPositions() throws IOException {
}
}
- @Test
public final void readAllSeekableBytesFromPositionAsInputStream() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
@@ -157,7 +151,6 @@ public final void readAllSeekableBytesFromPositionAsInputStream() throws IOExcep
}
}
- @Test
public final void skipUsingInputStream() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
@@ -223,7 +216,6 @@ public final void attemptToWrite() throws IOException {
}
}
- @Test( groups = { "seekable" })
public final void getFromForwardPosition() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
@@ -241,7 +233,6 @@ public final void getFromForwardPosition() throws IOException {
}
}
- @Test( groups = { "seekable" } )
public final void getFromBaseChannelThenForwardPosition() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
@@ -262,7 +253,6 @@ public final void getFromBaseChannelThenForwardPosition() throws IOException {
}
}
- @Test( groups = { "seekable" } )
public final void getFromForwardPositionThenBackwardPosition() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientSnapLinksIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientSnapLinksIT.java
index d5fb3c18..feb29686 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientSnapLinksIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/MantaClientSnapLinksIT.java
@@ -37,7 +37,7 @@
*
* @author Ashwin A Nair
*/
-@Test(groups = "snaplinks")
+@Test(groups = {"snaplinks"})
public class MantaClientSnapLinksIT {
private static final Logger LOG = LoggerFactory.getLogger(MantaClientSnapLinksIT.class);
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/MantaDirectoryListingIteratorIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/MantaDirectoryListingIteratorIT.java
index 07944c7b..bed30910 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/MantaDirectoryListingIteratorIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/MantaDirectoryListingIteratorIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2015-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -12,8 +12,6 @@
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Optional;
-import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.io.IOException;
@@ -24,10 +22,8 @@
/**
* Tests the proper functioning of the dynamically paging iterator.
- *
- * @author Elijah Zupancic
*/
-@Test
+@Test(groups={"directory"})
public class MantaDirectoryListingIteratorIT {
private static final String TEST_DATA = "EPISODEII_IS_BEST_EPISODE";
@@ -36,11 +32,10 @@ public class MantaDirectoryListingIteratorIT {
private String testPathPrefix;
@BeforeClass
- @Parameters({"usingEncryption"})
- public void beforeClass(@Optional Boolean usingEncryption) throws IOException {
+ public void beforeClass() throws IOException {
// Let TestNG configuration take precedence over environment variables
- final ConfigContext config = new IntegrationTestConfigContext(usingEncryption);
+ ConfigContext config = new IntegrationTestConfigContext();
mantaClient = new MantaClient(config);
testPathPrefix = IntegrationTestConfigContext.generateBasePath(config, this.getClass().getSimpleName());
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/MantaObjectOutputStreamIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/MantaObjectOutputStreamIT.java
index a666aaa9..8df6a648 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/MantaObjectOutputStreamIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/MantaObjectOutputStreamIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2016-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -29,23 +29,30 @@
import java.security.MessageDigest;
import java.util.UUID;
-@Test
+/**
+ * Tests for verifying the behavior of {@link MantaObjectOutputStream} with
+ * {@link MantaClient}.
+ */
+@Test(groups = {"encrypted"})
public class MantaObjectOutputStreamIT {
private static final String TEST_DATA = "EPISODEII_IS_BEST_EPISODE";
- private MantaClient mantaClient;
+ private final MantaClient mantaClient;
- private String testPathPrefix;
+ private final String testPathPrefix;
- @BeforeClass()
- @Parameters({"usingEncryption"})
- public void beforeClass(@Optional Boolean usingEncryption) throws IOException {
+ @Parameters({"encryptionCipher"})
+ public MantaObjectOutputStreamIT(final @Optional String encryptionCipher) throws IOException {
// Let TestNG configuration take precedence over environment variables
- ConfigContext config = new IntegrationTestConfigContext(usingEncryption);
+ ConfigContext config = new IntegrationTestConfigContext(encryptionCipher);
mantaClient = new MantaClient(config);
testPathPrefix = IntegrationTestConfigContext.generateBasePath(config, this.getClass().getSimpleName());
+ }
+
+ @BeforeClass()
+ public void beforeClass() throws IOException {
mantaClient.putDirectory(testPathPrefix, true);
}
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/jobs/MantaClientJobIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/jobs/MantaClientJobIT.java
index 2f891f4e..7549ca49 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/jobs/MantaClientJobIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/jobs/MantaClientJobIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2015-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -33,10 +33,8 @@
/**
* Tests the execution of Manta compute jobs.
- *
- * @author Elijah Zupancic
*/
-@Test(groups = { "job" }, retryAnalyzer = ThreeTriesRetryAnalyzer.class)
+@Test(groups = { "expensive" }, retryAnalyzer = ThreeTriesRetryAnalyzer.class)
public class MantaClientJobIT {
private static final Logger LOG = LoggerFactory.getLogger(MantaClientJobIT.class);
@@ -66,7 +64,7 @@ public void cleanup() throws IOException {
IntegrationTestConfigContext.cleanupTestDirectory(mantaClient, testPathPrefix);
}
- @Test
+ @Test(groups = { "expensive" })
public void createJob() throws IOException {
MantaJob job = buildJob();
UUID jobId = mantaClient.createJob(job);
@@ -76,7 +74,7 @@ public void createJob() throws IOException {
Assert.assertTrue(accepted, "Cancel request was not accepted");
}
- @Test(dependsOnMethods = { "createJob" })
+ @Test(groups = { "expensive" }, dependsOnMethods = { "createJob" })
public void getJob() throws IOException {
MantaJob job = buildJob();
UUID jobId = mantaClient.createJob(job);
@@ -169,7 +167,7 @@ public void canAddAndGetInputsFromStream() throws IOException {
}
}
- @Test(dependsOnMethods = { "createJob", "getJob" })
+ @Test(dependsOnMethods = { "createJob", "getJob" }, groups = { "expensive" })
public void canListAllJobIDs() throws IOException, InterruptedException {
final MantaJob job1 = buildJob();
final UUID job1id = mantaClient.createJob(job1);
@@ -199,7 +197,7 @@ public void canListAllJobIDs() throws IOException, InterruptedException {
* and development environments. The code path for testing job lists is
* tested elsewhere, but not the specific operation of listing ALL jobs.
*/
- @Test(enabled = false, dependsOnMethods = { "createJob", "getJob" })
+ @Test(dependsOnMethods = { "createJob", "getJob" }, groups = { "expensive" })
public void canListAllJobs() throws IOException, InterruptedException {
final MantaJob job1 = buildJob();
final UUID job1id = mantaClient.createJob(job1);
@@ -230,7 +228,7 @@ public void canListAllJobs() throws IOException, InterruptedException {
}
}
- @Test(dependsOnMethods = { "createJob", "getJob" })
+ @Test(dependsOnMethods = { "createJob", "getJob" }, groups = { "expensive" })
public void canListAllRunningJobIDs() throws IOException, InterruptedException {
final MantaJob job1 = buildJob();
final UUID job1id = mantaClient.createJob(job1);
@@ -263,7 +261,7 @@ public void canListAllRunningJobIDs() throws IOException, InterruptedException {
}
}
- @Test(dependsOnMethods = { "createJob", "getJob" })
+ @Test(dependsOnMethods = { "createJob", "getJob" }, groups = { "expensive" })
public void canListAllRunningJobs() throws IOException, InterruptedException {
final MantaJob job1 = buildJob();
final UUID job1id = mantaClient.createJob(job1);
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/jobs/MantaJobBuilderIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/jobs/MantaJobBuilderIT.java
index 0afbeeff..eb5c31d3 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/jobs/MantaJobBuilderIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/jobs/MantaJobBuilderIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2015-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -27,10 +27,8 @@
/**
* Tests the execution of Manta compute jobs using the builder fluent interface.
- *
- * @author Elijah Zupancic
*/
-@Test(dependsOnGroups = "job")
+@Test
public class MantaJobBuilderIT {
private static final String TEST_DATA =
"line 01 aa\n"
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedJobsMultipartManagerIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedJobsMultipartManagerIT.java
index 9b11310b..d5e8b519 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedJobsMultipartManagerIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedJobsMultipartManagerIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2017-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -55,7 +55,7 @@
/* Tests are disabled because functionality is obsolete and overall test runtime
* is very long and expensive. */
@Deprecated
-@Test(groups = { "encrypted" }, enabled = false)
+@Test(groups = { "expensive" }, enabled = false)
public class EncryptedJobsMultipartManagerIT {
private MantaClient mantaClient;
private EncryptedJobsMultipartManager multipart;
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedServerSideMultipartManagerIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedServerSideMultipartManagerIT.java
index 835f63ea..ac4a86d6 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedServerSideMultipartManagerIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedServerSideMultipartManagerIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2017-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -27,7 +27,6 @@
import org.testng.SkipException;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.io.ByteArrayInputStream;
@@ -46,29 +45,41 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
-@Test(groups = { "encrypted" })
+/**
+ * Tests for verifying the behavior of {@link EncryptedServerSideMultipartManager} with
+ * {@link MantaClient}.
+ */
+@Test(groups = {"encrypted", "expensive"})
@SuppressWarnings("Duplicates")
public class EncryptedServerSideMultipartManagerIT {
- private MantaClient mantaClient;
+ private final MantaClient mantaClient;
+
+ private final ConfigContext config;
- private EncryptedServerSideMultipartManager multipart;
+ private final EncryptedServerSideMultipartManager multipart;
private static final int FIVE_MB = 5242880;
private static final String TEST_FILENAME = "Master-Yoda.jpg";
- private String testPathPrefix;
+ private final String testPathPrefix;
+
+ public EncryptedServerSideMultipartManagerIT(final @org.testng.annotations.Optional String encryptionCipher) {
- @BeforeClass()
- @Parameters({"usingEncryption"})
- public void beforeClass(@org.testng.annotations.Optional Boolean usingEncryption) throws IOException {
// Let TestNG configuration take precedence over environment variables
- ConfigContext config = new IntegrationTestConfigContext(usingEncryption);
+ config = new IntegrationTestConfigContext(encryptionCipher);
+
+ mantaClient = new MantaClient(config);
+
+ multipart = new EncryptedServerSideMultipartManager(this.mantaClient);
+ testPathPrefix = IntegrationTestConfigContext.generateBasePath(config, this.getClass().getSimpleName());
+ }
+ @BeforeClass()
+ public void beforeClass() throws IOException {
if (!config.isClientEncryptionEnabled()) {
throw new SkipException("Skipping tests if encryption is disabled");
}
- mantaClient = new MantaClient(config);
// sanity check
if (!mantaClient.existsAndIsAccessible(config.getMantaHomeDirectory())) {
@@ -80,8 +91,6 @@ public void beforeClass(@org.testng.annotations.Optional Boolean usingEncryption
throw new SkipException("Server side uploads aren't supported in this Manta version");
}
- multipart = new EncryptedServerSideMultipartManager(this.mantaClient);
- testPathPrefix = IntegrationTestConfigContext.generateBasePath(config, this.getClass().getSimpleName());
mantaClient.putDirectory(testPathPrefix, true);
}
@@ -116,6 +125,7 @@ public final void canAbortUpload() throws IOException {
}
}
+ @Test(groups = {"expensive"})
public final void canListUploadsInProgress() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedServerSideMultipartManagerSerializationIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedServerSideMultipartManagerSerializationIT.java
index 09a33c52..6dba5158 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedServerSideMultipartManagerSerializationIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/multipart/EncryptedServerSideMultipartManagerSerializationIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2017-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -24,7 +24,7 @@
import org.testng.SkipException;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Parameters;
+import org.testng.annotations.Optional;
import org.testng.annotations.Test;
import java.io.IOException;
@@ -36,40 +36,48 @@
import static org.testng.Assert.fail;
-@Test(groups = { "encrypted" })
+/**
+ * Tests for verifying the behavior of {@link com.joyent.manta.serialization.EncryptedMultipartSerializer}
+ * and {@link EncryptedServerSideMultipartManager} with {@link MantaClient}.
+ */
+@Test(groups = {"encrypted"})
@SuppressWarnings("Duplicates")
public class EncryptedServerSideMultipartManagerSerializationIT {
- private static final Logger LOGGER = LoggerFactory.getLogger
- (EncryptedServerSideMultipartManagerSerializationIT.class);
- private MantaClient mantaClient;
- private EncryptedServerSideMultipartManager multipart;
+ private static final Logger LOGGER = LoggerFactory.getLogger(EncryptedServerSideMultipartManagerSerializationIT.class);
+
+ private final MantaClient mantaClient;
+
+ private final EncryptedServerSideMultipartManager multipart;
private static final int FIVE_MB = 5242880;
- private String testPathPrefix;
+ private final String testPathPrefix;
private Kryo kryo = new Kryo();
- private ConfigContext config;
+ private final ConfigContext config;
- @BeforeClass()
- @Parameters({"usingEncryption"})
- public void beforeClass(@org.testng.annotations.Optional Boolean usingEncryption) throws IOException {
+ public EncryptedServerSideMultipartManagerSerializationIT(final @Optional String encryptionCipher) {
// Let TestNG configuration take precedence over environment variables
- this.config = new IntegrationTestConfigContext(usingEncryption);
+ config = new IntegrationTestConfigContext(encryptionCipher);
+
+ mantaClient = new MantaClient(config);
+
+ multipart = new EncryptedServerSideMultipartManager(this.mantaClient);
+ testPathPrefix = IntegrationTestConfigContext.generateBasePath(config, this.getClass().getSimpleName());
+ }
+ @BeforeClass()
+ public void beforeClass() throws IOException {
if (!config.isClientEncryptionEnabled()) {
throw new SkipException("Skipping tests if encryption is disabled");
}
- mantaClient = new MantaClient(config);
if (!mantaClient.existsAndIsAccessible(config.getMantaHomeDirectory()
+ MantaClient.SEPARATOR + "uploads")) {
throw new SkipException("Server side uploads aren't supported in this Manta version");
}
- multipart = new EncryptedServerSideMultipartManager(this.mantaClient);
- testPathPrefix = IntegrationTestConfigContext.generateBasePath(config, this.getClass().getSimpleName());
mantaClient.putDirectory(testPathPrefix, true);
}
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/multipart/JobsMultipartManagerIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/multipart/JobsMultipartManagerIT.java
index 293b05a8..77606790 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/multipart/JobsMultipartManagerIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/multipart/JobsMultipartManagerIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2016-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -52,7 +52,7 @@
/* Tests are disabled because functionality is obsolete and overall test runtime
* is very long and expensive. */
@Deprecated
-@Test(enabled = false)
+@Test(groups = { "expensive" }, enabled = false)
public class JobsMultipartManagerIT {
private MantaClient mantaClient;
private JobsMultipartManager multipart;
diff --git a/java-manta-it/src/test/java/com/joyent/manta/client/multipart/ServerSideMultipartManagerIT.java b/java-manta-it/src/test/java/com/joyent/manta/client/multipart/ServerSideMultipartManagerIT.java
index 7b0486b4..b0605eae 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/client/multipart/ServerSideMultipartManagerIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/client/multipart/ServerSideMultipartManagerIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2017-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -37,7 +37,7 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
-@Test
+@Test(groups = {"expensive" })
@SuppressWarnings("Duplicates")
public class ServerSideMultipartManagerIT {
private MantaClient mantaClient;
@@ -91,6 +91,7 @@ public final void canAbortUpload() throws IOException {
}
}
+ @Test(groups = { "expensive" })
public final void canListUploadsInProgress() throws IOException {
final String name = UUID.randomUUID().toString();
final String path = testPathPrefix + name;
diff --git a/java-manta-it/src/test/java/com/joyent/manta/config/IntegrationTestConfigContext.java b/java-manta-it/src/test/java/com/joyent/manta/config/IntegrationTestConfigContext.java
index a7727c41..33a236d0 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/config/IntegrationTestConfigContext.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/config/IntegrationTestConfigContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2015-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -28,6 +28,7 @@
* and allows for TestNG parameters to be loaded.
*
* @author Elijah Zupancic
+ * @author Ashwin A Nair
*/
public class IntegrationTestConfigContext extends SystemSettingsConfigContext {
@@ -52,6 +53,15 @@ public IntegrationTestConfigContext(Boolean usingEncryption) {
BooleanUtils.isTrue(usingEncryption), encryptionCipher()));
}
+ /**
+ * Populate configuration from defaults, environment variables, system
+ * properties and an addition context passed in. Assigns hard-coded
+ * client-side encryption cipher algorithm settings.
+ */
+ public IntegrationTestConfigContext(final String encryptionCipher) {
+ this(encryptionCipher != null, encryptionCipher);
+ }
+
/**
* Populate configuration from defaults, environment variables, system
* properties and an addition context passed in. Assigns hard-coded
@@ -84,7 +94,10 @@ private static SettableConfigContext enableTestEncryption(
SecretKey key = SecretKeyUtils.generate(cipherDetails);
context.setEncryptionPrivateKeyBytes(key.getEncoded());
- System.out.printf("Unique secret key used for test (base64):\n%s\n",
+ System.out.printf(
+ "Integration test encryption enabled: %s\n"
+ + "Unique secret key used for test (base64):\n%s\n",
+ cipherDetails.getCipherId(),
Base64.getEncoder().encodeToString(key.getEncoded()));
}
diff --git a/java-manta-it/src/test/java/com/joyent/manta/http/ApacheHttpGetResponseEntityContentContinuatorIT.java b/java-manta-it/src/test/java/com/joyent/manta/http/ApacheHttpGetResponseEntityContentContinuatorIT.java
index 7384dda8..9b7aa9ef 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/http/ApacheHttpGetResponseEntityContentContinuatorIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/http/ApacheHttpGetResponseEntityContentContinuatorIT.java
@@ -124,7 +124,7 @@
* HTTP it provides no way to terminate in-flight requests.
*
*/
-@Test(singleThreaded = true)
+@Test(groups = {"range-downloads"}, singleThreaded = true)
public class ApacheHttpGetResponseEntityContentContinuatorIT {
private static final Logger LOG = LoggerFactory.getLogger(ApacheHttpGetResponseEntityContentContinuatorIT.class);
diff --git a/java-manta-it/src/test/java/com/joyent/manta/http/TCPSocketConnectionTimeoutIT.java b/java-manta-it/src/test/java/com/joyent/manta/http/TCPSocketConnectionTimeoutIT.java
index 0e7f3405..eb819a57 100644
--- a/java-manta-it/src/test/java/com/joyent/manta/http/TCPSocketConnectionTimeoutIT.java
+++ b/java-manta-it/src/test/java/com/joyent/manta/http/TCPSocketConnectionTimeoutIT.java
@@ -32,7 +32,7 @@
*
* @author Ashwin A Nair
*/
-@Test
+@Test(groups = {"timeout"})
public class TCPSocketConnectionTimeoutIT {
private MantaClient mantaClient;
diff --git a/java-manta-it/src/test/java/com/joyent/test/util/MantaPathSuiteListener.java b/java-manta-it/src/test/java/com/joyent/test/util/MantaPathSuiteListener.java
index 75f4c844..c87d5373 100644
--- a/java-manta-it/src/test/java/com/joyent/test/util/MantaPathSuiteListener.java
+++ b/java-manta-it/src/test/java/com/joyent/test/util/MantaPathSuiteListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2017-2019, Joyent, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -10,6 +10,8 @@
import com.joyent.manta.client.MantaClient;
import com.joyent.manta.config.ConfigContext;
import com.joyent.manta.config.IntegrationTestConfigContext;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.ISuite;
@@ -32,8 +34,18 @@ public void onStart(ISuite suite) {
@Override
public void onFinish(ISuite suite) {
+ LOG.info("Expected test count: " + TestListingInterceptor.getObservedTestCount());
+
MantaClient mantaClient = new MantaClient(config);
String path = IntegrationTestConfigContext.generateSuiteBasePath(config);
+
+ if (ObjectUtils.firstNonNull(
+ BooleanUtils.toBoolean(System.getProperty("it.dryRun")),
+ false)) {
+ LOG.warn("Skipping suite cleanup since dry-run is enabled.");
+ return;
+ }
+
try {
if (mantaClient.isDirectoryEmpty(path)) {
LOG.info("Removing base suite path: {}", path);
diff --git a/java-manta-it/src/test/java/com/joyent/test/util/TestListingInterceptor.java b/java-manta-it/src/test/java/com/joyent/test/util/TestListingInterceptor.java
new file mode 100644
index 00000000..587c875f
--- /dev/null
+++ b/java-manta-it/src/test/java/com/joyent/test/util/TestListingInterceptor.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2019, Joyent, Inc. All rights reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+package com.joyent.test.util;
+
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.IMethodInstance;
+import org.testng.IMethodInterceptor;
+import org.testng.ISuite;
+import org.testng.ISuiteListener;
+import org.testng.ITestContext;
+import org.testng.ITestNGMethod;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * Test method listener for determining which tests will actually run
+ * when we invoke mvn verify -Dit.dryRun=true. This test listener has
+ * been introduced to leverage TestNG feature since version 6.8.21 of determining
+ * order of tests without executing them.
+ *
+ * Enabled by: -Dit.dryRun=true
+ * @see Feature Reference
+ * @author Ashwin A Nair
+ */
+public class TestListingInterceptor implements IMethodInterceptor, ISuiteListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TestListingInterceptor.class);
+
+ private static final List EMPTY_LIST = new ArrayList<>(0);
+
+ private static final ConcurrentLinkedQueue observedTests = new ConcurrentLinkedQueue<>();
+
+ private static final boolean DRY_RUN_ENABLED;
+
+ static {
+ DRY_RUN_ENABLED = ObjectUtils.firstNonNull(
+ BooleanUtils.toBoolean(System.getProperty("it.dryRun")),
+ false);
+ }
+
+ public static int getObservedTestCount() {
+ return observedTests.size();
+ }
+
+ /**
+ * This method is used to alter the list of test methods that TestNG
+ * is about to run. It returns an empty list if -Dit.dryRun=false
+ *
+ * @param methods represents list of test methods that will be running.
+ * @param context passed in intercept method so implementers set user values and look-up while generating reports.
+ * @return list of methods run by TestNG consistent with the order returned.
+ */
+ @Override
+ public List intercept(final List methods, final ITestContext context) {
+ for (final IMethodInstance method : methods) {
+ final ITestNGMethod testNGMethod = method.getMethod();
+ final String testName = testNGMethod.getQualifiedName();
+ final Map params = testNGMethod.findMethodParameters(testNGMethod.getXmlTest());
+ final String paramsDetails = !params.isEmpty() ? params.toString() : "";
+ observedTests.add(testName + ' ' + paramsDetails);
+ }
+
+ if (DRY_RUN_ENABLED) {
+ return EMPTY_LIST;
+ }
+
+ return methods;
+ }
+
+ @Override
+ public void onStart(final ISuite suite) {
+ }
+
+ @Override
+ public void onFinish(final ISuite suite) {
+ if (!DRY_RUN_ENABLED) {
+ return;
+ }
+
+ if (LOG.isInfoEnabled()) {
+ LOG.info("DRY-RUN: Listing [{}] tests that would have run",
+ observedTests.size());
+ try (Stream stream = observedTests.stream()) {
+ stream.sorted().forEach(LOG::info);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/java-manta-it/src/test/resources/testng-it.xml b/java-manta-it/src/test/resources/testng-it.xml
index 4183ee47..5e9d219c 100644
--- a/java-manta-it/src/test/resources/testng-it.xml
+++ b/java-manta-it/src/test/resources/testng-it.xml
@@ -3,6 +3,7 @@
+
@@ -11,67 +12,109 @@
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
@@ -80,9 +123,4 @@
-
-
-
-
-