1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import impl.SimpleResolverProviderImpl;
import org.testng.Assert;
import org.testng.annotations.Test;
/*
* @test
* @summary Test that stale InetAddress caching security properties work as
* expected when a custom resolver is installed.
* @library lib providers/simple
* @build test.library/testlib.ResolutionRegistry
* simple.provider/impl.SimpleResolverProviderImpl AddressesStaleCachingTest
* @run testng/othervm -Djava.security.properties=${test.src}/props/CacheStale.props AddressesStaleCachingTest
*/
public class AddressesStaleCachingTest {
private static class Lookup {
private final byte[] address;
private final long timestamp;
private Lookup(byte[] address, long timestamp) {
this.address = address;
this.timestamp = timestamp;
}
}
/**
* Validates successful and unsuccessful lookups when the stale cache is
* enabled.
*/
@Test
public void testRefresh() throws Exception{
// The first request is to save the data into the cache
Lookup first = doLookup(false, 0);
Thread.sleep(10000); // intentionally big delay > x2 stale property
// The refreshTime is expired, we will do the successful lookup.
Lookup second = doLookup(false, 0);
Assert.assertNotEquals(first.timestamp, second.timestamp,
"Two lookups are expected");
Thread.sleep(10000); // intentionally big delay > x2 stale property
// The refreshTime is expired again, we will do the failed lookup.
Lookup third = doLookup(true, 0);
Assert.assertNotEquals(second.timestamp, third.timestamp,
"Two lookups are expected");
// The stale cache is enabled, so we should get valid/same data for
// all requests(even for the failed request).
Assert.assertEquals(first.address, second.address,
"Same address is expected");
Assert.assertEquals(second.address, third.address,
"Same address is expected");
}
/**
* Validates that only one thread is blocked during "refresh", all others
* will continue to use the "stale" data.
*/
@Test
public void testOnlyOneThreadIsBlockedDuringRefresh() throws Exception {
long timeout = System.nanoTime() + TimeUnit.SECONDS.toNanos(12);
doLookup(false, timeout);
Thread.sleep(9000);
CountDownLatch blockServer = new CountDownLatch(1);
SimpleResolverProviderImpl.setBlocker(blockServer);
Thread ts[] = new Thread[10];
CountDownLatch wait9 = new CountDownLatch(ts.length - 1);
CountDownLatch wait10 = new CountDownLatch(ts.length);
CountDownLatch start = new CountDownLatch(ts.length);
for (int i = 0; i < ts.length; i++) {
ts[i] = new Thread(() -> {
start.countDown();
try {
start.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
doLookup(true, timeout);
wait9.countDown();
wait10.countDown();
});
}
for (Thread t : ts) {
t.start();
}
if (!wait9.await(10, TimeUnit.SECONDS)) {
blockServer.countDown();
throw new RuntimeException("Some threads hang");
}
blockServer.countDown();
if (!wait10.await(10, TimeUnit.SECONDS)) {
throw new RuntimeException("The last thread hangs");
}
}
private static Lookup doLookup(boolean error, long timeout) {
SimpleResolverProviderImpl.setUnreachableServer(error);
try {
byte[] firstAddress = InetAddress.getByName("javaTest.org").getAddress();
long firstTimestamp = SimpleResolverProviderImpl.getLastLookupTimestamp();
byte[] secondAddress = InetAddress.getByName("javaTest.org").getAddress();
long secondTimestamp = SimpleResolverProviderImpl.getLastLookupTimestamp();
Assert.assertEquals(firstAddress, secondAddress,
"Same address is expected");
if (timeout == 0 || timeout - System.nanoTime() > 0) {
Assert.assertEquals(firstTimestamp, secondTimestamp,
"Only one positive lookup is expected with caching enabled");
}
return new Lookup(firstAddress, firstTimestamp);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
}
|