OSDN Git Service

Move integration tests for IApInterface to their own file
authorChristopher Wiley <wiley@google.com>
Thu, 21 Jul 2016 16:06:33 +0000 (09:06 -0700)
committerChristopher Wiley <wiley@google.com>
Fri, 29 Jul 2016 18:39:20 +0000 (11:39 -0700)
Move existing tests related to IApInterface to a new file.
Add additional test coverage to exercise IApInterface.

Bug: 30040724
Test: These tests pass.  Unfortunately, hostapd start/stop
      is still not as reliable as we'd like.

Change-Id: I08956798c917cf6abf09ab44c48b3588c61c8de5

Android.mk
tests/integration/ap_interface_test.cpp [new file with mode: 0644]
tests/integration/life_cycle_test.cpp
tests/integration/process_utils.cpp
tests/integration/process_utils.h

index 1755c72..c287df6 100644 (file)
@@ -153,6 +153,7 @@ LOCAL_MODULE := wificond_integration_test
 LOCAL_CPPFLAGS := $(wificond_cpp_flags)
 LOCAL_C_INCLUDES := $(wificond_includes)
 LOCAL_SRC_FILES := \
+    tests/integration/ap_interface_test.cpp \
     tests/integration/life_cycle_test.cpp \
     tests/main.cpp \
     tests/shell_unittest.cpp
diff --git a/tests/integration/ap_interface_test.cpp b/tests/integration/ap_interface_test.cpp
new file mode 100644 (file)
index 0000000..6a19027
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2016, 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 <vector>
+
+#include <gtest/gtest.h>
+#include <utils/StrongPointer.h>
+
+#include "android/net/wifi/IApInterface.h"
+#include "android/net/wifi/IWificond.h"
+#include "wificond/tests/integration/process_utils.h"
+
+using android::net::wifi::IApInterface;
+using android::net::wifi::IWificond;
+using android::wificond::tests::integration::HostapdIsDead;
+using android::wificond::tests::integration::HostapdIsRunning;
+using android::wificond::tests::integration::ScopedDevModeWificond;
+using android::wificond::tests::integration::WaitForTrue;
+using std::vector;
+
+namespace android {
+namespace wificond {
+namespace {
+
+constexpr int kHostapdStartupTimeoutSeconds = 3;
+constexpr int kHostapdDeathTimeoutSeconds = 3;
+
+const char kValidSsid[] = "foobar";
+const char kInvalidSsid[] = "0123456789"
+                            "0123456789"
+                            "0123456789"
+                            "012";  // 33 bytes is too long
+const char kValidPassphrase[] = "super secret";
+
+}  // namespace
+
+TEST(ApInterfaceTest, CanCreateApInterfaces) {
+  ScopedDevModeWificond dev_mode;
+  sp<IWificond> service = dev_mode.EnterDevModeOrDie();
+
+  // We should be able to create an AP interface.
+  sp<IApInterface> ap_interface;
+  EXPECT_TRUE(service->createApInterface(&ap_interface).isOk());
+  EXPECT_NE(nullptr, ap_interface.get());
+
+  // We should not be able to create two AP interfaces.
+  sp<IApInterface> ap_interface2;
+  EXPECT_TRUE(service->createApInterface(&ap_interface2).isOk());
+  EXPECT_EQ(nullptr, ap_interface2.get());
+
+  // We can tear down the created interface.
+  EXPECT_TRUE(service->tearDownInterfaces().isOk());
+}
+
+// TODO: b/30311493 this test fails because hostapd fails to set the driver
+//       channel every other time.
+TEST(ApInterfaceTest, CanStartStopHostapd) {
+  ScopedDevModeWificond dev_mode;
+  sp<IWificond> service = dev_mode.EnterDevModeOrDie();
+  sp<IApInterface> ap_interface;
+  EXPECT_TRUE(service->createApInterface(&ap_interface).isOk());
+  ASSERT_NE(nullptr, ap_interface.get());
+
+  bool wrote_config = false;
+  EXPECT_TRUE(ap_interface->writeHostapdConfig(
+      vector<uint8_t>(kValidSsid, kValidSsid + sizeof(kValidSsid) - 1),
+      false,
+      6,
+      IApInterface::ENCRYPTION_TYPE_WPA2,
+      vector<uint8_t>(kValidPassphrase,
+                      kValidPassphrase + sizeof(kValidPassphrase) - 1),
+      &wrote_config).isOk());
+  ASSERT_TRUE(wrote_config);
+
+  for (int iteration = 0; iteration < 4; iteration++) {
+    bool hostapd_started = false;
+    EXPECT_TRUE(ap_interface->startHostapd(&hostapd_started).isOk());
+    EXPECT_TRUE(hostapd_started);
+
+    EXPECT_TRUE(WaitForTrue(HostapdIsRunning, kHostapdStartupTimeoutSeconds))
+        << "Failed on iteration " << iteration;
+
+    // There are two reasons to do this:
+    //   1) We look for hostapd so quickly that we miss when it dies on startup
+    //   2) If we don't give hostapd enough time to get fully up, killing it
+    //      can leave the driver in a poor state.
+    // The latter points to an obvious race, where we cannot fully clean up the
+    // driver on quick transitions.
+    sleep(1);
+    EXPECT_TRUE(HostapdIsRunning()) << "Failed on iteration " << iteration;
+
+    bool hostapd_stopped = false;
+    EXPECT_TRUE(ap_interface->stopHostapd(&hostapd_stopped).isOk());
+    EXPECT_TRUE(hostapd_stopped);
+
+    EXPECT_TRUE(WaitForTrue(HostapdIsDead, kHostapdDeathTimeoutSeconds))
+        << "Failed on iteration " << iteration;
+  }
+}
+
+TEST(ApInterfaceTest, CanWriteHostapdConfig) {
+  ScopedDevModeWificond dev_mode;
+  sp<IWificond> service = dev_mode.EnterDevModeOrDie();
+  sp<IApInterface> ap_interface;
+  EXPECT_TRUE(service->createApInterface(&ap_interface).isOk());
+  ASSERT_NE(nullptr, ap_interface.get());
+
+  bool success = false;
+  // Should be able to write out a valid configuration
+  EXPECT_TRUE(ap_interface->writeHostapdConfig(
+      vector<uint8_t>(kValidSsid, kValidSsid + sizeof(kValidSsid) - 1),
+      false,
+      2,
+      IApInterface::ENCRYPTION_TYPE_WPA2,
+      vector<uint8_t>(kValidPassphrase,
+                      kValidPassphrase + sizeof(kValidPassphrase) - 1),
+      &success).isOk());
+  EXPECT_TRUE(success) << "Expected to write out a valid config.";
+
+  // SSIDs have to be 32 bytes or less
+  EXPECT_TRUE(ap_interface->writeHostapdConfig(
+      vector<uint8_t>(kInvalidSsid, kInvalidSsid + sizeof(kInvalidSsid) - 1),
+      false,
+      2,
+      IApInterface::ENCRYPTION_TYPE_WPA2,
+      vector<uint8_t>(kValidPassphrase,
+                      kValidPassphrase + sizeof(kValidPassphrase) - 1),
+      &success).isOk());
+  EXPECT_FALSE(success) << "Did not expect to write out an invalid config.";
+}
+
+}  // namespace wificond
+}  // namespace android
+
index 0a2ae5f..a3903cb 100644 (file)
 
 #include <gtest/gtest.h>
 
-#include <utils/StrongPointer.h>
-
-#include "android/net/wifi/IApInterface.h"
-#include "android/net/wifi/IWificond.h"
 #include "wificond/ipc_constants.h"
 #include "wificond/tests/shell_utils.h"
 #include "wificond/tests/integration/process_utils.h"
 
-using android::net::wifi::IApInterface;
-using android::net::wifi::IWificond;
 using android::wificond::ipc_constants::kDevModeServiceName;
 using android::wificond::ipc_constants::kServiceName;
 using android::wificond::tests::integration::RunShellCommand;
@@ -60,23 +54,5 @@ TEST(LifeCycleTest, ProcessStartsUp) {
                           ScopedDevModeWificond::kWificondStartTimeoutSeconds));
 }
 
-TEST(LifeCycleTest, CanCreateApInterfaces) {
-  ScopedDevModeWificond dev_mode;
-  sp<IWificond> service = dev_mode.EnterDevModeOrDie();
-
-  // We should be able to create an AP interface.
-  sp<IApInterface> ap_interface;
-  EXPECT_TRUE(service->createApInterface(&ap_interface).isOk());
-  EXPECT_NE(nullptr, ap_interface.get());
-
-  // We should not be able to create two AP interfaces.
-  sp<IApInterface> ap_interface2;
-  EXPECT_TRUE(service->createApInterface(&ap_interface2).isOk());
-  EXPECT_EQ(nullptr, ap_interface2.get());
-
-  // We can tear down the created interface.
-  EXPECT_TRUE(service->tearDownInterfaces().isOk());
-}
-
 }  // namespace wificond
 }  // namespace android
index 5b43434..2979fd2 100644 (file)
@@ -19,6 +19,7 @@
 #include <unistd.h>
 
 #include <android-base/logging.h>
+#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <binder/IBinder.h>
 #include <binder/IServiceManager.h>
@@ -30,6 +31,7 @@
 #include "wificond/tests/shell_utils.h"
 
 using android::String16;
+using android::base::StringPrintf;
 using android::base::Trim;
 using android::net::wifi::IWificond;
 using android::sp;
@@ -40,6 +42,19 @@ namespace android {
 namespace wificond {
 namespace tests {
 namespace integration {
+namespace {
+
+bool IsProcessRunning(const char* process_name) {
+  std::string output;
+  RunShellCommand(StringPrintf("pgrep -c ^%s$", process_name), &output);
+  output = Trim(output);
+  if (output == "0") {
+    return false;
+  }
+  return true;
+}
+
+}
 
 const uint32_t ScopedDevModeWificond::kWificondDeathTimeoutSeconds = 10;
 const uint32_t ScopedDevModeWificond::kWificondStartTimeoutSeconds = 10;
@@ -96,13 +111,7 @@ bool IsBinderServiceRegistered(const char* service_name) {
 }
 
 bool WificondIsRunning() {
-  std::string output;
-  RunShellCommand("pgrep -c ^wificond$", &output);
-  output = Trim(output);
-  if (output == "0") {
-    return false;
-  }
-  return true;
+  return IsProcessRunning("wificond");
 }
 
 bool WificondIsDead() { return !WificondIsRunning(); }
@@ -111,6 +120,12 @@ bool WificondSetDevMode(bool is_on) {
   return property_set(kDevModePropertyKey, (is_on) ? "1" : "0") == 0;
 }
 
+bool HostapdIsRunning() {
+  return IsProcessRunning("hostapd");
+}
+
+bool HostapdIsDead() { return !HostapdIsRunning(); }
+
 }  // namespace integration
 }  // namespace tests
 }  // namespace android
index ca23965..838a370 100644 (file)
@@ -87,6 +87,12 @@ bool WificondIsDead();
 // developer mode.  See wificond's main() for what this entails.
 bool WificondSetDevMode(bool is_on);
 
+// Returns true iff the hostapd process is running on the system.
+bool HostapdIsRunning();
+
+// Convenient alias for !HostapdIsRunning
+bool HostapdIsDead();
+
 }  // namespace integration
 }  // namespace tests
 }  // namespace android