blob: 2ab8f97bc18b3cb57475a357840603fcc6bf600d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.util;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteInterruptedException;
import org.apache.ignite.cluster.ClusterGroup;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.ComputeJobAdapter;
import org.apache.ignite.internal.IgniteInterruptedCheckedException;
import org.apache.ignite.internal.util.future.GridFutureAdapter;
import org.apache.ignite.internal.util.lang.GridPeerDeployAware;
import org.apache.ignite.internal.util.lang.IgniteThrowableFunction;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.lang.IgniteProductVersion;
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.http.GridEmbeddedHttpServer;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.apache.ignite.testframework.junits.common.GridCommonTest;
import org.apache.ignite.thread.IgniteThreadFactory;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import org.junit.Test;
import static java.util.Arrays.asList;
import static java.util.Objects.nonNull;
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.stream.Collectors.joining;
import static org.apache.ignite.testframework.GridTestUtils.assertThrows;
import static org.apache.ignite.testframework.GridTestUtils.readResource;
import static org.junit.Assert.assertArrayEquals;
/**
* Grid utils tests.
*/
@GridCommonTest(group = "Utils")
public class IgniteUtilsSelfTest extends GridCommonAbstractTest {
/** */
public static final int[] EMPTY = new int[0];
/** Maximum string length to be written at once. */
private static final int MAX_STR_LEN = 0xFFFF / 4;
/**
* @return 120 character length string.
*/
private String text120() {
char[] chs = new char[120];
Arrays.fill(chs, 'x');
return new String(chs);
}
/**
*
*/
@Test
public void testIsPow2() {
assertTrue(U.isPow2(1));
assertTrue(U.isPow2(2));
assertTrue(U.isPow2(4));
assertTrue(U.isPow2(8));
assertTrue(U.isPow2(16));
assertTrue(U.isPow2(16 * 16));
assertTrue(U.isPow2(32 * 32));
assertFalse(U.isPow2(-4));
assertFalse(U.isPow2(-3));
assertFalse(U.isPow2(-2));
assertFalse(U.isPow2(-1));
assertFalse(U.isPow2(0));
assertFalse(U.isPow2(3));
assertFalse(U.isPow2(5));
assertFalse(U.isPow2(6));
assertFalse(U.isPow2(7));
assertFalse(U.isPow2(9));
}
/**
*
*/
@Test
public void testNextPowOf2() {
assertEquals(1, U.nextPowerOf2(0));
assertEquals(1, U.nextPowerOf2(1));
assertEquals(2, U.nextPowerOf2(2));
assertEquals(4, U.nextPowerOf2(3));
assertEquals(4, U.nextPowerOf2(4));
assertEquals(8, U.nextPowerOf2(5));
assertEquals(8, U.nextPowerOf2(6));
assertEquals(8, U.nextPowerOf2(7));
assertEquals(8, U.nextPowerOf2(8));
assertEquals(32768, U.nextPowerOf2(32767));
}
/**
* @throws Exception If failed.
*/
@Test
public void testAllLocalIps() throws Exception {
Collection<String> ips = U.allLocalIps();
System.out.println("All local IPs: " + ips);
}
/**
* @throws Exception If failed.
*/
@Test
public void testAllLocalMACs() throws Exception {
Collection<String> macs = U.allLocalMACs();
System.out.println("All local MACs: " + macs);
}
/**
* On linux NetworkInterface.getHardwareAddress() returns null from time to time.
*
* @throws Exception If failed.
*/
@Test
public void testAllLocalMACsMultiThreaded() throws Exception {
GridTestUtils.runMultiThreaded(new Runnable() {
@Override public void run() {
for (int i = 0; i < 30; i++) {
Collection<String> macs = U.allLocalMACs();
assertTrue("Mac address are not defined.", !macs.isEmpty());
}
}
}, 32, "thread");
}
/**
* @throws Exception If failed.
*/
@Test
public void testByteArray2String() throws Exception {
assertEquals("{0x0A,0x14,0x1E,0x28,0x32,0x3C,0x46,0x50,0x5A}",
U.byteArray2String(new byte[]{10, 20, 30, 40, 50, 60, 70, 80, 90}, "0x%02X", ",0x%02X"));
}
/**
* @throws Exception If failed.
*/
@Test
public void testFormatMins() throws Exception {
printFormatMins(0);
printFormatMins(1);
printFormatMins(2);
printFormatMins(59);
printFormatMins(60);
printFormatMins(61);
printFormatMins(60 * 24 - 1);
printFormatMins(60 * 24);
printFormatMins(60 * 24 + 1);
printFormatMins(5 * 60 * 24 - 1);
printFormatMins(5 * 60 * 24);
printFormatMins(5 * 60 * 24 + 1);
}
/**
* Helper method for {@link #testFormatMins()}
*
* @param mins Minutes to test.
*/
private void printFormatMins(long mins) {
System.out.println("For " + mins + " minutes: " + X.formatMins(mins));
}
/**
* @throws Exception If failed.
*/
@Test
public void testDownloadUrlFromHttp() throws Exception {
GridEmbeddedHttpServer srv = null;
try {
String urlPath = "/testDownloadUrl/";
srv = GridEmbeddedHttpServer.startHttpServer().withFileDownloadingHandler(urlPath,
GridTestUtils.resolveIgnitePath("/modules/core/src/test/config/tests.properties"));
File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "url-http.file");
file = U.downloadUrl(new URL(srv.getBaseUrl() + urlPath), file);
assert file.exists();
assert file.delete();
}
finally {
if (srv != null)
srv.stop(1);
}
}
/**
* @throws Exception If failed.
*/
@Test
public void testDownloadUrlFromHttps() throws Exception {
GridEmbeddedHttpServer srv = null;
try {
String urlPath = "/testDownloadUrl/";
srv = GridEmbeddedHttpServer.startHttpsServer().withFileDownloadingHandler(urlPath,
GridTestUtils.resolveIgnitePath("modules/core/src/test/config/tests.properties"));
File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "url-http.file");
file = U.downloadUrl(new URL(srv.getBaseUrl() + urlPath), file);
assert file.exists();
assert file.delete();
}
finally {
if (srv != null)
srv.stop(1);
}
}
/**
* @throws Exception If failed.
*/
@Test
public void testDownloadUrlFromLocalFile() throws Exception {
File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "url-http.file");
file = U.downloadUrl(
GridTestUtils.resolveIgnitePath("modules/core/src/test/config/tests.properties").toURI().toURL(), file);
assert file.exists();
assert file.delete();
}
/**
* @throws Exception If failed.
*/
@Test
public void testOs() throws Exception {
System.out.println("OS string: " + U.osString());
System.out.println("JDK string: " + U.jdkString());
System.out.println("OS/JDK string: " + U.osJdkString());
System.out.println("Is Windows: " + U.isWindows());
System.out.println("Is Windows 95: " + U.isWindows95());
System.out.println("Is Windows 98: " + U.isWindows98());
System.out.println("Is Windows NT: " + U.isWindowsNt());
System.out.println("Is Windows 2000: " + U.isWindows2k());
System.out.println("Is Windows 2003: " + U.isWindows2003());
System.out.println("Is Windows XP: " + U.isWindowsXp());
System.out.println("Is Windows Vista: " + U.isWindowsVista());
System.out.println("Is Linux: " + U.isLinux());
System.out.println("Is Mac OS: " + U.isMacOs());
System.out.println("Is Netware: " + U.isNetWare());
System.out.println("Is Solaris: " + U.isSolaris());
System.out.println("Is Solaris SPARC: " + U.isSolarisSparc());
System.out.println("Is Solaris x86: " + U.isSolarisX86());
System.out.println("Is Windows7: " + U.isWindows7());
}
/**
* @throws Exception If failed.
*/
@Test
public void testJavaSerialization() throws Exception {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(byteOut);
objOut.writeObject(new byte[] {1, 2, 3, 4, 5, 5});
objOut.flush();
byte[] sBytes = byteOut.toByteArray();
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(sBytes));
in.readObject();
}
/**
*
*/
@Test
public void testHidePassword() {
Collection<String> uriList = new ArrayList<>();
uriList.add("ftp://anonymous:111111;freq=5000@unknown.host:21/pub/gg-test");
uriList.add("ftp://anonymous:111111;freq=5000@localhost:21/pub/gg-test");
uriList.add("http://freq=5000@localhost/tasks");
uriList.add("http://freq=5000@unknownhost.host/tasks");
for (String uri : uriList)
X.println(uri + " -> " + U.hidePassword(uri));
}
/**
* Test job to test possible indefinite recursion in detecting peer deploy aware.
*/
private class SelfReferencedJob extends ComputeJobAdapter implements GridPeerDeployAware {
/** */
private SelfReferencedJob ref;
/** */
private SelfReferencedJob[] arr;
/** */
private Collection<SelfReferencedJob> col;
/** */
private ClusterNode node;
/** */
private ClusterGroup subGrid;
/**
* @param ignite Grid.
*/
private SelfReferencedJob(Ignite ignite) throws IgniteCheckedException {
node = ignite.cluster().localNode();
ref = this;
arr = new SelfReferencedJob[]{this, this};
col = asList(this, this, this);
newContext();
subGrid = ignite.cluster().forNodes(Collections.singleton(node));
}
/** {@inheritDoc} */
@Override public Object execute() {
return null;
}
/** {@inheritDoc} */
@Override public Class<?> deployClass() {
return getClass();
}
/** {@inheritDoc} */
@Override public ClassLoader classLoader() {
return getClass().getClassLoader();
}
}
/**
* @throws Exception If test fails.
*/
@Test
public void testDetectPeerDeployAwareInfiniteRecursion() throws Exception {
Ignite g = startGrid(1);
try {
final SelfReferencedJob job = new SelfReferencedJob(g);
GridPeerDeployAware d = U.detectPeerDeployAware(U.peerDeployAware(job));
assert d != null;
assert SelfReferencedJob.class == d.deployClass();
assert d.classLoader() == SelfReferencedJob.class.getClassLoader();
}
finally {
stopGrid(1);
}
}
/**
* @param r Runnable.
* @return Job created for given runnable.
*/
private static ComputeJob job(final Runnable r) {
return new ComputeJobAdapter() {
@Nullable @Override public Object execute() {
r.run();
return null;
}
};
}
/**
* @throws Exception If test failed.
*/
@Test
public void testPeerDeployAware0() throws Exception {
Collection<Object> col = new ArrayList<>();
col.add(null);
col.add(null);
col.add(null);
GridPeerDeployAware pda = U.peerDeployAware0(col);
assert pda != null;
col.clear();
col.add(null);
pda = U.peerDeployAware0(col);
assert pda != null;
col.clear();
pda = U.peerDeployAware0(col);
assert pda != null;
col.clear();
col.add(null);
col.add("Test");
col.add(null);
pda = U.peerDeployAware0(col);
assert pda != null;
col.clear();
col.add("Test");
pda = U.peerDeployAware0(col);
assert pda != null;
col.clear();
col.add("Test");
col.add(this);
pda = U.peerDeployAware0(col);
assert pda != null;
col.clear();
col.add(null);
col.add("Test");
col.add(null);
col.add(this);
col.add(null);
pda = U.peerDeployAware0(col);
assert pda != null;
}
/**
* Test UUID to bytes array conversion.
*/
@Test
public void testsGetBytes() {
for (int i = 0; i < 100; i++) {
UUID id = UUID.randomUUID();
byte[] bytes = U.uuidToBytes(id);
BigInteger n = new BigInteger(bytes);
assert n.shiftRight(Long.SIZE).longValue() == id.getMostSignificantBits();
assert n.longValue() == id.getLeastSignificantBits();
}
}
/**
*
*/
@SuppressWarnings("ZeroLengthArrayAllocation")
@Test
public void testReadByteArray() {
assertTrue(Arrays.equals(new byte[0], U.readByteArray(ByteBuffer.allocate(0))));
assertTrue(Arrays.equals(new byte[0], U.readByteArray(ByteBuffer.allocate(0), ByteBuffer.allocate(0))));
Random rnd = new Random();
byte[] bytes = new byte[13];
rnd.nextBytes(bytes);
assertTrue(Arrays.equals(bytes, U.readByteArray(ByteBuffer.wrap(bytes))));
assertTrue(Arrays.equals(bytes, U.readByteArray(ByteBuffer.wrap(bytes), ByteBuffer.allocate(0))));
assertTrue(Arrays.equals(bytes, U.readByteArray(ByteBuffer.allocate(0), ByteBuffer.wrap(bytes))));
for (int i = 0; i < 1000; i++) {
int n = rnd.nextInt(100);
bytes = new byte[n];
rnd.nextBytes(bytes);
ByteBuffer[] bufs = new ByteBuffer[1 + rnd.nextInt(10)];
int x = 0;
for (int j = 0; j < bufs.length - 1; j++) {
int size = x == n ? 0 : rnd.nextInt(n - x);
bufs[j] = (ByteBuffer)ByteBuffer.wrap(bytes).position(x).limit(x += size);
}
bufs[bufs.length - 1] = (ByteBuffer)ByteBuffer.wrap(bytes).position(x).limit(n);
assertTrue(Arrays.equals(bytes, U.readByteArray(bufs)));
}
}
/**
*
*/
@SuppressWarnings("ZeroLengthArrayAllocation")
@Test
public void testHashCodeFromBuffers() {
assertEquals(Arrays.hashCode(new byte[0]), U.hashCode(ByteBuffer.allocate(0)));
assertEquals(Arrays.hashCode(new byte[0]), U.hashCode(ByteBuffer.allocate(0), ByteBuffer.allocate(0)));
Random rnd = new Random();
for (int i = 0; i < 1000; i++) {
ByteBuffer[] bufs = new ByteBuffer[1 + rnd.nextInt(15)];
for (int j = 0; j < bufs.length; j++) {
byte[] bytes = new byte[rnd.nextInt(25)];
rnd.nextBytes(bytes);
bufs[j] = ByteBuffer.wrap(bytes);
}
assertEquals(U.hashCode(bufs), Arrays.hashCode(U.readByteArray(bufs)));
}
}
/**
* Test annotation look up.
*/
@Test
public void testGetAnnotations() {
assert U.getAnnotation(A1.class, Ann1.class) != null;
assert U.getAnnotation(A2.class, Ann1.class) != null;
assert U.getAnnotation(A1.class, Ann2.class) != null;
assert U.getAnnotation(A2.class, Ann2.class) != null;
assert U.getAnnotation(A3.class, Ann1.class) == null;
assert U.getAnnotation(A3.class, Ann2.class) != null;
}
/**
*
*/
@Test
public void testUnique() {
int[][][] arrays = new int[][][]{
new int[][]{EMPTY, EMPTY, EMPTY},
new int[][]{new int[]{1, 2, 3}, EMPTY, new int[]{1, 2, 3}},
new int[][]{new int[]{1, 2, 3}, new int[]{1, 2, 3}, new int[]{1, 2, 3}},
new int[][]{new int[]{1, 2, 3}, new int[]{1, 3}, new int[]{1, 2, 3}},
new int[][]{new int[]{1, 2, 30, 40, 50}, new int[]{2, 40}, new int[]{1, 2, 30, 40, 50}},
new int[][]{new int[]{-100, -13, 1, 2, 5, 30, 40, 50}, new int[]{1, 2, 6, 100, 113},
new int[]{-100, -13, 1, 2, 5, 6, 30, 40, 50, 100, 113}}
};
for (int[][] a : arrays) {
assertArrayEquals(a[2], U.unique(a[0], a[0].length, a[1], a[1].length));
assertArrayEquals(a[2], U.unique(a[1], a[1].length, a[0], a[0].length));
}
assertArrayEquals(new int[]{1, 2, 3, 4}, U.unique(new int[]{1, 2, 3, 8}, 3, new int[]{2, 4, 5}, 2));
assertArrayEquals(new int[]{2, 4}, U.unique(new int[]{1, 2, 3, 8}, 0, new int[]{2, 4, 5}, 2));
assertArrayEquals(new int[]{1, 2, 4, 5}, U.unique(new int[]{1, 2, 3, 8}, 2, new int[]{2, 4, 5, 6}, 3));
assertArrayEquals(new int[]{1, 2}, U.unique(new int[]{1, 2, 3, 8}, 2, new int[]{2, 4, 5, 6}, 0));
}
/**
*
*/
@Test
public void testDifference() {
int[][][] arrays = new int[][][]{
new int[][]{EMPTY, EMPTY, EMPTY},
new int[][]{new int[]{1, 2, 3}, EMPTY, new int[]{1, 2, 3}},
new int[][]{EMPTY, new int[]{1, 2, 3}, EMPTY},
new int[][]{new int[]{1, 2, 3}, new int[]{1, 2, 3}, EMPTY},
new int[][]{new int[]{-100, -50, 1, 2, 3}, new int[]{-50, -1, 1, 3}, new int[]{-100, 2}},
new int[][]{new int[]{-100, 1, 2, 30, 40, 50}, new int[]{2, 40}, new int[]{-100, 1, 30, 50}},
new int[][]{new int[]{-1, 1, 2, 30, 40, 50}, new int[]{1, 2, 100, 113}, new int[]{-1, 30, 40, 50}}
};
for (int[][] a : arrays)
assertArrayEquals(a[2], U.difference(a[0], a[0].length, a[1], a[1].length));
assertArrayEquals(new int[]{1, 2}, U.difference(new int[]{1, 2, 30, 40, 50}, 3, new int[]{30, 40}, 2));
assertArrayEquals(EMPTY, U.difference(new int[]{1, 2, 30, 40, 50}, 0, new int[]{30, 40}, 2));
assertArrayEquals(new int[]{1, 2, 40}, U.difference(new int[]{1, 2, 30, 40, 50}, 4, new int[]{30, 40}, 1));
assertArrayEquals(new int[]{1, 2, 30, 40}, U.difference(new int[]{1, 2, 30, 40, 50}, 4, new int[]{30, 40}, 0));
}
/**
*
*/
@Test
public void testCopyIfExceeded() {
int[][] arrays = new int[][]{new int[]{13, 14, 17, 11}, new int[]{13}, EMPTY};
for (int[] a : arrays) {
int[] b = Arrays.copyOf(a, a.length);
assertEquals(a, U.copyIfExceeded(a, a.length));
assertArrayEquals(b, U.copyIfExceeded(a, a.length));
for (int j = 0; j < a.length - 1; j++)
assertArrayEquals(Arrays.copyOf(b, j), U.copyIfExceeded(a, j));
}
}
/**
*
*/
@Test
public void testIsIncreasingArray() {
assertTrue(U.isIncreasingArray(EMPTY, 0));
assertTrue(U.isIncreasingArray(new int[]{Integer.MIN_VALUE, -10, 1, 13, Integer.MAX_VALUE}, 5));
assertTrue(U.isIncreasingArray(new int[]{1, 2, 3, -1, 5}, 0));
assertTrue(U.isIncreasingArray(new int[]{1, 2, 3, -1, 5}, 3));
assertFalse(U.isIncreasingArray(new int[]{1, 2, 3, -1, 5}, 4));
assertFalse(U.isIncreasingArray(new int[]{1, 2, 3, -1, 5}, 5));
assertFalse(U.isIncreasingArray(new int[]{1, 2, 3, 3, 5}, 4));
assertTrue(U.isIncreasingArray(new int[]{1, -1}, 1));
assertFalse(U.isIncreasingArray(new int[]{1, -1}, 2));
assertTrue(U.isIncreasingArray(new int[]{13, 13, 13}, 1));
assertFalse(U.isIncreasingArray(new int[]{13, 13, 13}, 2));
assertFalse(U.isIncreasingArray(new int[]{13, 13, 13}, 3));
}
/**
*
*/
@Test
public void testIsNonDecreasingArray() {
assertTrue(U.isNonDecreasingArray(EMPTY, 0));
assertTrue(U.isNonDecreasingArray(new int[]{Integer.MIN_VALUE, -10, 1, 13, Integer.MAX_VALUE}, 5));
assertTrue(U.isNonDecreasingArray(new int[]{1, 2, 3, -1, 5}, 0));
assertTrue(U.isNonDecreasingArray(new int[]{1, 2, 3, -1, 5}, 3));
assertFalse(U.isNonDecreasingArray(new int[]{1, 2, 3, -1, 5}, 4));
assertFalse(U.isNonDecreasingArray(new int[]{1, 2, 3, -1, 5}, 5));
assertTrue(U.isNonDecreasingArray(new int[]{1, 2, 3, 3, 5}, 4));
assertTrue(U.isNonDecreasingArray(new int[]{1, -1}, 1));
assertFalse(U.isNonDecreasingArray(new int[]{1, -1}, 2));
assertTrue(U.isNonDecreasingArray(new int[]{13, 13, 13}, 1));
assertTrue(U.isNonDecreasingArray(new int[]{13, 13, 13}, 2));
assertTrue(U.isNonDecreasingArray(new int[]{13, 13, 13}, 3));
}
/**
* Test InetAddress Comparator.
*/
@Test
public void testInetAddressesComparator() {
List<InetSocketAddress> ips = new ArrayList<InetSocketAddress>() {
{
add(new InetSocketAddress("127.0.0.1", 1));
add(new InetSocketAddress("10.0.0.1", 1));
add(new InetSocketAddress("172.16.0.1", 1));
add(new InetSocketAddress("192.168.0.1", 1));
add(new InetSocketAddress("100.0.0.1", 1));
add(new InetSocketAddress("XXX", 1));
}
};
Collections.sort(ips, U.inetAddressesComparator(true));
assertTrue(ips.get(0).getAddress().isLoopbackAddress());
assertTrue(ips.get(ips.size() - 1).isUnresolved());
Collections.sort(ips, U.inetAddressesComparator(false));
assertTrue(ips.get(ips.size() - 2).getAddress().isLoopbackAddress());
assertTrue(ips.get(ips.size() - 1).isUnresolved());
}
@Test
public void testMD5Calculation() throws Exception {
String md5 = U.calculateMD5(new ByteArrayInputStream("Corrupted information.".getBytes()));
assertEquals("d7dbe555be2eee7fa658299850169fa1", md5);
}
/**
* @throws Exception If failed.
*/
@Test
public void testResolveLocalAddresses() throws Exception {
InetAddress inetAddress = InetAddress.getByName("0.0.0.0");
IgniteBiTuple<Collection<String>, Collection<String>> addrs = U.resolveLocalAddresses(inetAddress);
Collection<String> hostNames = addrs.get2();
assertFalse(hostNames.contains(null));
assertFalse(hostNames.contains(""));
assertFalse(hostNames.contains("127.0.0.1"));
assertFalse(F.exist(hostNames, new IgnitePredicate<String>() {
@Override public boolean apply(String hostName) {
return hostName.contains("localhost") || hostName.contains("0:0:0:0:0:0:0:1");
}
}));
}
/**
*
*/
@Test
public void testToSocketAddressesNoDuplicates() {
Collection<String> addrs = new ArrayList<>();
addrs.add("127.0.0.1");
addrs.add("localhost");
Collection<String> hostNames = new ArrayList<>();
int port = 1234;
assertEquals(1, U.toSocketAddresses(addrs, hostNames, port).size());
}
/**
* Composes a test String of given tlength.
*
* @param len The length.
* @return The String.
*/
private static String composeString(int len) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++)
sb.append((char)i);
String x = sb.toString();
assertEquals(len, x.length());
return x;
}
/**
* Writes the given String to a DataOutput, reads from DataInput, then checks if they are the same.
*
* @param s0 The String to check serialization for.
* @throws Exception On error.
*/
private static void checkString(String s0) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutput dout = new DataOutputStream(baos);
writeUTF(dout, s0);
DataInput din = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()));
String s1 = readUTF(din);
assertEquals(s0, s1);
}
/**
* Write UTF string which can be {@code null}.
*
* @param out Output stream.
* @param val Value.
* @throws IOException If failed.
*/
public static void writeUTF(DataOutput out, @Nullable String val) throws IOException {
if (val == null)
out.writeInt(-1);
else {
out.writeInt(val.length());
if (val.length() <= MAX_STR_LEN)
out.writeUTF(val); // Optimized write in 1 chunk.
else {
int written = 0;
while (written < val.length()) {
int partLen = Math.min(val.length() - written, MAX_STR_LEN);
String part = val.substring(written, written + partLen);
out.writeUTF(part);
written += partLen;
}
}
}
}
/**
* Read UTF string which can be {@code null}.
*
* @param in Input stream.
* @return Value.
* @throws IOException If failed.
*/
public static String readUTF(DataInput in) throws IOException {
int len = in.readInt(); // May be zero.
if (len < 0)
return null;
else {
if (len <= MAX_STR_LEN)
return in.readUTF();
StringBuilder sb = new StringBuilder(len);
do {
sb.append(in.readUTF());
}
while (sb.length() < len);
assert sb.length() == len;
return sb.toString();
}
}
/**
* Tests long String serialization/deserialization,
*
* @throws Exception If failed.
*/
@Test
public void testLongStringWriteUTF() throws Exception {
checkString(null);
checkString("");
checkString("a");
checkString("Quick brown fox jumps over the lazy dog.");
String x = composeString(0xFFFF / 4 - 1);
checkString(x);
x = composeString(0xFFFF / 4);
checkString(x);
x = composeString(0xFFFF / 4 + 1);
checkString(x);
}
/**
*
*/
@Test
public void testCeilPow2() throws Exception {
assertEquals(2, U.ceilPow2(2));
assertEquals(4, U.ceilPow2(3));
assertEquals(4, U.ceilPow2(4));
assertEquals(8, U.ceilPow2(5));
assertEquals(8, U.ceilPow2(6));
assertEquals(8, U.ceilPow2(7));
assertEquals(8, U.ceilPow2(8));
assertEquals(16, U.ceilPow2(9));
assertEquals(1 << 15, U.ceilPow2((1 << 15) - 1));
assertEquals(1 << 15, U.ceilPow2(1 << 15));
assertEquals(1 << 16, U.ceilPow2((1 << 15) + 1));
assertEquals(1 << 26, U.ceilPow2((1 << 26) - 100));
assertEquals(1 << 26, U.ceilPow2(1 << 26));
assertEquals(1 << 27, U.ceilPow2((1 << 26) + 100));
for (int i = (int)Math.pow(2, 30); i < Integer.MAX_VALUE; i++)
assertEquals((int)Math.pow(2, 30), U.ceilPow2(i));
for (int i = Integer.MIN_VALUE; i < 0; i++)
assertEquals(0, U.ceilPow2(i));
}
/**
*
*/
@Test
public void testIsOldestNodeVersionAtLeast() {
IgniteProductVersion v240 = IgniteProductVersion.fromString("2.4.0");
IgniteProductVersion v241 = IgniteProductVersion.fromString("2.4.1");
IgniteProductVersion v250 = IgniteProductVersion.fromString("2.5.0");
IgniteProductVersion v250ts = IgniteProductVersion.fromString("2.5.0-b1-3");
TcpDiscoveryNode node240 = new TcpDiscoveryNode();
node240.version(v240);
TcpDiscoveryNode node241 = new TcpDiscoveryNode();
node241.version(v241);
TcpDiscoveryNode node250 = new TcpDiscoveryNode();
node250.version(v250);
TcpDiscoveryNode node250ts = new TcpDiscoveryNode();
node250ts.version(v250ts);
assertTrue(U.isOldestNodeVersionAtLeast(v240, asList(node240, node241, node250, node250ts)));
assertFalse(U.isOldestNodeVersionAtLeast(v241, asList(node240, node241, node250, node250ts)));
assertTrue(U.isOldestNodeVersionAtLeast(v250, asList(node250, node250ts)));
assertTrue(U.isOldestNodeVersionAtLeast(v250ts, asList(node250, node250ts)));
}
/**
*
*/
@Test
public void testDoInParallel() throws Throwable {
CyclicBarrier barrier = new CyclicBarrier(3);
ExecutorService executorService = Executors.newFixedThreadPool(3,
new IgniteThreadFactory("testscope", "ignite-utils-test"));
try {
IgniteUtils.doInParallel(3,
executorService,
asList(1, 2, 3),
i -> {
try {
barrier.await(1, SECONDS);
}
catch (Exception e) {
throw new IgniteCheckedException(e);
}
return null;
}
);
} finally {
executorService.shutdownNow();
}
}
/**
*
*/
@Test
public void testDoInParallelBatch() {
CyclicBarrier barrier = new CyclicBarrier(3);
ExecutorService executorService = Executors.newFixedThreadPool(3,
new IgniteThreadFactory("testscope", "ignite-utils-test"));
try {
IgniteUtils.doInParallel(2,
executorService,
asList(1, 2, 3),
i -> {
try {
barrier.await(400, TimeUnit.MILLISECONDS);
}
catch (Exception e) {
throw new IgniteCheckedException(e);
}
return null;
}
);
fail("Should throw timeout exception");
}
catch (Exception e) {
assertTrue(e.toString(), X.hasCause(e, TimeoutException.class));
} finally {
executorService.shutdownNow();
}
}
/**
* Test optimal splitting on batch sizes.
*/
@Test
public void testOptimalBatchSize() {
assertArrayEquals(new int[]{1}, IgniteUtils.calculateOptimalBatchSizes(1, 1));
assertArrayEquals(new int[]{2}, IgniteUtils.calculateOptimalBatchSizes(1, 2));
assertArrayEquals(new int[]{1, 1, 1, 1}, IgniteUtils.calculateOptimalBatchSizes(6, 4));
assertArrayEquals(new int[]{1}, IgniteUtils.calculateOptimalBatchSizes(4, 1));
assertArrayEquals(new int[]{1, 1}, IgniteUtils.calculateOptimalBatchSizes(4, 2));
assertArrayEquals(new int[]{1, 1, 1}, IgniteUtils.calculateOptimalBatchSizes(4, 3));
assertArrayEquals(new int[]{1, 1, 1, 1}, IgniteUtils.calculateOptimalBatchSizes(4, 4));
assertArrayEquals(new int[]{2, 1, 1, 1}, IgniteUtils.calculateOptimalBatchSizes(4, 5));
assertArrayEquals(new int[]{2, 2, 1, 1}, IgniteUtils.calculateOptimalBatchSizes(4, 6));
assertArrayEquals(new int[]{2, 2, 2, 1}, IgniteUtils.calculateOptimalBatchSizes(4, 7));
assertArrayEquals(new int[]{2, 2, 2, 2}, IgniteUtils.calculateOptimalBatchSizes(4, 8));
assertArrayEquals(new int[]{3, 2, 2, 2}, IgniteUtils.calculateOptimalBatchSizes(4, 9));
assertArrayEquals(new int[]{3, 3, 2, 2}, IgniteUtils.calculateOptimalBatchSizes(4, 10));
}
/**
* Test parallel execution in order.
*/
@Test
public void testDoInParallelResultsOrder() throws IgniteCheckedException {
ExecutorService executorService = Executors.newFixedThreadPool(4,
new IgniteThreadFactory("testscope", "ignite-utils-test"));
try {
for (int parallelism = 1; parallelism < 16; parallelism++)
for (int size = 0; size < 10_000; size++)
testOrder(executorService, size, parallelism);
} finally {
executorService.shutdownNow();
}
}
/**
* Test parallel execution steal job.
*/
@Test
public void testDoInParallelWithStealingJob() throws IgniteCheckedException {
// Pool size should be less that input data collection.
ExecutorService executorService = Executors
.newSingleThreadExecutor(new IgniteThreadFactory("testscope", "ignite-utils-test"));
CountDownLatch mainThreadLatch = new CountDownLatch(1);
CountDownLatch poolThreadLatch = new CountDownLatch(1);
// Busy one thread from the pool.
executorService.submit(new Runnable() {
@Override public void run() {
try {
poolThreadLatch.await();
}
catch (InterruptedException e) {
throw new IgniteInterruptedException(e);
}
}
});
List<Integer> data = asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
AtomicInteger taskProcessed = new AtomicInteger();
long threadId = Thread.currentThread().getId();
AtomicInteger curThreadCnt = new AtomicInteger();
AtomicInteger poolThreadCnt = new AtomicInteger();
Collection<Integer> res = U.doInParallel(10,
executorService,
data,
new IgniteThrowableFunction<Integer, Integer>() {
@Override public Integer apply(Integer cnt) throws IgniteInterruptedCheckedException {
// Release thread in pool in the middle of range.
if (taskProcessed.getAndIncrement() == (data.size() / 2) - 1) {
poolThreadLatch.countDown();
try {
// Await thread in thread pool complete task.
mainThreadLatch.await();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IgniteInterruptedCheckedException(e);
}
}
// Increment if executed in current thread.
if (Thread.currentThread().getId() == threadId)
curThreadCnt.incrementAndGet();
else {
poolThreadCnt.incrementAndGet();
if (taskProcessed.get() == data.size())
mainThreadLatch.countDown();
}
return -cnt;
}
});
Assert.assertEquals(curThreadCnt.get() + poolThreadCnt.get(), data.size());
Assert.assertEquals(5, curThreadCnt.get());
Assert.assertEquals(5, poolThreadCnt.get());
Assert.assertEquals(asList(0, -1, -2, -3, -4, -5, -6, -7, -8, -9), res);
}
/**
* Test parallel execution steal job.
*/
@Test
public void testDoInParallelWithStealingJobRunTaskInExecutor() throws Exception {
// Pool size should be less that input data collection.
ExecutorService executorService = Executors.newFixedThreadPool(2,
new IgniteThreadFactory("testscope", "ignite-utils-test"));
Future<?> f1 = executorService.submit(() -> runTask(executorService));
Future<?> f2 = executorService.submit(() -> runTask(executorService));
Future<?> f3 = executorService.submit(() -> runTask(executorService));
f1.get();
f2.get();
f3.get();
}
/**
*
* @param executorService Executor service.
*/
private void runTask(ExecutorService executorService) {
List<Integer> data = asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
long threadId = Thread.currentThread().getId();
AtomicInteger curThreadCnt = new AtomicInteger();
Collection<Integer> res;
// Future for avoiding fast execution in only executor threads.
// Here we try to pass a number of tasks more that executor size,
// but there is a case when all task will be completed after last submit return control and
// current thread can not steal task because all task will be already finished.
GridFutureAdapter fut = new GridFutureAdapter();
try {
res = U.doInParallel(10,
executorService,
data,
new IgniteThrowableFunction<Integer, Integer>() {
@Override public Integer apply(Integer cnt) {
if (Thread.currentThread().getId() == threadId) {
fut.onDone();
curThreadCnt.incrementAndGet();
}
else {
try {
fut.get();
}
catch (IgniteCheckedException e) {
throw U.convertException(e);
}
}
return -cnt;
}
});
}
catch (IgniteCheckedException e) {
throw new IgniteException(e);
}
Assert.assertTrue(curThreadCnt.get() > 0);
Assert.assertEquals(asList(0, -1, -2, -3, -4, -5, -6, -7, -8, -9), res);
}
/**
* Template method to test parallel execution
* @param executorService ExecutorService.
* @param size Size.
* @param parallelism Parallelism.
* @throws IgniteCheckedException Exception.
*/
private void testOrder(ExecutorService executorService, int size, int parallelism) throws IgniteCheckedException {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < size; i++)
list.add(i);
Collection<Integer> results = IgniteUtils.doInParallel(
parallelism,
executorService,
list,
i -> i * 2
);
assertEquals(list.size(), results.size());
final int[] i = {0};
results.forEach(new Consumer<Integer>() {
@Override public void accept(Integer integer) {
assertEquals(2 * list.get(i[0]), integer.intValue());
i[0]++;
}
});
}
/**
*
*/
@Test
public void testDoInParallelException() {
String expectedException = "ExpectedException";
ExecutorService executorService = Executors
.newSingleThreadExecutor(new IgniteThreadFactory("testscope", "ignite-utils-test"));
try {
IgniteUtils.doInParallel(
1,
executorService,
asList(1, 2, 3),
i -> {
if (Integer.valueOf(1).equals(i))
throw new IgniteCheckedException(expectedException);
return null;
}
);
fail("Should throw ParallelExecutionException");
}
catch (IgniteCheckedException e) {
assertEquals(expectedException, e.getMessage());
} finally {
executorService.shutdownNow();
}
}
/**
* Testing methods {@link IgniteUtils#writeLongString} and
* {@link IgniteUtils#readLongString} using resource files, where each line is
* needed to test different cases:
* 1){@code null}. <br/>
*
* 2)Empty line. <br/>
*
* 3)Simple strings. <br/>
*
* 4)Various combinations of strings with one, two, and three-byte
* characters with size greater than {@link IgniteUtils#UTF_BYTE_LIMIT}. <br/>
*
* @throws Exception If failed.
*/
@Test
public void testReadWriteBigUTF() throws Exception {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
readLines("org.apache.ignite.util/bigUtf.txt", readLine -> {
baos.reset();
DataOutput dOut = new DataOutputStream(baos);
U.writeLongString(dOut, readLine);
DataInputStream dIn = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()));
String readBigUTF = U.readLongString(dIn);
assertEquals(readLine, readBigUTF);
});
}
}
/**
* Testing method {@link IgniteUtils#writeCutString} using resource files,
* where each line is needed to test different cases: <br/>
* 1){@code null}. <br/>
*
* 2)Empty line. <br/>
*
* 3)Simple strings. <br/>
*
* 4)String containing single-byte characters of size
* {@link IgniteUtils#UTF_BYTE_LIMIT}. <br/>
*
* 5)String containing single-byte characters of size more than
* {@link IgniteUtils#UTF_BYTE_LIMIT}. <br/>
*
* 6)String containing two-byte characters of size
* {@link IgniteUtils#UTF_BYTE_LIMIT}. <br/>
*
* 7)String containing two-byte characters of size more than
* {@link IgniteUtils#UTF_BYTE_LIMIT}. <br/>
*
* 8)String containing three-byte characters of size
* {@link IgniteUtils#UTF_BYTE_LIMIT}. <br/>
*
* 9)String containing three-byte characters of size more than
* {@link IgniteUtils#UTF_BYTE_LIMIT}. <br/>
*
* @throws Exception If failed.
*/
@Test
public void testWriteLimitUTF() throws Exception {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
readLines("org.apache.ignite.util/limitUtf.txt", readLine -> {
baos.reset();
DataOutput dOut = new DataOutputStream(baos);
U.writeCutString(dOut, readLine);
DataInputStream dIn = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()));
String readUTF = U.readString(dIn);
if (nonNull(readLine)) {
AtomicInteger utfBytes = new AtomicInteger();
readLine = readLine.chars()
.filter(c -> utfBytes.addAndGet(U.utfBytes((char)c)) <= U.UTF_BYTE_LIMIT)
.mapToObj(c -> String.valueOf((char)c)).collect(joining());
}
assertEquals(readLine, readUTF);
});
}
}
/**
* Test of {@link U#humanReadableDuration}.
*/
@Test
public void testHumanReadableDuration() {
assertEquals("0ms", U.humanReadableDuration(0));
assertEquals("10ms", U.humanReadableDuration(10));
assertEquals("1s", U.humanReadableDuration(SECONDS.toMillis(1)));
assertEquals("1s", U.humanReadableDuration(SECONDS.toMillis(1) + 10));
assertEquals("12s", U.humanReadableDuration(SECONDS.toMillis(12)));
assertEquals("1m", U.humanReadableDuration(MINUTES.toMillis(1)));
assertEquals("2m", U.humanReadableDuration(MINUTES.toMillis(2)));
assertEquals("1m5s", U.humanReadableDuration(SECONDS.toMillis(65)));
assertEquals("1m5s", U.humanReadableDuration(SECONDS.toMillis(65) + 10));
assertEquals("1h", U.humanReadableDuration(HOURS.toMillis(1)));
assertEquals("3h", U.humanReadableDuration(HOURS.toMillis(3)));
assertEquals(
"1h5m12s",
U.humanReadableDuration(MINUTES.toMillis(65) + SECONDS.toMillis(12) + 10)
);
assertEquals("1d", U.humanReadableDuration(DAYS.toMillis(1)));
assertEquals("15d", U.humanReadableDuration(DAYS.toMillis(15)));
assertEquals("1d4h", U.humanReadableDuration(HOURS.toMillis(28)));
assertEquals(
"4d6h15m",
U.humanReadableDuration(DAYS.toMillis(4) + HOURS.toMillis(6) + MINUTES.toMillis(15))
);
}
/**
* Test of {@link U#humanReadableByteCount}.
*/
@Test
public void testHumanReadableByteCount() {
assertEquals("0.0 B", U.humanReadableByteCount(0));
assertEquals("10.0 B", U.humanReadableByteCount(10));
assertEquals("1.0 KB", U.humanReadableByteCount(1024));
assertEquals("15.0 KB", U.humanReadableByteCount(15 * 1024));
assertEquals("15.0 KB", U.humanReadableByteCount(15 * 1024 + 10));
assertEquals("1.0 MB", U.humanReadableByteCount(1024 * 1024));
assertEquals("6.0 MB", U.humanReadableByteCount(6 * 1024 * 1024));
assertEquals("6.1 MB", U.humanReadableByteCount(6 * 1024 * 1024 + 130 * 1024));
}
/**
* Test to verify the {@link U#uncompressedSize}.
*
* @throws Exception If failed.
*/
@Test
public void testUncompressedSize() throws Exception {
File zipFile = new File(System.getProperty("java.io.tmpdir"), "test.zip");
try {
assertThrows(log, () -> U.uncompressedSize(zipFile), IOException.class, null);
byte[] raw = IntStream.range(0, 10).mapToObj(i -> zipFile.getAbsolutePath() + i)
.collect(joining()).getBytes(StandardCharsets.UTF_8);
try (FileOutputStream fos = new FileOutputStream(zipFile)) {
fos.write(U.zip(raw));
fos.flush();
}
assertEquals(raw.length, U.uncompressedSize(zipFile));
}
finally {
assertTrue(U.delete(zipFile));
}
}
/**
* Reading lines from a resource file and passing them to consumer.
* If read string is {@code "null"}, it is converted to {@code null}.
*
* @param rsrcName Resource name.
* @param consumer Consumer.
* @throws Exception If failed.
*/
private void readLines(String rsrcName, ThrowableConsumer<String> consumer) throws Exception {
byte[] content = readResource(getClass().getClassLoader(), rsrcName);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(content)))) {
String readLine;
while (nonNull(readLine = reader.readLine())) {
if ("null".equals(readLine))
readLine = null;
consumer.accept(readLine);
}
}
}
/**
* Test enum.
*/
private enum TestEnum {
E1,
E2,
E3
}
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE)
private @interface Ann1 {}
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE)
private @interface Ann2 {}
private static class A1 implements I3, I5 {}
private static class A2 extends A1 {}
private static class A3 implements I5 {}
@Ann1 private interface I1 {}
private interface I2 extends I1 {}
private interface I3 extends I2 {}
@Ann2 private interface I4 {}
private interface I5 extends I4 {}
/**
* Represents an operation that accepts a single input argument and returns
* no result. Unlike most other functional interfaces,
* {@code ThrowableConsumer} is expected to operate via side-effects.
*
* Also it is able to throw {@link Exception} unlike {@link Consumer}.
*
* @param <T> The type of the input to the operation.
*/
@FunctionalInterface
private static interface ThrowableConsumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument.
*/
void accept(@Nullable T t) throws Exception;
}
/**
* Test to verify the {@link U#hashToIndex(int, int)}.
*/
@Test
public void testHashToIndexDistribution() {
assertEquals(0, U.hashToIndex(1, 1));
assertEquals(0, U.hashToIndex(2, 1));
assertEquals(1, U.hashToIndex(1, 2));
assertEquals(0, U.hashToIndex(2, 2));
assertEquals(1, U.hashToIndex(1, 4));
assertEquals(2, U.hashToIndex(2, 4));
assertEquals(3, U.hashToIndex(3, 4));
assertEquals(0, U.hashToIndex(4, 4));
assertEquals(1, U.hashToIndex(5, 4));
assertEquals(0, U.hashToIndex(8, 4));
assertEquals(3, U.hashToIndex(15, 4));
assertEquals(1, U.hashToIndex(-1, 4));
assertEquals(2, U.hashToIndex(-2, 4));
assertEquals(3, U.hashToIndex(-3, 4));
assertEquals(0, U.hashToIndex(-4, 4));
assertEquals(1, U.hashToIndex(-5, 4));
assertEquals(0, U.hashToIndex(-8, 4));
assertEquals(3, U.hashToIndex(-15, 4));
}
}