diff options
author | Hungming Chen <nuccachen@google.com> | 2019-04-10 17:34:06 +0800 |
---|---|---|
committer | Hungming Chen <nuccachen@google.com> | 2019-06-06 09:46:45 +0800 |
commit | e8f970cd88e1ce008f9671fa9305d2018a09a500 (patch) | |
tree | b35201a7ede768fb146724affce4b58f9bb1efed /tests/dns_metrics_listener | |
parent | 41b82c41f3f1b8c33f7d37c71bb8b8bcaa7c68b2 (diff) | |
download | DnsResolver-e8f970cd88e1ce008f9671fa9305d2018a09a500.tar.gz |
resolv_integration_test: Retrieve NAT64 prefix through DNS event listener
Currently, the unit test could retrieve NAT64 prefix through registering a
DNS event listener. It doesn't need to query the prefix through the binder
interface method getPrefix64() anymore.
Test: built, flashed, booted
system/netd/tests/runtests.sh passes
Change-Id: I54386f7d8c03f7009c12fe3fc39da85985d8d3ad
Diffstat (limited to 'tests/dns_metrics_listener')
-rw-r--r-- | tests/dns_metrics_listener/Android.bp | 17 | ||||
-rw-r--r-- | tests/dns_metrics_listener/base_metrics_listener.cpp | 72 | ||||
-rw-r--r-- | tests/dns_metrics_listener/base_metrics_listener.h | 63 | ||||
-rw-r--r-- | tests/dns_metrics_listener/dns_metrics_listener.cpp | 55 | ||||
-rw-r--r-- | tests/dns_metrics_listener/dns_metrics_listener.h | 61 | ||||
-rw-r--r-- | tests/dns_metrics_listener/test_metrics.cpp | 85 | ||||
-rw-r--r-- | tests/dns_metrics_listener/test_metrics.h | 97 |
7 files changed, 450 insertions, 0 deletions
diff --git a/tests/dns_metrics_listener/Android.bp b/tests/dns_metrics_listener/Android.bp new file mode 100644 index 00000000..a0b93c91 --- /dev/null +++ b/tests/dns_metrics_listener/Android.bp @@ -0,0 +1,17 @@ +cc_test_library { + name: "libnetd_test_metrics_listener", + defaults: ["netd_defaults"], + srcs: [ + "base_metrics_listener.cpp", + "dns_metrics_listener.cpp", + "test_metrics.cpp", + ], + shared_libs: [ + "libbase", + "libbinder", + "libutils", + ], + static_libs: [ + "netd_event_listener_interface-V1-cpp", + ], +}
\ No newline at end of file diff --git a/tests/dns_metrics_listener/base_metrics_listener.cpp b/tests/dns_metrics_listener/base_metrics_listener.cpp new file mode 100644 index 00000000..e6dbb325 --- /dev/null +++ b/tests/dns_metrics_listener/base_metrics_listener.cpp @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed 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. + */ + +#include "base_metrics_listener.h" + +namespace android { +namespace net { +namespace metrics { + +android::binder::Status BaseMetricsListener::onDnsEvent( + int32_t /*netId*/, int32_t /*eventType*/, int32_t /*returnCode*/, int32_t /*latencyMs*/, + const std::string& /*hostname*/, const ::std::vector<std::string>& /*ipAddresses*/, + int32_t /*ipAddressesCount*/, int32_t /*uid*/) { + // default no-op + return android::binder::Status::ok(); +}; + +android::binder::Status BaseMetricsListener::onPrivateDnsValidationEvent( + int32_t /*netId*/, const ::android::String16& /*ipAddress*/, + const ::android::String16& /*hostname*/, bool /*validated*/) { + // default no-op + return android::binder::Status::ok(); +}; + +android::binder::Status BaseMetricsListener::onConnectEvent(int32_t /*netId*/, int32_t /*error*/, + int32_t /*latencyMs*/, + const ::android::String16& /*ipAddr*/, + int32_t /*port*/, int32_t /*uid*/) { + // default no-op + return android::binder::Status::ok(); +}; + +android::binder::Status BaseMetricsListener::onWakeupEvent( + const ::android::String16& /*prefix*/, int32_t /*uid*/, int32_t /*ethertype*/, + int32_t /*ipNextHeader*/, const ::std::vector<uint8_t>& /*dstHw*/, + const ::android::String16& /*srcIp*/, const ::android::String16& /*dstIp*/, + int32_t /*srcPort*/, int32_t /*dstPort*/, int64_t /*timestampNs*/) { + // default no-op + return android::binder::Status::ok(); +}; + +android::binder::Status BaseMetricsListener::onTcpSocketStatsEvent( + const ::std::vector<int32_t>& /*networkIds*/, const ::std::vector<int32_t>& /*sentPackets*/, + const ::std::vector<int32_t>& /*lostPackets*/, const ::std::vector<int32_t>& /*rttUs*/, + const ::std::vector<int32_t>& /*sentAckDiffMs*/) { + // default no-op + return android::binder::Status::ok(); +}; + +android::binder::Status BaseMetricsListener::onNat64PrefixEvent( + int32_t /*netId*/, bool /*added*/, const ::std::string& /*prefixString*/, + int32_t /*prefixLength*/) { + // default no-op + return android::binder::Status::ok(); +}; + +} // namespace metrics +} // namespace net +} // namespace android
\ No newline at end of file diff --git a/tests/dns_metrics_listener/base_metrics_listener.h b/tests/dns_metrics_listener/base_metrics_listener.h new file mode 100644 index 00000000..9ba84239 --- /dev/null +++ b/tests/dns_metrics_listener/base_metrics_listener.h @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed 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. + */ + +#pragma once + +#include <string> +#include <vector> + +#include "android/net/metrics/BnNetdEventListener.h" + +namespace android { +namespace net { +namespace metrics { + +class BaseMetricsListener : public BnNetdEventListener { + public: + BaseMetricsListener() = default; + ~BaseMetricsListener() = default; + + virtual android::binder::Status onDnsEvent(int32_t /*netId*/, int32_t /*eventType*/, + int32_t /*returnCode*/, int32_t /*latencyMs*/, + const std::string& /*hostname*/, + const ::std::vector<std::string>& /*ipAddresses*/, + int32_t /*ipAddressesCount*/, + int32_t /*uid*/) override; + virtual android::binder::Status onPrivateDnsValidationEvent( + int32_t /*netId*/, const ::android::String16& /*ipAddress*/, + const ::android::String16& /*hostname*/, bool /*validated*/) override; + virtual android::binder::Status onConnectEvent(int32_t /*netId*/, int32_t /*error*/, + int32_t /*latencyMs*/, + const ::android::String16& /*ipAddr*/, + int32_t /*port*/, int32_t /*uid*/) override; + virtual android::binder::Status onWakeupEvent( + const ::android::String16& /*prefix*/, int32_t /*uid*/, int32_t /*ethertype*/, + int32_t /*ipNextHeader*/, const ::std::vector<uint8_t>& /*dstHw*/, + const ::android::String16& /*srcIp*/, const ::android::String16& /*dstIp*/, + int32_t /*srcPort*/, int32_t /*dstPort*/, int64_t /*timestampNs*/) override; + virtual android::binder::Status onTcpSocketStatsEvent( + const ::std::vector<int32_t>& /*networkIds*/, + const ::std::vector<int32_t>& /*sentPackets*/, + const ::std::vector<int32_t>& /*lostPackets*/, const ::std::vector<int32_t>& /*rttUs*/, + const ::std::vector<int32_t>& /*sentAckDiffMs*/) override; + virtual android::binder::Status onNat64PrefixEvent(int32_t /*netId*/, bool /*added*/, + const ::std::string& /*prefixString*/, + int32_t /*prefixLength*/) override; +}; + +} // namespace metrics +} // namespace net +} // namespace android
\ No newline at end of file diff --git a/tests/dns_metrics_listener/dns_metrics_listener.cpp b/tests/dns_metrics_listener/dns_metrics_listener.cpp new file mode 100644 index 00000000..8f3b6463 --- /dev/null +++ b/tests/dns_metrics_listener/dns_metrics_listener.cpp @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed 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. + */ + +#include "dns_metrics_listener.h" + +#include <android-base/chrono_utils.h> +#include <thread> + +namespace android { +namespace net { +namespace metrics { + +using std::chrono::milliseconds; + +constexpr milliseconds kRetryIntervalMs{20}; + +android::binder::Status DnsMetricsListener::onNat64PrefixEvent(int32_t netId, bool added, + const std::string& prefixString, + int32_t /*prefixLength*/) { + std::lock_guard lock(mMutex); + if (netId == mNetId) mNat64Prefix = added ? prefixString : ""; + return android::binder::Status::ok(); +} + +bool DnsMetricsListener::waitForNat64Prefix(ExpectNat64PrefixStatus status, + milliseconds timeout) const { + android::base::Timer t; + while (t.duration() < timeout) { + { + std::lock_guard lock(mMutex); + if ((status == EXPECT_FOUND && !mNat64Prefix.empty()) || + (status == EXPECT_NOT_FOUND && mNat64Prefix.empty())) + return true; + } + std::this_thread::sleep_for(kRetryIntervalMs); + } + return false; +} + +} // namespace metrics +} // namespace net +} // namespace android
\ No newline at end of file diff --git a/tests/dns_metrics_listener/dns_metrics_listener.h b/tests/dns_metrics_listener/dns_metrics_listener.h new file mode 100644 index 00000000..1f8170d3 --- /dev/null +++ b/tests/dns_metrics_listener/dns_metrics_listener.h @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed 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. + */ + +#pragma once + +#include <android-base/thread_annotations.h> + +#include "base_metrics_listener.h" + +enum ExpectNat64PrefixStatus : bool { + EXPECT_FOUND, + EXPECT_NOT_FOUND, +}; + +namespace android { +namespace net { +namespace metrics { + +// TODO: Perhaps use condition variable but continually polling. +// TODO: Perhaps create a queue to monitor the event changes. That improves the unit test which can +// verify the event count, the event change order, and so on. +class DnsMetricsListener : public BaseMetricsListener { + public: + DnsMetricsListener() = delete; + DnsMetricsListener(int32_t netId) : mNetId(netId){}; + + // Override DNS metrics event(s). + android::binder::Status onNat64PrefixEvent(int32_t netId, bool added, + const std::string& prefixString, + int32_t /*prefixLength*/) override; + + // Wait for expected NAT64 prefix status until timeout. + bool waitForNat64Prefix(ExpectNat64PrefixStatus status, + std::chrono::milliseconds timeout) const; + + private: + // Monitor the event which was fired on specific network id. + const int32_t mNetId; + + // The NAT64 prefix of the network |mNetId|. It is updated by the event onNat64PrefixEvent(). + std::string mNat64Prefix GUARDED_BY(mMutex); + + mutable std::mutex mMutex; +}; + +} // namespace metrics +} // namespace net +} // namespace android
\ No newline at end of file diff --git a/tests/dns_metrics_listener/test_metrics.cpp b/tests/dns_metrics_listener/test_metrics.cpp new file mode 100644 index 00000000..094c3a87 --- /dev/null +++ b/tests/dns_metrics_listener/test_metrics.cpp @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed 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. + */ + +#include "test_metrics.h" + +#include <netdb.h> + +namespace android { +namespace net { +namespace metrics { + +// Base class BaseTestMetricsEvent. +void BaseTestMetricsEvent::notify() { + std::lock_guard lock(mCvMutex); + mCv.notify_one(); +} + +void BaseTestMetricsEvent::setVerified(EventFlag event) { + mVerified |= event; +} + +// Derived class TestOnDnsEvent. +android::binder::Status TestOnDnsEvent::onDnsEvent(int32_t netId, int32_t eventType, + int32_t returnCode, int32_t /*latencyMs*/, + const std::string& hostname, + const ::std::vector<std::string>& ipAddresses, + int32_t ipAddressesCount, int32_t /*uid*/) { + // A bitwise-OR combination of all expected test cases. + // Currently, the maximum number of test case is 32 because a 32-bits bitwise-OR combination + // is used for checking and recording verified test cases. + static const uint32_t kExpectedTests = (1 << mResults.size()) - 1; + + // A bitwise-OR combination for recording verified test cases. + static uint32_t verifiedTests = 0; + + for (size_t i = 0; i < mResults.size(); ++i) { + // Generate bitwise flag to trace which testcase is running. + const uint32_t currentTestFlag = 1 << i; + + // Ignore verified testcase. + if (verifiedTests & currentTestFlag) continue; + + // Verify expected event content. + auto& result = mResults[i]; + if (netId != result.netId) continue; + if (eventType != result.eventType) continue; + if (hostname != result.hostname) continue; + if (returnCode != result.returnCode) continue; + if (ipAddressesCount != result.ipAddressesCount) continue; + if (result.returnCode == 0 /*success*/) { + // Only verify first address. + // TODO: Check all addresses. + if (ipAddresses.empty() || ipAddresses.front() != result.ipAddress) continue; + } + + // Record current testcase as verified. + verifiedTests |= currentTestFlag; + break; + } + + // All testcases of onDnsEvent are verified. Notify who was waiting for test results. + if (verifiedTests == kExpectedTests) { + setVerified(EventFlag::onDnsEvent); + notify(); + } + + return android::binder::Status::ok(); +}; + +} // namespace metrics +} // namespace net +} // namespace android
\ No newline at end of file diff --git a/tests/dns_metrics_listener/test_metrics.h b/tests/dns_metrics_listener/test_metrics.h new file mode 100644 index 00000000..d098acae --- /dev/null +++ b/tests/dns_metrics_listener/test_metrics.h @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed 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. + */ + +#pragma once + +#include "base_metrics_listener.h" + +enum EventFlag : uint32_t { + onDnsEvent = 1 << 0, + onPrivateDnsValidationEvent = 1 << 1, + onConnectEvent = 1 << 2, + onWakeupEvent = 1 << 3, + onTcpSocketStatsEvent = 1 << 4, + onNat64PrefixEvent = 1 << 5, +}; + +namespace android { +namespace net { +namespace metrics { + +// Base class for metrics event unit test. Used for notifications about DNS event changes. Should +// be extended by unit tests wanting notifications. +class BaseTestMetricsEvent : public BaseMetricsListener { + public: + // Returns TRUE if the verification was successful. Otherwise, returns FALSE. + virtual bool isVerified() = 0; + + std::condition_variable& getCv() { return mCv; } + std::mutex& getCvMutex() { return mCvMutex; } + + private: + // The verified event(s) as a bitwise-OR combination of enum EventFlag flags. + uint32_t mVerified{}; + + // This lock prevents racing condition between signaling thread(s) and waiting thread(s). + std::mutex mCvMutex; + + // Condition variable signaled when notify() is called. + std::condition_variable mCv; + + protected: + // Notify who is waiting for test results. See also mCvMutex and mCv. + void notify(); + + // Get current verified event(s). + uint32_t getVerified() const { return mVerified; } + + // Set the specific event as verified if its verification was successful. + void setVerified(EventFlag event); +}; + +// Derived class for testing onDnsEvent(). +class TestOnDnsEvent : public BaseTestMetricsEvent { + public: + // Both latencyMs and uid are not verified. No special reason. + // TODO: Considering to verify uid. + struct TestResult { + int netId; + int eventType; + int returnCode; + int ipAddressesCount; + std::string hostname; + std::string ipAddress; // Check first address only. + }; + + TestOnDnsEvent() = delete; + TestOnDnsEvent(const std::vector<TestResult>& results) : mResults(results){}; + + // BaseTestMetricsEvent::isVerified() override. + bool isVerified() override { return (getVerified() & EventFlag::onDnsEvent) != 0; } + + // Override for testing verification. + android::binder::Status onDnsEvent(int32_t netId, int32_t eventType, int32_t returnCode, + int32_t /*latencyMs*/, const std::string& hostname, + const std::vector<std::string>& ipAddresses, + int32_t ipAddressesCount, int32_t /*uid*/) override; + + private: + const std::vector<TestResult>& mResults; // Expected results for test verification. +}; + +} // namespace metrics +} // namespace net +} // namespace android
\ No newline at end of file |