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
12 changes: 12 additions & 0 deletions src/test/java/com/aliyun/tea/TeaModelTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -801,5 +801,17 @@ public void confirmTypeTest() {
object6 = TeaModel.confirmType(String.class, list);
Assert.assertEquals("[\"1\",2,true,{\"sub\":\"sub\"}]", object6);

Assert.assertNull(TeaModel.parseObject(null));
try {
TeaModel.confirmType(Float.class, "not-a-float");
Assert.fail();
} catch (NumberFormatException ignored) {
}
try {
TeaModel.confirmType(Double.class, "not-a-double");
Assert.fail();
} catch (NumberFormatException ignored) {
}
Assert.assertEquals(1L, TeaModel.confirmType(Long.class, 1.5F));
}
}
17 changes: 17 additions & 0 deletions src/test/java/com/aliyun/tea/TeaResponseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,21 @@ public void getResponseBodyTest() throws Exception{
response.body = new ByteArrayInputStream("test".getBytes("UTF-8"));
Assert.assertEquals("test", response.getResponseBody());
}

@Test
public void getResponseBodyExceptionTest() {
TeaResponse response = new TeaResponse();
response.body = new InputStream() {
@Override
public int read() throws java.io.IOException {
throw new java.io.IOException("read failed");
}
};
try {
response.getResponseBody();
Assert.fail();
} catch (TeaException e) {
Assert.assertEquals("read failed", e.getMessage());
}
}
}
40 changes: 40 additions & 0 deletions src/test/java/com/aliyun/tea/TeaTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,44 @@ public void toReadableTest() throws IOException {
String result = new String(bytes, 0, index);
Assert.assertTrue(str.equals(result));
}

@Test
public void doActionWithNullChainTest() {
ClientHelper.clients.clear();
TeaRequest request = new TeaRequest();
Map<String, String> map = new HashMap<>();
map.put("host", "www.google.com.hk");
request.protocol = "http";
request.headers = map;
request.method = "GET";
Map<String, Object> runtimeOptions = new HashMap<>();
runtimeOptions.put("readTimeout", "50000");
runtimeOptions.put("connectTimeout", "50000");
TeaResponse response = Tea.doAction(request, runtimeOptions, null);
Assert.assertEquals(200, response.statusCode);
}

@Test
public void toWriteableTest() {
Assert.assertNotNull(Tea.toWriteable(16));
try {
Tea.toWriteable(-1);
Assert.fail();
} catch (TeaException e) {
Assert.assertNotNull(e.getMessage());
}
}

@Test
public void sleepInterruptedTest() {
Thread.currentThread().interrupt();
try {
Tea.sleep(1000);
Assert.fail();
} catch (TeaException e) {
Assert.assertNotNull(e.getMessage());
} finally {
Thread.interrupted();
}
}
}
37 changes: 37 additions & 0 deletions src/test/java/com/aliyun/tea/logging/LoggerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,41 @@ public void errorTest() {
logger.error("test: {}, {}", "key1", "key2");
logger.error("test: {}, {}, {}", "key1", "key2", "key3");
}

@Test
public void defaultLoggerOverloadsTest() {
System.setProperty(DefaultLogger.SDK_LOG_LEVEL, "verbose");
DefaultLogger logger = new DefaultLogger("com.aliyun.tea.logging.NotExistClass");
Assert.assertEquals("com.aliyun.tea.logging.NotExistClass", logger.getName());

logger.trace("trace {}", "a");
logger.trace("trace", new RuntimeException("t"));
logger.debug("debug {}", "a");
logger.debug("debug {} {}", "a", "b");
logger.debug("debug", new RuntimeException("d"));
logger.info("info {}", "a");
logger.info("info {} {}", "a", "b");
logger.info("info", new RuntimeException("i"));
logger.warn("warn {}", "a");
logger.warn("warn {} {}", "a", "b");
logger.warn("warn", new RuntimeException("w"));
logger.error("error {}", "a");
logger.error("error {} {}", "a", "b");
logger.error("error", new RuntimeException("e"));
}

@Test
public void logLevelFromStringNullTest() {
Assert.assertEquals(LogLevel.NOT_SET, LogLevel.fromString(null));
}

@Test
public void clientLoggerThrowableInArgsTest() {
System.setProperty(DefaultLogger.SDK_LOG_LEVEL, "warn");
ClientLogger logger = new ClientLogger(LoggerTest.class);
logger.warning("warn with throwable: {}", "x", new RuntimeException("warn-ex"));
logger.error("error with throwable: {}", "y", new RuntimeException("error-ex"));
logger.verbose("empty-args");
logger.verbose("format-only", new Object[0]);
}
}
5 changes: 5 additions & 0 deletions src/test/java/com/aliyun/tea/okhttp/ClientHelperTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public void getClientKeyTest() throws NoSuchMethodException, InvocationTargetExc
map.put("callTimeout", null);
str = (String) getClientKey.invoke(ClientHelper.class, "0:0:0:0:0:0:0:1", 0, map);
Assert.assertEquals("0:0:0:0:0:0:0:1:0:http://127.0.0.1:80:https://127.0.0.1:80:socks5://user:password@127.0.0.1:1080:1000:2000:false", str);

map.put("keepAliveDuration", 10000);
map.put("maxIdleConns", 5);
str = (String) getClientKey.invoke(ClientHelper.class, "0:0:0:0:0:0:0:1", 0, map);
Assert.assertEquals("0:0:0:0:0:0:0:1:0:http://127.0.0.1:80:https://127.0.0.1:80:socks5://user:password@127.0.0.1:1080:1000:2000:10000:5:false", str);
}

@Test
Expand Down
163 changes: 162 additions & 1 deletion src/test/java/com/aliyun/tea/okhttp/OkHttpClientBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,113 @@
import com.aliyun.tea.utils.DefaultHostnameVerifier;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Route;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

public class OkHttpClientBuilderTest {
private Map<String, Object> map = new HashMap<>();

/**
* Build an ephemeral self-signed CA PEM at runtime (CN under *.local / UnitTestFixture).
* No production certificates or private keys are committed to the repository.
*/
private static String createEphemeralSelfSignedCaPem(String commonName) throws Exception {
Path workDir = Files.createTempDirectory("tea-java-test-ca-");
Path keystore = workDir.resolve("test-ca.p12");
Path pemFile = workDir.resolve("test-ca.pem");
try {
Path keytool = resolveKeytool();
runKeytool(keytool,
"-genkeypair",
"-alias", "testca",
"-keyalg", "RSA",
"-keysize", "2048",
"-validity", "1",
"-dname", "CN=" + commonName + ",OU=UnitTestFixture,O=AliyunTeaJavaTest,C=CN",
"-keystore", keystore.toString(),
"-storetype", "PKCS12",
"-storepass", "changeit",
"-keypass", "changeit",
"-noprompt");
runKeytool(keytool,
"-exportcert",
"-alias", "testca",
"-keystore", keystore.toString(),
"-storetype", "PKCS12",
"-storepass", "changeit",
"-rfc",
"-file", pemFile.toString());
byte[] pemBytes = Files.readAllBytes(pemFile);
return new String(pemBytes, StandardCharsets.US_ASCII);
} finally {
deleteRecursively(workDir);
}
}

private static Path resolveKeytool() {
Path keytool = java.nio.file.Paths.get(System.getProperty("java.home"), "bin", "keytool");
if (!Files.isExecutable(keytool)) {
keytool = java.nio.file.Paths.get(System.getProperty("java.home"), "bin", "keytool.exe");
}
Assert.assertTrue("keytool not found under java.home", Files.isExecutable(keytool));
return keytool;
}

private static void runKeytool(Path keytool, String... args) throws Exception {
String[] command = new String[args.length + 1];
command[0] = keytool.toString();
System.arraycopy(args, 0, command, 1, args.length);
Process process = new ProcessBuilder(command)
.redirectErrorStream(true)
.start();
ByteArrayOutputStream output = new ByteArrayOutputStream();
try (InputStream in = process.getInputStream()) {
byte[] buf = new byte[1024];
int n;
while ((n = in.read(buf)) >= 0) {
output.write(buf, 0, n);
}
}
if (!process.waitFor(60, TimeUnit.SECONDS)) {
process.destroyForcibly();
Assert.fail("keytool timed out");
}
if (process.exitValue() != 0) {
Assert.fail("keytool failed: " + new String(output.toByteArray(), StandardCharsets.UTF_8));
}
}

private static void deleteRecursively(Path root) throws IOException {
if (!Files.exists(root)) {
return;
}
try (Stream<Path> walk = Files.walk(root)) {
walk.sorted(Comparator.reverseOrder()).forEach(path -> {
try {
Files.deleteIfExists(path);
} catch (IOException ignored) {
// best-effort cleanup of ephemeral fixtures
}
});
}
}

@Test
public void timeOutTest() {
map.clear();
Expand Down Expand Up @@ -120,7 +216,7 @@ public void connectionPoolTest() {
}

@Test
public void certificateTest() throws IOException {
public void certificateTest() throws Exception {
map.clear();
OkHttpClientBuilder clientBuilder = Mockito.spy(new OkHttpClientBuilder());
clientBuilder.certificate(map);
Expand Down Expand Up @@ -176,6 +272,71 @@ public void certificateTest() throws IOException {
} catch (Exception e) {
Assert.assertTrue(e instanceof TeaException);
}

// ephemeral self-signed fixtures only — covers split + trust store without committed PEMs / CI CA secret
map.clear();
map.put("ignoreSSL", false);
String singleCa = createEphemeralSelfSignedCaPem("tea-java-unit-test.local");
map.put("ca", singleCa);
OkHttpClient clientWithCa = new OkHttpClientBuilder().certificate(map).buildOkHttpClient();
Assert.assertNotNull(clientWithCa.sslSocketFactory());

String dualCa = createEphemeralSelfSignedCaPem("tea-java-unit-test-a.local")
+ "\n"
+ createEphemeralSelfSignedCaPem("tea-java-unit-test-b.local");
map.put("ca", dualCa);
Assert.assertNotNull(new OkHttpClientBuilder().certificate(map).buildOkHttpClient().sslSocketFactory());

// non-PEM CA still enters splitPemCertificates else-branch
map.put("ca", "not-a-pem-certificate");
try {
new OkHttpClientBuilder().certificate(map);
Assert.fail();
} catch (TeaException e) {
Assert.assertNotNull(e.getMessage());
}
}

@Test
public void proxyAuthenticatorTest() throws Exception {
map.clear();
OkHttpClientBuilder clientBuilder = new OkHttpClientBuilder();
map.put("httpsProxy", "https://user:password@127.0.0.1:8080");
OkHttpClient client = clientBuilder.proxy(map).proxyAuthenticator(map).buildOkHttpClient();
Assert.assertNotNull(client.proxyAuthenticator());

Request request = new Request.Builder().url("http://example.com").build();
Response response = new Response.Builder()
.request(request)
.protocol(Protocol.HTTP_1_1)
.code(407)
.message("Proxy Authentication Required")
.build();
Request authenticated = client.proxyAuthenticator().authenticate((Route) null, response);
Assert.assertNotNull(authenticated);
Assert.assertNotNull(authenticated.header("Proxy-Authorization"));

map.clear();
map.put("socks5Proxy", "socks5://user:password@127.0.0.1:1080");
Assert.assertNotNull(new OkHttpClientBuilder().proxy(map).proxyAuthenticator(map).buildOkHttpClient());

map.clear();
map.put("httpProxy", "://bad-url");
try {
new OkHttpClientBuilder().proxy(map);
Assert.fail();
} catch (TeaException e) {
Assert.assertNotNull(e.getMessage());
}

map.clear();
map.put("httpProxy", "://bad-url");
try {
new OkHttpClientBuilder().proxyAuthenticator(map);
Assert.fail();
} catch (TeaException e) {
Assert.assertNotNull(e.getMessage());
}
}

@Test
Expand Down
9 changes: 9 additions & 0 deletions src/test/java/com/aliyun/tea/okhttp/OkRequestBodyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,14 @@ public void writeToTest() throws IOException {
Mockito.verify(body).writeTo(sink);
}

@Test
public void contentLengthTest() throws IOException {
TeaRequest request = new TeaRequest();
OkRequestBody body = new OkRequestBody(request);
Assert.assertEquals(-1L, body.contentLength());

request.body = new ByteArrayInputStream("tes".getBytes("UTF-8"));
body = new OkRequestBody(request);
Assert.assertEquals(3L, body.contentLength());
}
}
8 changes: 8 additions & 0 deletions src/test/java/com/aliyun/tea/utils/IOUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ public void closeQuietlyTest() {
InputStream inputStream = new ByteArrayInputStream(source);
try {
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(null);
IOUtils.closeQuietly(new AutoCloseable() {
@Override
public void close() throws Exception {
throw new IOException("close failed");
}
});
} catch (Exception e) {
Assert.fail();
}
Expand All @@ -22,6 +29,7 @@ public void closeQuietlyTest() {
public void closeIfCloseableTest() {
try {
IOUtils.closeIfCloseable("test");
IOUtils.closeIfCloseable(new ByteArrayInputStream(new byte[]{1}));
} catch (Exception e) {
Assert.fail();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ public void trueHostnameVerifierTest() throws InvocationTargetException, Instant
Assert.assertTrue(trueHostnameVerifier.verify("authType", sslSession));
Assert.assertTrue(trueHostnameVerifier.verify(null, null));

HostnameVerifier defaultVerifier = DefaultHostnameVerifier.getInstance(false);
Assert.assertFalse(defaultVerifier instanceof DefaultHostnameVerifier);

Constructor<DefaultHostnameVerifier> constructor = DefaultHostnameVerifier.class.getDeclaredConstructor(boolean.class);
constructor.setAccessible(true);
DefaultHostnameVerifier hostnameVerifier = constructor.newInstance(false);
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/com/aliyun/tea/utils/ValidateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
public class ValidateTest {
@Test
public void isTrueTest() {
Validate.isTrue(true, "message: %s", "test");
try {
Validate.isTrue(false, "message: %s", "test");
} catch (Exception e) {
Expand All @@ -27,6 +28,7 @@ public void notNullTest() {

@Test
public void isNullTest() {
Validate.isNull(null, "message: %s", "test");
try {
Validate.isNull("not null", "message: %s", "test");
} catch (Exception e) {
Expand Down
Loading