/*
*
* * Copyright 2014 Red Hat, Inc.
* *
* * All rights reserved. This program and the accompanying materials
* * are made available under the terms of the Eclipse Public License v1.0
* * and Apache License v2.0 which accompanies this distribution.
* *
* * The Eclipse Public License is available at
* * http://www.eclipse.org/legal/epl-v10.html
* *
* * The Apache License v2.0 is available at
* * http://www.opensource.org/licenses/apache2.0.php
* *
* * You may elect to redistribute this code under either of these licenses.
* *
*
*/
package io.vertx.test.core;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http2.Http2CodecUtil;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.Http2Settings;
import io.vertx.core.net.*;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.security.cert.X509Certificate;
import java.io.ByteArrayOutputStream;
import java.util.EnumSet;
import java.util.Random;
import java.util.Set;
import java.util.zip.GZIPOutputStream;
import static org.junit.Assert.fail;
/**
* @author <a href="http://tfox.org">Tim Fox</a>
*/
public class TestUtils {
private static Random random = new Random();
/**
* Creates a Buffer of random bytes.
* @param length The length of the Buffer
* @return the Buffer
*/
public static Buffer randomBuffer(int length) {
return randomBuffer(length, false, (byte) 0);
}
/**
* Create an array of random bytes
* @param length The length of the created array
* @return the byte array
*/
public static byte[] randomByteArray(int length) {
return randomByteArray(length, false, (byte) 0);
}
/**
* Create an array of random bytes
* @param length The length of the created array
* @param avoid If true, the resulting array will not contain avoidByte
* @param avoidByte A byte that is not to be included in the resulting array
* @return an array of random bytes
*/
public static byte[] randomByteArray(int length, boolean avoid, byte avoidByte) {
byte[] line = new byte[length];
for (int i = 0; i < length; i++) {
byte rand;
do {
rand = randomByte();
} while (avoid && rand == avoidByte);
line[i] = rand;
}
return line;
}
/**
* Creates a Buffer containing random bytes
* @param length the size of the Buffer to create
* @param avoid if true, the resulting Buffer will not contain avoidByte
* @param avoidByte A byte that is not to be included in the resulting array
* @return a Buffer of random bytes
*/
public static Buffer randomBuffer(int length, boolean avoid, byte avoidByte) {
byte[] line = randomByteArray(length, avoid, avoidByte);
return Buffer.buffer(line);
}
/**
* @return a random byte
*/
public static byte randomByte() {
return (byte) ((int) (Math.random() * 255) - 128);
}
/**
* @return a random int
*/
public static int randomInt() {
return random.nextInt();
}
/**
* @return a random port
*/
public static int randomPortInt() {
return random.nextInt(65536);
}
/**
* @return a random positive int
*/
public static int randomPositiveInt() {
while (true) {
int rand = random.nextInt();
if (rand > 0) {
return rand;
}
}
}
/**
* @return a random positive long
*/
public static long randomPositiveLong() {
while (true) {
long rand = random.nextLong();
if (rand > 0) {
return rand;
}
}
}
/**
* @return a random long
*/
public static long randomLong() {
return random.nextLong();
}
/**
* @return a random boolean
*/
public static boolean randomBoolean() {
return random.nextBoolean();
}
/**
* @return a random char
*/
public static char randomChar() {
return (char)(random.nextInt(16));
}
/**
* @return a random short
*/
public static short randomShort() {
return (short)(random.nextInt(1 << 15));
}
/**
* @return a random random float
*/
public static float randomFloat() {
return random.nextFloat();
}
/**
* @return a random random double
*/
public static double randomDouble() {
return random.nextDouble();
}
/**
* Creates a String containing random unicode characters
* @param length The length of the string to create
* @return a String of random unicode characters
*/
public static String randomUnicodeString(int length) {
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char c;
do {
c = (char) (0xFFFF * Math.random());
} while ((c >= 0xFFFE && c <= 0xFFFF) || (c >= 0xD800 && c <= 0xDFFF)); //Illegal chars
builder.append(c);
}
return builder.toString();
}
/**
* Creates a random string of ascii alpha characters
* @param length the length of the string to create
* @return a String of random ascii alpha characters
*/
public static String randomAlphaString(int length) {
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char c = (char) (65 + 25 * Math.random());
builder.append(c);
}
return builder.toString();
}
/**
* Create random {@link Http2Settings} with valid values.
* @return the random settings
*/
public static Http2Settings randomHttp2Settings() {
long headerTableSize = 10 + randomPositiveInt() % (Http2CodecUtil.MAX_HEADER_TABLE_SIZE - 10);
boolean enablePush = randomBoolean();
long maxConcurrentStreams = 10 + randomPositiveLong() % (Http2CodecUtil.MAX_CONCURRENT_STREAMS - 10);
int initialWindowSize = 10 + randomPositiveInt() % (Http2CodecUtil.MAX_INITIAL_WINDOW_SIZE - 10);
int maxFrameSize = Http2CodecUtil.MAX_FRAME_SIZE_LOWER_BOUND + randomPositiveInt() % (Http2CodecUtil.MAX_FRAME_SIZE_UPPER_BOUND - Http2CodecUtil.MAX_FRAME_SIZE_LOWER_BOUND);
long maxHeaderListSize = 10 + randomPositiveLong() % (Http2CodecUtil.MAX_HEADER_LIST_SIZE - 10);
Http2Settings settings = new Http2Settings();
settings.setHeaderTableSize(headerTableSize);
settings.setPushEnabled(enablePush);
settings.setMaxConcurrentStreams(maxConcurrentStreams);
settings.setInitialWindowSize(initialWindowSize);
settings.setMaxFrameSize(maxFrameSize);
settings.setMaxHeaderListSize(maxHeaderListSize);
settings.set('\u0007', (randomPositiveLong() & 0xFFFFFFFFL));
return settings;
}
public static <E extends Enum<E>> Set<E> randomEnumSet(Class<E> enumType) {
EnumSet<E> set = EnumSet.noneOf(enumType);
for (E e : EnumSet.allOf(enumType)) {
if (randomPositiveInt() % 2 == 1) {
set.add(e);
}
}
return set;
}
public static <E> E randomElement(E[] array) {
return array[randomPositiveInt() % array.length];
}
/**
* Determine if two byte arrays are equal
* @param b1 The first byte array to compare
* @param b2 The second byte array to compare
* @return true if the byte arrays are equal
*/
public static boolean byteArraysEqual(byte[] b1, byte[] b2) {
if (b1.length != b2.length) return false;
for (int i = 0; i < b1.length; i++) {
if (b1[i] != b2[i]) return false;
}
return true;
}
/**
* Asserts that an IllegalArgumentException is thrown by the code block.
* @param runnable code block to execute
*/
public static void assertIllegalArgumentException(Runnable runnable) {
try {
runnable.run();
fail("Should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
// OK
}
}
/**
* Asserts that a NullPointerException is thrown by the code block.
* @param runnable code block to execute
*/
public static void assertNullPointerException(Runnable runnable) {
try {
runnable.run();
fail("Should throw NullPointerException");
} catch (NullPointerException e) {
// OK
}
}
/**
* Asserts that an IllegalStateException is thrown by the code block.
* @param runnable code block to execute
*/
public static void assertIllegalStateException(Runnable runnable) {
try {
runnable.run();
fail("Should throw IllegalStateException");
} catch (IllegalStateException e) {
// OK
}
}
/**
* Asserts that an IndexOutOfBoundsException is thrown by the code block.
* @param runnable code block to execute
*/
public static void assertIndexOutOfBoundsException(Runnable runnable) {
try {
runnable.run();
fail("Should throw IndexOutOfBoundsException");
} catch (IndexOutOfBoundsException e) {
// OK
}
}
/**
* @param source
* @return gzipped data
* @throws Exception
*/
public static byte[] compressGzip(String source) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gos = new GZIPOutputStream(baos);
gos.write(source.getBytes());
gos.close();
return baos.toByteArray();
}
public static KeyCertOptions randomKeyCertOptions() {
KeyCertOptions keyCertOptions;
switch (TestUtils.randomPositiveInt() % 3) {
case 0:
keyCertOptions = new JksOptions();
String jksPassword = TestUtils.randomAlphaString(100);
((JksOptions) keyCertOptions).setPassword(jksPassword);
break;
case 1:
keyCertOptions = new PemKeyCertOptions();
Buffer keyValue = TestUtils.randomBuffer(100);
((PemKeyCertOptions) keyCertOptions).setKeyValue(keyValue);
break;
default:
keyCertOptions = new PfxOptions();
String pfxPassword = TestUtils.randomAlphaString(100);
((PfxOptions) keyCertOptions).setPassword(pfxPassword);
}
return keyCertOptions;
}
public static TrustOptions randomTrustOptions() {
TrustOptions trustOptions;
switch (TestUtils.randomPositiveInt() % 3) {
case 0:
trustOptions = new JksOptions();
String tsPassword = TestUtils.randomAlphaString(100);
((JksOptions) trustOptions).setPassword(tsPassword);
break;
case 1:
trustOptions = new PemTrustOptions();
Buffer keyValue = TestUtils.randomBuffer(100);
((PemTrustOptions) trustOptions).addCertValue(keyValue);
break;
default:
trustOptions = new PfxOptions();
String pfxPassword = TestUtils.randomAlphaString(100);
((PfxOptions) trustOptions).setPassword(pfxPassword);
}
return trustOptions;
}
public static Buffer leftPad(int padding, Buffer buffer) {
return Buffer.buffer(Unpooled.buffer()
.writerIndex(padding)
.readerIndex(padding)
.writeBytes(buffer.getByteBuf())
);
}
public static String cnOf(X509Certificate cert) throws Exception {
String dn = cert.getSubjectDN().getName();
LdapName ldapDN = new LdapName(dn);
for (Rdn rdn : ldapDN.getRdns()) {
if (rdn.getType().equalsIgnoreCase("cn")) {
return rdn.getValue().toString();
}
}
return null;
}
}