DnsResolver cts changes to match API council requests
Bug: 129261432
Test: atest DnsResolverTest
Merged-In: I42df921cc3bb01ea25a671d5a1af678a6d3f5872
(cherry picked from commit 89996844304a2919f8cd000f82a4d1af9de3df01)
Change-Id: Ibcb92ac23cf413322234bba9100293ab794cf50e
diff --git a/tests/cts/net/src/android/net/cts/DnsResolverTest.java b/tests/cts/net/src/android/net/cts/DnsResolverTest.java
index 0ff6cd8..40d64cf 100644
--- a/tests/cts/net/src/android/net/cts/DnsResolverTest.java
+++ b/tests/cts/net/src/android/net/cts/DnsResolverTest.java
@@ -39,13 +39,14 @@
import android.test.AndroidTestCase;
import android.util.Log;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
public class DnsResolverTest extends AndroidTestCase {
private static final String TAG = "DnsResolverTest";
@@ -53,7 +54,9 @@
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
static final int TIMEOUT_MS = 12_000;
+ static final int CANCEL_TIMEOUT_MS = 3_000;
static final int CANCEL_RETRY_TIMES = 5;
+ static final int NXDOMAIN = 3;
private ConnectivityManager mCM;
private Executor mExecutor;
@@ -94,73 +97,26 @@
return testableNetworks.toArray(new Network[0]);
}
- public void testQueryWithInetAddressCallback() {
- final String dname = "www.google.com";
- final String msg = "Query with InetAddressAnswerCallback " + dname;
- for (Network network : getTestableNetworks()) {
- final CountDownLatch latch = new CountDownLatch(1);
- final AtomicReference<List<InetAddress>> answers = new AtomicReference<>();
- final DnsResolver.InetAddressAnswerCallback callback =
- new DnsResolver.InetAddressAnswerCallback() {
- @Override
- public void onAnswer(@NonNull List<InetAddress> answerList) {
- answers.set(answerList);
- for (InetAddress addr : answerList) {
- Log.d(TAG, "Reported addr: " + addr.toString());
- }
- latch.countDown();
- }
-
- @Override
- public void onParseException(@NonNull ParseException e) {
- fail(msg + e.getMessage());
- }
-
- @Override
- public void onQueryException(@NonNull ErrnoException e) {
- fail(msg + e.getMessage());
- }
- };
- mDns.query(network, dname, CLASS_IN, TYPE_A, FLAG_NO_CACHE_LOOKUP,
- mExecutor, null, callback);
- try {
- assertTrue(msg + " but no valid answer after " + TIMEOUT_MS + "ms.",
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- assertGreaterThan(msg + " returned 0 result", answers.get().size(), 0);
- } catch (InterruptedException e) {
- fail(msg + " Waiting for DNS lookup was interrupted");
- }
- }
- }
-
static private void assertGreaterThan(String msg, int first, int second) {
assertTrue(msg + " Excepted " + first + " to be greater than " + second, first > second);
}
- static private void assertValidAnswer(String msg, @NonNull DnsAnswer ans) {
- // Check rcode field.(0, No error condition).
- assertTrue(msg + " Response error, rcode: " + ans.getRcode(), ans.getRcode() == 0);
- // Check answer counts.
- assertGreaterThan(msg + " No answer found", ans.getANCount(), 0);
- // Check question counts.
- assertGreaterThan(msg + " No question found", ans.getQDCount(), 0);
- }
+ private static class DnsParseException extends Exception {
+ public DnsParseException(String msg) {
+ super(msg);
+ }
- static private void assertValidEmptyAnswer(String msg, @NonNull DnsAnswer ans) {
- // Check rcode field.(0, No error condition).
- assertTrue(msg + " Response error, rcode: " + ans.getRcode(), ans.getRcode() == 0);
- // Check answer counts. Expect 0 answer.
- assertTrue(msg + " Not an empty answer", ans.getANCount() == 0);
- // Check question counts.
- assertGreaterThan(msg + " No question found", ans.getQDCount(), 0);
+ public DnsParseException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
}
private static class DnsAnswer extends DnsPacket {
- DnsAnswer(@NonNull byte[] data) throws ParseException {
+ DnsAnswer(@NonNull byte[] data) throws DnsParseException {
super(data);
// Check QR field.(query (0), or a response (1)).
if ((mHeader.flags & (1 << 15)) == 0) {
- throw new ParseException("Not an answer packet");
+ throw new DnsParseException("Not an answer packet");
}
}
@@ -175,63 +131,116 @@
}
}
- class RawAnswerCallbackImpl extends DnsResolver.RawAnswerCallback {
+ /**
+ * A query callback that ensures that the query is cancelled and that onAnswer is never
+ * called. If the query succeeds before it is cancelled, needRetry will return true so the
+ * test can retry.
+ */
+ class VerifyCancelCallback implements DnsResolver.Callback<byte[]> {
private final CountDownLatch mLatch = new CountDownLatch(1);
private final String mMsg;
- private final int mTimeout;
+ private final CancellationSignal mCancelSignal;
+ private int mRcode;
+ private DnsAnswer mDnsAnswer;
- RawAnswerCallbackImpl(@NonNull String msg, int timeout) {
+ VerifyCancelCallback(@NonNull String msg, @Nullable CancellationSignal cancel) {
this.mMsg = msg;
- this.mTimeout = timeout;
+ this.mCancelSignal = cancel;
+ this.mDnsAnswer = null;
}
- RawAnswerCallbackImpl(@NonNull String msg) {
- this(msg, TIMEOUT_MS);
+ VerifyCancelCallback(@NonNull String msg) {
+ this(msg, null);
+ }
+
+ public boolean waitForAnswer(int timeout) throws InterruptedException {
+ return mLatch.await(timeout, TimeUnit.MILLISECONDS);
}
public boolean waitForAnswer() throws InterruptedException {
- return mLatch.await(mTimeout, TimeUnit.MILLISECONDS);
+ return waitForAnswer(TIMEOUT_MS);
+ }
+
+ public boolean needRetry() throws InterruptedException {
+ return mLatch.await(CANCEL_TIMEOUT_MS, TimeUnit.MILLISECONDS);
}
@Override
- public void onAnswer(@NonNull byte[] answer) {
+ public void onAnswer(@NonNull byte[] answer, int rcode) {
+ if (mCancelSignal != null && mCancelSignal.isCanceled()) {
+ fail(mMsg + " should not have returned any answers");
+ }
+
+ mRcode = rcode;
try {
- assertValidAnswer(mMsg, new DnsAnswer(answer));
- Log.d(TAG, "Reported blob: " + byteArrayToHexString(answer));
- mLatch.countDown();
- } catch (ParseException e) {
+ mDnsAnswer = new DnsAnswer(answer);
+ } catch (DnsParseException e) {
fail(mMsg + e.getMessage());
}
+ Log.d(TAG, "Reported blob: " + byteArrayToHexString(answer));
+ mLatch.countDown();
}
@Override
- public void onParseException(@NonNull ParseException e) {
- fail(mMsg + e.getMessage());
+ public void onError(@NonNull DnsResolver.DnsException error) {
+ fail(mMsg + error.getMessage());
}
- @Override
- public void onQueryException(@NonNull ErrnoException e) {
- fail(mMsg + e.getMessage());
+ private void assertValidAnswer() {
+ assertTrue(mMsg + "No valid answer", mDnsAnswer != null);
+ assertTrue(mMsg + " Unexpected error: reported rcode" + mRcode +
+ " blob's rcode " + mDnsAnswer.getRcode(), mRcode == mDnsAnswer.getRcode());
+ }
+
+ public void assertHasAnswer() {
+ assertValidAnswer();
+ // Check rcode field.(0, No error condition).
+ assertTrue(mMsg + " Response error, rcode: " + mRcode, mRcode == 0);
+ // Check answer counts.
+ assertGreaterThan(mMsg + " No answer found", mDnsAnswer.getANCount(), 0);
+ // Check question counts.
+ assertGreaterThan(mMsg + " No question found", mDnsAnswer.getQDCount(), 0);
+ }
+
+ public void assertNXDomain() {
+ assertValidAnswer();
+ // Check rcode field.(3, NXDomain).
+ assertTrue(mMsg + " Unexpected rcode: " + mRcode, mRcode == NXDOMAIN);
+ // Check answer counts. Expect 0 answer.
+ assertTrue(mMsg + " Not an empty answer", mDnsAnswer.getANCount() == 0);
+ // Check question counts.
+ assertGreaterThan(mMsg + " No question found", mDnsAnswer.getQDCount(), 0);
+ }
+
+ public void assertEmptyAnswer() {
+ assertValidAnswer();
+ // Check rcode field.(0, No error condition).
+ assertTrue(mMsg + " Response error, rcode: " + mRcode, mRcode == 0);
+ // Check answer counts. Expect 0 answer.
+ assertTrue(mMsg + " Not an empty answer", mDnsAnswer.getANCount() == 0);
+ // Check question counts.
+ assertGreaterThan(mMsg + " No question found", mDnsAnswer.getQDCount(), 0);
}
}
- public void testQueryWithRawAnswerCallback() {
+ public void testRawQuery() {
final String dname = "www.google.com";
- final String msg = "Query with RawAnswerCallback " + dname;
+ final String msg = "RawQuery " + dname;
for (Network network : getTestableNetworks()) {
- final RawAnswerCallbackImpl callback = new RawAnswerCallbackImpl(msg);
- mDns.query(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
+ final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
+ mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
mExecutor, null, callback);
try {
assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
callback.waitForAnswer());
+ callback.assertHasAnswer();
} catch (InterruptedException e) {
fail(msg + " Waiting for DNS lookup was interrupted");
}
}
}
- public void testQueryBlobWithRawAnswerCallback() {
+ public void testRawQueryBlob() {
final byte[] blob = new byte[]{
/* Header */
0x55, 0x66, /* Transaction ID */
@@ -246,137 +255,58 @@
0x00, 0x01, /* Type */
0x00, 0x01 /* Class */
};
- final String msg = "Query with RawAnswerCallback " + byteArrayToHexString(blob);
+ final String msg = "RawQuery blob " + byteArrayToHexString(blob);
for (Network network : getTestableNetworks()) {
- final RawAnswerCallbackImpl callback = new RawAnswerCallbackImpl(msg);
- mDns.query(network, blob, FLAG_NO_CACHE_LOOKUP, mExecutor, null, callback);
+ final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
+ mDns.rawQuery(network, blob, FLAG_NO_CACHE_LOOKUP, mExecutor, null, callback);
try {
assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
callback.waitForAnswer());
+ callback.assertHasAnswer();
} catch (InterruptedException e) {
fail(msg + " Waiting for DNS lookup was interrupted");
}
}
}
- public void testQueryRoot() {
+ public void testRawQueryRoot() {
final String dname = "";
- final String msg = "Query with RawAnswerCallback empty dname(ROOT) ";
+ final String msg = "RawQuery empty dname(ROOT) ";
for (Network network : getTestableNetworks()) {
- final CountDownLatch latch = new CountDownLatch(1);
- final DnsResolver.RawAnswerCallback callback = new DnsResolver.RawAnswerCallback() {
- @Override
- public void onAnswer(@NonNull byte[] answer) {
- try {
- // Except no answer record because of querying with empty dname(ROOT)
- assertValidEmptyAnswer(msg, new DnsAnswer(answer));
- latch.countDown();
- } catch (ParseException e) {
- fail(msg + e.getMessage());
- }
- }
-
- @Override
- public void onParseException(@NonNull ParseException e) {
- fail(msg + e.getMessage());
- }
-
- @Override
- public void onQueryException(@NonNull ErrnoException e) {
- fail(msg + e.getMessage());
- }
- };
- mDns.query(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
+ final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
+ mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
mExecutor, null, callback);
try {
- assertTrue(msg + "but no answer after " + TIMEOUT_MS + "ms.",
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ // Except no answer record because of querying with empty dname(ROOT)
+ callback.assertEmptyAnswer();
} catch (InterruptedException e) {
fail(msg + "Waiting for DNS lookup was interrupted");
}
}
}
- public void testQueryNXDomain() {
+ public void testRawQueryNXDomain() {
final String dname = "test1-nx.metric.gstatic.com";
- final String msg = "Query with InetAddressAnswerCallback " + dname;
+ final String msg = "RawQuery " + dname;
for (Network network : getTestableNetworks()) {
- final CountDownLatch latch = new CountDownLatch(1);
- final DnsResolver.InetAddressAnswerCallback callback =
- new DnsResolver.InetAddressAnswerCallback() {
- @Override
- public void onAnswer(@NonNull List<InetAddress> answerList) {
- if (answerList.size() == 0) {
- latch.countDown();
- return;
- }
- fail(msg + " but get valid answers");
- }
-
- @Override
- public void onParseException(@NonNull ParseException e) {
- fail(msg + e.getMessage());
- }
-
- @Override
- public void onQueryException(@NonNull ErrnoException e) {
- fail(msg + e.getMessage());
- }
- };
- mDns.query(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
+ final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
+ mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
mExecutor, null, callback);
try {
assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ callback.waitForAnswer());
+ callback.assertNXDomain();
} catch (InterruptedException e) {
fail(msg + " Waiting for DNS lookup was interrupted");
}
}
}
- /**
- * A query callback that ensures that the query is cancelled and that onAnswer is never
- * called. If the query succeeds before it is cancelled, needRetry will return true so the
- * test can retry.
- */
- class VerifyCancelCallback extends DnsResolver.RawAnswerCallback {
- private static final int CANCEL_TIMEOUT = 3_000;
-
- private final CountDownLatch mLatch = new CountDownLatch(1);
- private final String mMsg;
- private final CancellationSignal mCancelSignal;
-
- VerifyCancelCallback(@NonNull String msg, @NonNull CancellationSignal cancelSignal) {
- this.mMsg = msg;
- this.mCancelSignal = cancelSignal;
- }
-
- public boolean needRetry() throws InterruptedException {
- return mLatch.await(CANCEL_TIMEOUT, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public void onAnswer(@NonNull byte[] answer) {
- if (mCancelSignal.isCanceled()) {
- fail(mMsg + " should not have returned any answers");
- }
- mLatch.countDown();
- }
-
- @Override
- public void onParseException(@NonNull ParseException e) {
- fail(mMsg + e.getMessage());
- }
-
- @Override
- public void onQueryException(@NonNull ErrnoException e) {
- fail(mMsg + e.getMessage());
- }
- }
-
- public void testQueryCancel() throws ErrnoException {
+ public void testRawQueryCancel() throws ErrnoException {
final String dname = "www.google.com";
- final String msg = "Test cancel query " + dname;
+ final String msg = "Test cancel RawQuery " + dname;
// Start a DNS query and the cancel it immediately. Use VerifyCancelCallback to expect
// that the query is cancelled before it succeeds. If it is not cancelled before it
// succeeds, retry the test until it is.
@@ -390,7 +320,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final CancellationSignal cancelSignal = new CancellationSignal();
final VerifyCancelCallback callback = new VerifyCancelCallback(msg, cancelSignal);
- mDns.query(network, dname, CLASS_IN, TYPE_AAAA, FLAG_EMPTY,
+ mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_EMPTY,
mExecutor, cancelSignal, callback);
mExecutor.execute(() -> {
cancelSignal.cancel();
@@ -399,7 +329,7 @@
try {
retry = callback.needRetry();
assertTrue(msg + " query was not cancelled",
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
fail(msg + "Waiting for DNS lookup was interrupted");
}
@@ -407,7 +337,7 @@
}
}
- public void testQueryBlobCancel() throws ErrnoException {
+ public void testRawQueryBlobCancel() throws ErrnoException {
final byte[] blob = new byte[]{
/* Header */
0x55, 0x66, /* Transaction ID */
@@ -422,7 +352,7 @@
0x00, 0x01, /* Type */
0x00, 0x01 /* Class */
};
- final String msg = "Test cancel raw Query " + byteArrayToHexString(blob);
+ final String msg = "Test cancel RawQuery blob " + byteArrayToHexString(blob);
// Start a DNS query and the cancel it immediately. Use VerifyCancelCallback to expect
// that the query is cancelled before it succeeds. If it is not cancelled before it
// succeeds, retry the test until it is.
@@ -436,7 +366,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final CancellationSignal cancelSignal = new CancellationSignal();
final VerifyCancelCallback callback = new VerifyCancelCallback(msg, cancelSignal);
- mDns.query(network, blob, FLAG_EMPTY, mExecutor, cancelSignal, callback);
+ mDns.rawQuery(network, blob, FLAG_EMPTY, mExecutor, cancelSignal, callback);
mExecutor.execute(() -> {
cancelSignal.cancel();
latch.countDown();
@@ -444,7 +374,7 @@
try {
retry = callback.needRetry();
assertTrue(msg + " cancel is not done",
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
fail(msg + " Waiting for DNS lookup was interrupted");
}
@@ -454,16 +384,16 @@
public void testCancelBeforeQuery() throws ErrnoException {
final String dname = "www.google.com";
- final String msg = "Test cancelled query " + dname;
+ final String msg = "Test cancelled RawQuery " + dname;
for (Network network : getTestableNetworks()) {
- final RawAnswerCallbackImpl callback = new RawAnswerCallbackImpl(msg, 3_000);
+ final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
final CancellationSignal cancelSignal = new CancellationSignal();
cancelSignal.cancel();
- mDns.query(network, dname, CLASS_IN, TYPE_AAAA, FLAG_EMPTY,
+ mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_EMPTY,
mExecutor, cancelSignal, callback);
try {
assertTrue(msg + " should not return any answers",
- !callback.waitForAnswer());
+ !callback.waitForAnswer(CANCEL_TIMEOUT_MS));
} catch (InterruptedException e) {
fail(msg + " Waiting for DNS lookup was interrupted");
}
@@ -476,9 +406,7 @@
* before it is cancelled, needRetry will return true so the
* test can retry.
*/
- class VerifyCancelInetAddressCallback extends DnsResolver.InetAddressAnswerCallback {
- private static final int CANCEL_TIMEOUT = 3_000;
-
+ class VerifyCancelInetAddressCallback implements DnsResolver.Callback<List<InetAddress>> {
private final CountDownLatch mLatch = new CountDownLatch(1);
private final String mMsg;
private final List<InetAddress> mAnswers;
@@ -495,31 +423,43 @@
}
public boolean needRetry() throws InterruptedException {
- return mLatch.await(CANCEL_TIMEOUT, TimeUnit.MILLISECONDS);
+ return mLatch.await(CANCEL_TIMEOUT_MS, TimeUnit.MILLISECONDS);
}
public boolean isAnswerEmpty() {
return mAnswers.isEmpty();
}
+ public boolean hasIpv6Answer() {
+ for (InetAddress answer : mAnswers) {
+ if (answer instanceof Inet6Address) return true;
+ }
+ return false;
+ }
+
+ public boolean hasIpv4Answer() {
+ for (InetAddress answer : mAnswers) {
+ if (answer instanceof Inet4Address) return true;
+ }
+ return false;
+ }
+
@Override
- public void onAnswer(@NonNull List<InetAddress> answerList) {
+ public void onAnswer(@NonNull List<InetAddress> answerList, int rcode) {
if (mCancelSignal != null && mCancelSignal.isCanceled()) {
fail(mMsg + " should not have returned any answers");
}
+ for (InetAddress addr : answerList) {
+ Log.d(TAG, "Reported addr: " + addr.toString());
+ }
mAnswers.clear();
mAnswers.addAll(answerList);
mLatch.countDown();
}
@Override
- public void onParseException(@NonNull ParseException e) {
- fail(mMsg + e.getMessage());
- }
-
- @Override
- public void onQueryException(@NonNull ErrnoException e) {
- fail(mMsg + e.getMessage());
+ public void onError(@NonNull DnsResolver.DnsException error) {
+ fail(mMsg + error.getMessage());
}
}
@@ -544,8 +484,8 @@
public void testQueryCancelForInetAddress() throws ErrnoException {
final String dname = "www.google.com";
final String msg = "Test cancel query for InetAddress " + dname;
- // Start a DNS query and the cancel it immediately. Use VerifyCancelCallback to expect
- // that the query is cancelled before it succeeds. If it is not cancelled before it
+ // Start a DNS query and the cancel it immediately. Use VerifyCancelInetAddressCallback to
+ // expect that the query is cancelled before it succeeds. If it is not cancelled before it
// succeeds, retry the test until it is.
for (Network network : getTestableNetworks()) {
boolean retry = false;
@@ -566,11 +506,49 @@
try {
retry = callback.needRetry();
assertTrue(msg + " query was not cancelled",
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
fail(msg + "Waiting for DNS lookup was interrupted");
}
} while (retry);
}
}
+
+ public void testQueryForInetAddressIpv4() {
+ final String dname = "www.google.com";
+ final String msg = "Test query for IPv4 InetAddress " + dname;
+ for (Network network : getTestableNetworks()) {
+ final VerifyCancelInetAddressCallback callback =
+ new VerifyCancelInetAddressCallback(msg, null);
+ mDns.query(network, dname, TYPE_A, FLAG_NO_CACHE_LOOKUP,
+ mExecutor, null, callback);
+ try {
+ assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty());
+ assertTrue(msg + " returned Ipv6 results", !callback.hasIpv6Answer());
+ } catch (InterruptedException e) {
+ fail(msg + " Waiting for DNS lookup was interrupted");
+ }
+ }
+ }
+
+ public void testQueryForInetAddressIpv6() {
+ final String dname = "www.google.com";
+ final String msg = "Test query for IPv6 InetAddress " + dname;
+ for (Network network : getTestableNetworks()) {
+ final VerifyCancelInetAddressCallback callback =
+ new VerifyCancelInetAddressCallback(msg, null);
+ mDns.query(network, dname, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
+ mExecutor, null, callback);
+ try {
+ assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
+ callback.waitForAnswer());
+ assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty());
+ assertTrue(msg + " returned Ipv4 results", !callback.hasIpv4Answer());
+ } catch (InterruptedException e) {
+ fail(msg + " Waiting for DNS lookup was interrupted");
+ }
+ }
+ }
}