summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGirish Moturu <gmoturu@google.com>2018-05-30 18:32:26 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2018-05-30 18:32:26 +0000
commit3fad38709022ac57669af42d25a398ac86be7200 (patch)
tree18c21b677c991188f632d623df2559bb87169fd7
parent0243ef1a25801f1a727c99bac55cce85cb4ce9e3 (diff)
parent7da460b214b4e4cd982b1fb944f5612c4a5eb18a (diff)
downloadplatform_tools_test_connectivity-3fad38709022ac57669af42d25a398ac86be7200.tar.gz
platform_tools_test_connectivity-3fad38709022ac57669af42d25a398ac86be7200.tar.bz2
platform_tools_test_connectivity-3fad38709022ac57669af42d25a398ac86be7200.zip
Merge "[socket_test_utils] Add test utils for socket based methods" into pi-dev
-rw-r--r--acts/framework/acts/controllers/__init__.py2
-rw-r--r--acts/framework/acts/controllers/arduino_wifi_dongle.py392
-rw-r--r--acts/framework/acts/keys.py3
-rw-r--r--acts/framework/acts/test_utils/net/arduino_test_utils.py73
-rw-r--r--acts/framework/acts/test_utils/net/connectivity_const.py18
-rw-r--r--acts/framework/acts/test_utils/net/socket_test_utils.py285
-rw-r--r--acts/tests/google/net/arduino/connect_wifi/connect_wifi.ino93
-rw-r--r--acts/tests/google/net/arduino/disconnect_wifi/disconnect_wifi.ino64
-rw-r--r--acts/tests/google/wifi/WifiTetheringTest.py89
9 files changed, 999 insertions, 20 deletions
diff --git a/acts/framework/acts/controllers/__init__.py b/acts/framework/acts/controllers/__init__.py
index 2cc6f43fa1..41e48dfc31 100644
--- a/acts/framework/acts/controllers/__init__.py
+++ b/acts/framework/acts/controllers/__init__.py
@@ -25,5 +25,5 @@ def destroy(objs):
"""This is a list of all the top level controller modules"""
__all__ = [
"android_device", "attenuator", "monsoon", "access_point", "iperf_server",
- "packet_sender"
+ "packet_sender", "arduino_wifi_dongle"
]
diff --git a/acts/framework/acts/controllers/arduino_wifi_dongle.py b/acts/framework/acts/controllers/arduino_wifi_dongle.py
new file mode 100644
index 0000000000..7978f3034a
--- /dev/null
+++ b/acts/framework/acts/controllers/arduino_wifi_dongle.py
@@ -0,0 +1,392 @@
+#!/usr/bin/env python3
+#
+# Copyright 2018 - 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.
+
+import logging
+import os
+import re
+import serial
+import subprocess
+import threading
+import time
+
+from acts import logger
+from acts import signals
+from acts import tracelogger
+from acts import utils
+from acts.test_utils.wifi import wifi_test_utils as wutils
+
+from datetime import datetime
+
+ACTS_CONTROLLER_CONFIG_NAME = "ArduinoWifiDongle"
+ACTS_CONTROLLER_REFERENCE_NAME = "arduino_wifi_dongles"
+
+WIFI_DONGLE_EMPTY_CONFIG_MSG = "Configuration is empty, abort!"
+WIFI_DONGLE_NOT_LIST_CONFIG_MSG = "Configuration should be a list, abort!"
+
+DEV = "/dev/"
+IP = "IP: "
+STATUS = "STATUS: "
+SSID = "SSID: "
+RSSI = "RSSI: "
+PING = "PING: "
+SCAN_BEGIN = "Scan Begin"
+SCAN_END = "Scan End"
+READ_TIMEOUT = 10
+BAUD_RATE = 9600
+TMP_DIR = "tmp/"
+SSID_KEY = wutils.WifiEnums.SSID_KEY
+PWD_KEY = wutils.WifiEnums.PWD_KEY
+
+
+class ArduinoWifiDongleError(signals.ControllerError):
+ pass
+
+class DoesNotExistError(ArduinoWifiDongleError):
+ """Raised when something that does not exist is referenced."""
+
+def create(configs):
+ """Creates ArduinoWifiDongle objects.
+
+ Args:
+ configs: A list of dicts or a list of serial numbers, each representing
+ a configuration of a arduino wifi dongle.
+
+ Returns:
+ A list of Wifi dongle objects.
+ """
+ wcs = []
+ if not configs:
+ raise ArduinoWifiDongleError(WIFI_DONGLE_EMPTY_CONFIG_MSG)
+ elif not isinstance(configs, list):
+ raise ArduinoWifiDongleError(WIFI_DONGLE_NOT_LIST_CONFIG_MSG)
+ elif isinstance(configs[0], str):
+ # Configs is a list of serials.
+ wcs = get_instances(configs)
+ else:
+ # Configs is a list of dicts.
+ wcs = get_instances_with_configs(configs)
+
+ return wcs
+
+def destroy(wcs):
+ for wc in wcs:
+ wc.clean_up()
+
+def get_instances(configs):
+ wcs = []
+ for s in configs:
+ wcs.append(ArduinoWifiDongle(s))
+ return wcs
+
+def get_instances_with_configs(configs):
+ wcs = []
+ for c in configs:
+ try:
+ s = c.pop("serial")
+ except KeyError:
+ raise ArduinoWifiDongleError(
+ "'serial' is missing for ArduinoWifiDongle config %s." % c)
+ wcs.append(ArduinoWifiDongle(s))
+ return wcs
+
+class ArduinoWifiDongle(object):
+ """Class representing an arduino wifi dongle.
+
+ Each object of this class represents one wifi dongle in ACTS.
+
+ Attribtues:
+ serial: Short serial number of the wifi dongle in string.
+ port: The terminal port the dongle is connected to in string.
+ log: A logger adapted from root logger with added token specific to an
+ ArduinoWifiDongle instance.
+ log_file_fd: File handle of the log file.
+ set_logging: Logging for the dongle is enabled when this param is set
+ lock: Lock to acquire and release set_logging variable
+ ssid: SSID of the wifi network the dongle is connected to.
+ ip_addr: IP address on the wifi interface.
+ scan_results: Most recent scan results.
+ ping: Ping status in bool - ping to www.google.com
+ """
+ def __init__(self, serial=''):
+ """Initializes the ArduinoWifiDongle object."""
+ self.serial = serial
+ self.port = self._get_serial_port()
+ self.log = logger.create_tagged_trace_logger(
+ "ArduinoWifiDongle|%s" % self.serial)
+ log_path_base = getattr(logging, "log_path", "/tmp/logs")
+ self.log_file_path = os.path.join(
+ log_path_base, "ArduinoWifiDongle_%s_serial_log.txt" % self.serial)
+ self.log_file_fd = open(self.log_file_path, "a")
+
+ self.set_logging = True
+ self.lock = threading.Lock()
+ self.start_controller_log()
+
+ self.ssid = None
+ self.ip_addr = None
+ self.status = 0
+ self.scan_results = []
+ self.scanning = False
+ self.ping = False
+
+ try:
+ os.stat(TMP_DIR)
+ except:
+ os.mkdir(TMP_DIR)
+
+ def clean_up(self):
+ """Cleans up the ArduinoifiDongle object and releases any resources it
+ claimed.
+ """
+ self.stop_controller_log()
+ self.log_file_fd.close()
+
+ def _get_serial_port(self):
+ """Get the serial port for a given ArduinoWifiDongle serial number.
+
+ Returns:
+ Serial port in string if the dongle is attached.
+ """
+ if not self.serial:
+ raise ArduinoWifiDongleError(
+ "Wifi dongle's serial should not be empty")
+ cmd = "ls %s" % DEV
+ serial_ports = utils.exe_cmd(cmd).decode("utf-8", "ignore").split("\n")
+ for port in serial_ports:
+ if "USB" not in port:
+ continue
+ tty_port = "%s%s" % (DEV, port)
+ cmd = "udevadm info %s" % tty_port
+ udev_output = utils.exe_cmd(cmd).decode("utf-8", "ignore")
+ result = re.search("ID_SERIAL_SHORT=(.*)\n", udev_output)
+ if self.serial == result.group(1):
+ logging.info("Found wifi dongle %s at serial port %s" %
+ (self.serial, tty_port))
+ return tty_port
+ raise ArduinoWifiDongleError("Wifi dongle %s is specified in config"
+ " but is not attached." % self.serial)
+
+ def write(self, arduino, file_path, network=None):
+ """Write an ino file to the arduino wifi dongle.
+
+ Args:
+ arduino: path of the arduino executable.
+ file_path: path of the ino file to flash onto the dongle.
+ network: wifi network to connect to.
+
+ Returns:
+ True: if the write is sucessful.
+ False: if not.
+ """
+ return_result = True
+ self.stop_controller_log("Flashing %s\n" % file_path)
+ cmd = arduino + file_path + " --upload --port " + self.port
+ if network:
+ cmd = self._update_ino_wifi_network(arduino, file_path, network)
+ self.log.info("Command is %s" % cmd)
+ proc = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+ out, err = proc.communicate()
+ return_code = proc.returncode
+ if return_code != 0:
+ self.log.error("Failed to write file %s" % return_code)
+ return_result = False
+ self.start_controller_log("Flashing complete\n")
+ return return_result
+
+ def _update_ino_wifi_network(self, arduino, file_path, network):
+ """Update wifi network in the ino file.
+
+ Args:
+ arduino: path of the arduino executable.
+ file_path: path of the ino file to flash onto the dongle
+ network: wifi network to update the ino file with
+
+ Returns:
+ cmd: arduino command to run to flash the ino file
+ """
+ tmp_file = "%s%s" % (TMP_DIR, file_path.split('/')[-1])
+ utils.exe_cmd("cp %s %s" % (file_path, tmp_file))
+ ssid = network[SSID_KEY]
+ pwd = network[PWD_KEY]
+ sed_cmd = "sed -i 's/\"wifi_tethering_test\"/\"%s\"/' %s" % (ssid, tmp_file)
+ utils.exe_cmd(sed_cmd)
+ sed_cmd = "sed -i 's/\"password\"/\"%s\"/' %s" % (pwd, tmp_file)
+ utils.exe_cmd(sed_cmd)
+ cmd = "%s %s --upload --port %s" %(arduino, tmp_file, self.port)
+ return cmd
+
+ def start_controller_log(self, msg=None):
+ """Reads the serial port and writes the data to ACTS log file.
+
+ This method depends on the logging enabled in the .ino files. The logs
+ are read from the serial port and are written to the ACTS log after
+ adding a timestamp to the data.
+
+ Args:
+ msg: Optional param to write to the log file.
+ """
+ if msg:
+ curr_time = str(datetime.now())
+ self.log_file_fd.write(curr_time + " INFO: " + msg)
+ t = threading.Thread(target=self._start_log)
+ t.daemon = True
+ t.start()
+
+ def stop_controller_log(self, msg=None):
+ """Stop the controller log.
+
+ Args:
+ msg: Optional param to write to the log file.
+ """
+ with self.lock:
+ self.set_logging = False
+ if msg:
+ curr_time = str(datetime.now())
+ self.log_file_fd.write(curr_time + " INFO: " + msg)
+
+ def _start_log(self):
+ """Target method called by start_controller_log().
+
+ This method is called as a daemon thread, which continously reads the
+ serial port. Stops when set_logging is set to False or when the test
+ ends.
+ """
+ self.set_logging = True
+ ser = serial.Serial(self.port, BAUD_RATE)
+ while True:
+ curr_time = str(datetime.now())
+ data = ser.readline().decode("utf-8", "ignore")
+ self._set_vars(data)
+ with self.lock:
+ if not self.set_logging:
+ break
+ self.log_file_fd.write(curr_time + " " + data)
+
+ def _set_vars(self, data):
+ """Sets the variables by reading from the serial port.
+
+ Wifi dongle data such as wifi status, ip address, scan results
+ are read from the serial port and saved inside the class.
+
+ Args:
+ data: New line from the serial port.
+ """
+ # 'data' represents each line retrieved from the device's serial port.
+ # since we depend on the serial port logs to get the attributes of the
+ # dongle, every line has the format of {ino_file: method: param: value}.
+ # We look for the attribute in the log and retrieve its value.
+ # Ex: data = "connect_wifi: loop(): STATUS: 3" then val = "3"
+ # Similarly, we check when the scan has begun and ended and get all the
+ # scan results in between.
+ if data.count(":") != 3:
+ return
+ val = data.split(":")[-1].lstrip().rstrip()
+ if SCAN_BEGIN in data:
+ self.scan_results = []
+ self.scanning = True
+ elif SCAN_END in data:
+ self.scanning = False
+ elif self.scanning:
+ self.scan_results.append(data)
+ elif IP in data:
+ self.ip_addr = None if val == "0.0.0.0" else val
+ elif SSID in data:
+ self.ssid = val
+ elif STATUS in data:
+ self.status = int(val)
+ elif PING in data:
+ self.ping = False if int(val) == 0 else True
+
+ def ip_address(self, exp_result=True, timeout=READ_TIMEOUT):
+ """Get the ip address of the wifi dongle.
+
+ Args:
+ exp_result: True if IP address is expected (wifi connected).
+ timeout: Optional param that specifies the wait time for the IP
+ address to come up on the dongle.
+
+ Returns:
+ IP: addr in string, if wifi connected.
+ None if not connected.
+ """
+ curr_time = time.time()
+ while time.time() < curr_time + timeout:
+ if (exp_result and self.ip_addr) or \
+ (not exp_result and not self.ip_addr):
+ break
+ time.sleep(1)
+ return self.ip_addr
+
+ def wifi_status(self, exp_result=True, timeout=READ_TIMEOUT):
+ """Get wifi status on the dongle.
+
+ Returns:
+ True: if wifi is connected.
+ False: if not connected.
+ """
+ curr_time = time.time()
+ while time.time() < curr_time + timeout:
+ if (exp_result and self.status == 3) or \
+ (not exp_result and not self.status):
+ break
+ time.sleep(1)
+ return self.status == 3
+
+ def wifi_scan(self, exp_result=True, timeout=READ_TIMEOUT):
+ """Get the wifi scan results.
+
+ Args:
+ exp_result: True if scan results are expected.
+ timeout: Optional param that specifies the wait time for the scan
+ results to come up on the dongle.
+
+ Returns:
+ list of dictionaries each with SSID and RSSI of the network
+ found in the scan.
+ """
+ scan_networks = []
+ d = {}
+ curr_time = time.time()
+ while time.time() < curr_time + timeout:
+ if (exp_result and self.scan_results) or \
+ (not exp_result and not self.scan_results):
+ break
+ time.sleep(1)
+ for i in range(len(self.scan_results)):
+ if SSID in self.scan_results[i]:
+ d = {}
+ d[SSID] = self.scan_results[i].split(":")[-1].rstrip()
+ elif RSSI in self.scan_results[i]:
+ d[RSSI] = self.scan_results[i].split(":")[-1].rstrip()
+ scan_networks.append(d)
+
+ return scan_networks
+
+ def ping_status(self, exp_result=True, timeout=READ_TIMEOUT):
+ """ Get ping status on the dongle.
+
+ Returns:
+ True: if ping is successful
+ False: if not successful
+ """
+ curr_time = time.time()
+ while time.time() < curr_time + timeout:
+ if (exp_result and self.ping) or \
+ (not exp_result and not self.ping):
+ break
+ time.sleep(1)
+ return self.ping
diff --git a/acts/framework/acts/keys.py b/acts/framework/acts/keys.py
index 526ef7146d..a0aa52af46 100644
--- a/acts/framework/acts/keys.py
+++ b/acts/framework/acts/keys.py
@@ -47,6 +47,7 @@ class Config(enum.Enum):
key_packet_sender = "PacketSender"
key_monsoon = "Monsoon"
key_sniffer = "Sniffer"
+ key_arduino_wifi_dongle = "ArduinoWifiDongle"
# Internal keys, used internally, not exposed to user's config files.
ikey_user_param = "user_params"
ikey_testbed_name = "testbed_name"
@@ -64,6 +65,7 @@ class Config(enum.Enum):
m_key_iperf_server = "iperf_server"
m_key_packet_sender = "packet_sender"
m_key_sniffer = "sniffer"
+ m_key_arduino_wifi_dongle = "arduino_wifi_dongle"
# A list of keys whose values in configs should not be passed to test
# classes without unpacking first.
@@ -81,6 +83,7 @@ class Config(enum.Enum):
key_monsoon,
key_sniffer,
key_chameleon_device,
+ key_arduino_wifi_dongle,
]
# Keys that are file or folder paths.
diff --git a/acts/framework/acts/test_utils/net/arduino_test_utils.py b/acts/framework/acts/test_utils/net/arduino_test_utils.py
new file mode 100644
index 0000000000..af0b3da15f
--- /dev/null
+++ b/acts/framework/acts/test_utils/net/arduino_test_utils.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3.4
+#
+# Copyright 2018 Google, Inc.
+#
+# 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.
+
+import logging
+import time
+import pprint
+
+from enum import IntEnum
+from queue import Empty
+
+from acts import asserts
+from acts import signals
+from acts import utils
+from acts.controllers import attenuator
+from acts.test_utils.wifi import wifi_constants
+from acts.test_utils.tel import tel_defines
+from acts.test_utils.wifi import wifi_test_utils as wutils
+
+ARDUINO = "/root/arduino/arduino-1.8.5/arduino "
+CONNECT_WIFI = "/arduino/connect_wifi/connect_wifi.ino"
+DISCONNECT_WIFI = "/arduino/disconnect_wifi/disconnect_wifi.ino"
+SSID = wutils.WifiEnums.SSID_KEY
+PWD = wutils.WifiEnums.PWD_KEY
+
+def connect_wifi(wd, network=None):
+ """Connect wifi on arduino wifi dongle
+
+ Args:
+ wd - wifi dongle object
+ network - wifi network to connect to
+ """
+ wd.log.info("Flashing connect_wifi.ino onto dongle")
+ cmd = "locate %s" % CONNECT_WIFI
+ file_path = utils.exe_cmd(cmd).decode("utf-8", "ignore").rstrip()
+ write_status = wd.write(ARDUINO, file_path, network)
+ asserts.assert_true(write_status, "Failed to flash connect wifi")
+ wd.log.info("Flashing complete")
+ wifi_status = wd.wifi_status()
+ asserts.assert_true(wifi_status, "Failed to connect to %s" % network)
+ ping_status = wd.ping_status()
+ asserts.assert_true(ping_status, "Failed to connect to internet")
+
+def disconnect_wifi(wd):
+ """Disconnect wifi on arduino wifi dongle
+
+ Args:
+ wd - wifi dongle object
+
+ Returns:
+ True - if wifi is disconnected
+ False - if not
+ """
+ wd.log.info("Flashing disconnect_wifi.ino onto dongle")
+ cmd = "locate %s" % DISCONNECT_WIFI
+ file_path = utils.exe_cmd(cmd).decode("utf-8", "ignore").rstrip()
+ write_status = wd.write(ARDUINO, file_path)
+ asserts.assert_true(write_status, "Failed to flash disconnect wifi")
+ wd.log.info("Flashing complete")
+ wifi_status = wd.wifi_status(False)
+ asserts.assert_true(not wifi_status, "Failed to disconnect wifi")
diff --git a/acts/framework/acts/test_utils/net/connectivity_const.py b/acts/framework/acts/test_utils/net/connectivity_const.py
index 64bd8b024a..bea006090f 100644
--- a/acts/framework/acts/test_utils/net/connectivity_const.py
+++ b/acts/framework/acts/test_utils/net/connectivity_const.py
@@ -63,6 +63,24 @@ MULTIPATH_PREFERENCE_HANDOVER = 1 << 0
MULTIPATH_PREFERENCE_RELIABILITY = 1 << 1
MULTIPATH_PREFERENCE_PERFORMANCE = 1 << 2
+# IpSec constants
+SOCK_STREAM = 1
+SOCK_DGRAM = 2
+AF_INET = 2
+AF_INET6 = 10
+DIRECTION_IN = 0
+DIRECTION_OUT = 1
+MODE_TRANSPORT = 0
+MODE_TUNNEL = 1
+CRYPT_NULL = "ecb(cipher_null)"
+CRYPT_AES_CBC = "cbc(aes)"
+AUTH_HMAC_MD5 = "hmac(md5)"
+AUTH_HMAC_SHA1 = "hmac(sha1)"
+AUTH_HMAC_SHA256 = "hmac(sha256)"
+AUTH_HMAC_SHA384 = "hmac(sha384)"
+AUTH_HMAC_SHA512 = "hmac(sha512)"
+AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))"
+
# Constants for VpnProfile
class VpnProfile(object):
""" This class contains all the possible
diff --git a/acts/framework/acts/test_utils/net/socket_test_utils.py b/acts/framework/acts/test_utils/net/socket_test_utils.py
new file mode 100644
index 0000000000..a8a05fc206
--- /dev/null
+++ b/acts/framework/acts/test_utils/net/socket_test_utils.py
@@ -0,0 +1,285 @@
+#
+# Copyright 2018 - 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.
+
+import queue
+import re
+import threading
+import time
+
+from acts.test_utils.net import connectivity_const as cconst
+from acts import asserts
+
+MSG = "Test message "
+PKTS = 5
+
+""" Methods for android.system.Os based sockets """
+def open_android_socket(ad, domain, sock_type, ip, port):
+ """ Open TCP or UDP using android.system.Os class
+
+ Args:
+ 1. ad - android device object
+ 2. domain - IPv4 or IPv6 type
+ 3. sock_type - UDP or TCP socket
+ 4. ip - IP addr on the device
+ 5. port - open socket on port
+
+ Returns:
+ File descriptor key
+ """
+ fd_key = ad.droid.openSocket(domain, sock_type, ip, port)
+ ad.log.info("File descriptor: %s" % fd_key)
+ asserts.assert_true(fd_key, "Failed to open socket")
+ return fd_key
+
+def close_android_socket(ad, fd_key):
+ """ Close socket
+
+ Args:
+ 1. ad - android device object
+ 2. fd_key - file descriptor key
+ """
+ status = ad.droid.closeSocket(fd_key)
+ asserts.assert_true(status, "Failed to close socket")
+
+def listen_accept_android_socket(client,
+ server,
+ client_fd,
+ server_fd,
+ server_ip,
+ server_port):
+ """ Listen, accept TCP sockets
+
+ Args:
+ 1. client : ad object for client device
+ 2. server : ad object for server device
+ 3. client_fd : client's socket handle
+ 4. server_fd : server's socket handle
+ 5. server_ip : send data to this IP
+ 6. server_port : send data to this port
+ """
+ server.droid.listenSocket(server_fd)
+ client.droid.connectSocket(client_fd, server_ip, server_port)
+ sock = server.droid.acceptSocket(server_fd)
+ asserts.assert_true(sock, "Failed to accept socket")
+ return sock
+
+def send_recv_data_android_sockets(client,
+ server,
+ client_fd,
+ server_fd,
+ server_ip,
+ server_port):
+ """ Send TCP or UDP data over android os sockets from client to server.
+ Verify that server received the data.
+
+ Args:
+ 1. client : ad object for client device
+ 2. server : ad object for server device
+ 3. client_fd : client's socket handle
+ 4. server_fd : server's socket handle
+ 5. server_ip : send data to this IP
+ 6. server_port : send data to this port
+ """
+ send_list = []
+ recv_list = []
+
+ for _ in range(1, PKTS+1):
+ msg = MSG + " %s" % _
+ send_list.append(msg)
+ client.log.info("Sending message: %s" % msg)
+ client.droid.sendDataOverSocket(server_ip, server_port, msg, client_fd)
+ recv_msg = server.droid.recvDataOverSocket(server_fd)
+ server.log.info("Received message: %s" % recv_msg)
+ recv_list.append(recv_msg)
+
+ recv_list = [x.rstrip('\x00') if x else x for x in recv_list]
+ asserts.assert_true(send_list and recv_list and send_list == recv_list,
+ "Send and recv information is incorrect")
+
+""" Methods for java.net.DatagramSocket based sockets """
+def open_datagram_socket(ad, ip, port):
+ """ Open datagram socket
+
+ Args:
+ 1. ad : android device object
+ 2. ip : IP addr on the device
+ 3. port : socket port
+
+ Returns:
+ Hash key of the datagram socket
+ """
+ socket_key = ad.droid.openDatagramSocket(ip, port)
+ ad.log.info("Datagram socket: %s" % socket_key)
+ asserts.assert_true(socket_key, "Failed to open datagram socket")
+ return socket_key
+
+def close_datagram_socket(ad, socket_key):
+ """ Close datagram socket
+
+ Args:
+ 1. socket_key : hash key of datagram socket
+ """
+ status = ad.droid.closeDatagramSocket(socket_key)
+ asserts.assert_true(status, "Failed to close datagram socket")
+
+def send_recv_data_datagram_sockets(client,
+ server,
+ client_sock,
+ server_sock,
+ server_ip,
+ server_port):
+ """ Send data over datagram socket from dut_a to dut_b.
+ Verify that dut_b received the data.
+
+ Args:
+ 1. client : ad object for client device
+ 2. server : ad object for server device
+ 3. client_sock : client's socket handle
+ 4. server_sock : server's socket handle
+ 5. server_ip : send data to this IP
+ 6. server_port : send data to this port
+ """
+ send_list = []
+ recv_list = []
+
+ for _ in range(1, PKTS+1):
+ msg = MSG + " %s" % _
+ send_list.append(msg)
+ client.log.info("Sending message: %s" % msg)
+ client.droid.sendDataOverDatagramSocket(client_sock,
+ msg,
+ server_ip,
+ server_port)
+ recv_msg = server.droid.recvDataOverDatagramSocket(server_sock)
+ server.log.info("Received message: %s" % recv_msg)
+ recv_list.append(recv_msg)
+
+ recv_list = [x.rstrip('\x00') if x else x for x in recv_list]
+ asserts.assert_true(send_list and recv_list and send_list == recv_list,
+ "Send and recv information is incorrect")
+
+""" Utils methods for java.net.Socket based sockets """
+def _accept_socket(server, server_ip, server_port, server_sock, q):
+ sock = server.droid.acceptTcpSocket(server_sock)
+ server.log.info("Server socket: %s" % sock)
+ q.put(sock)
+
+def _client_socket(client, server_ip, server_port, client_ip, client_port, q):
+ time.sleep(0.5)
+ sock = client.droid.openTcpSocket(server_ip,
+ server_port,
+ client_ip,
+ client_port)
+ client.log.info("Client socket: %s" % sock)
+ q.put(sock)
+
+def open_connect_socket(client,
+ server,
+ client_ip,
+ server_ip,
+ client_port,
+ server_port,
+ server_sock):
+ """ Open tcp socket and connect to server
+
+ Args:
+ 1. client : ad object for client device
+ 2. server : ad object for server device
+ 3. client_ip : client's socket handle
+ 4. server_ip : send data to this IP
+ 5. client_port : port on client socket
+ 6. server_port : port on server socket
+ 7. server_sock : server socket
+
+ Returns:
+ client and server socket from successful connect
+ """
+ sq = queue.Queue()
+ cq = queue.Queue()
+ s = threading.Thread(target = _accept_socket,
+ args = (server, server_ip, server_port, server_sock,
+ sq))
+ c = threading.Thread(target = _client_socket,
+ args = (client, server_ip, server_port, client_ip,
+ client_port, cq))
+ s.start()
+ c.start()
+ c.join()
+ s.join()
+
+ client_sock = cq.get()
+ server_sock = sq.get()
+ asserts.assert_true(client_sock and server_sock, "Failed to open sockets")
+
+ return client_sock, server_sock
+
+def open_server_socket(server, server_ip, server_port):
+ """ Open tcp server socket
+
+ Args:
+ 1. server : ad object for server device
+ 2. server_ip : send data to this IP
+ 3. server_port : send data to this port
+ """
+ sock = server.droid.openTcpServerSocket(server_ip, server_port)
+ server.log.info("Server Socket: %s" % sock)
+ asserts.assert_true(sock, "Failed to open server socket")
+ return sock
+
+def close_socket(ad, socket):
+ """ Close socket
+
+ Args:
+ 1. ad - android device object
+ 2. socket - socket key
+ """
+ status = ad.droid.closeTcpSocket(socket)
+ asserts.assert_true(status, "Failed to socket")
+
+def close_server_socket(ad, socket):
+ """ Close server socket
+
+ Args:
+ 1. ad - android device object
+ 2. socket - server socket key
+ """
+ status = ad.droid.closeTcpServerSocket(socket)
+ asserts.assert_true(status, "Failed to socket")
+
+def send_recv_data_sockets(client, server, client_sock, server_sock):
+ """ Send data over TCP socket from client to server.
+ Verify that server received the data
+
+ Args:
+ 1. client : ad object for client device
+ 2. server : ad object for server device
+ 3. client_sock : client's socket handle
+ 4. server_sock : server's socket handle
+ """
+ send_list = []
+ recv_list = []
+
+ for _ in range(1, PKTS+1):
+ msg = MSG + " %s" % _
+ send_list.append(msg)
+ client.log.info("Sending message: %s" % msg)
+ client.droid.sendDataOverTcpSocket(client_sock, msg)
+ recv_msg = server.droid.recvDataOverTcpSocket(server_sock)
+ server.log.info("Received message: %s" % recv_msg)
+ recv_list.append(recv_msg)
+
+ recv_list = [x.rstrip('\x00') if x else x for x in recv_list]
+ asserts.assert_true(send_list and recv_list and send_list == recv_list,
+ "Send and recv information is incorrect")
diff --git a/acts/tests/google/net/arduino/connect_wifi/connect_wifi.ino b/acts/tests/google/net/arduino/connect_wifi/connect_wifi.ino
new file mode 100644
index 0000000000..14bd1961b2
--- /dev/null
+++ b/acts/tests/google/net/arduino/connect_wifi/connect_wifi.ino
@@ -0,0 +1,93 @@
+#include <ESP8266WiFi.h>
+#include <ESP8266Ping.h>
+#include <WiFiUdp.h>
+
+const char* ssid = "wifi_tethering_test";
+const char* password = "password";
+
+unsigned int localPort = 8888;
+char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
+WiFiUDP Udp;
+
+
+void setup() {
+ delay(1000); // wait for a second to read from serial port after flashing
+ Serial.begin(9600);
+ Serial.println("connect: setup(): CALL: Setup Begin");
+ Serial.println("connect: setup(): INFO: Setting baud rate to 9600");
+
+ wifiStatus();
+ connectWifi();
+
+ Udp.begin(localPort);
+ Serial.println("connect: setup(): CALL: Setup End");
+}
+
+void loop() {
+ wifiStatus();
+ udpPackets();
+}
+
+void connectWifi() {
+ Serial.println("connect: connectWifi(): CALL: Connect Begin");
+ WiFi.begin(ssid, password);
+ while (WiFi.status() != WL_CONNECTED) {
+ Serial.println("connect: setup(): INFO: WiFi disconnected");
+ delay(1000);
+ }
+ Serial.println("connect: connectWifi(): CALL: Connect End");
+}
+
+void wifiStatus() {
+ Serial.println("connect: wifiStatus(): CALL: Status Begin");
+ Serial.println("connect: wifiStatus(): INFO: WiFi connected");
+ Serial.print("connect: wifiStatus(): STATUS: ");
+ Serial.println(WiFi.status());
+ Serial.print("connect: wifiStatus(): IP: ");
+ Serial.println(WiFi.localIP());
+ Serial.print("connect: wifiStatus(): SSID: ");
+ Serial.println(WiFi.SSID());
+ bool ret = Ping.ping("www.google.com", 3);
+ Serial.print("connect: wifiStatus(): PING: ");
+ if (ret) {
+ Serial.println("1");
+ } else {
+ Serial.println("0");
+ }
+
+ delay(250);
+ Serial.println("connect: wifiStatus(): CALL: Status End");
+}
+
+void udpPackets() {
+ Serial.println("connect: udpPackets(): CALL: UDP Begin");
+ int packetSize = Udp.parsePacket();
+ while(packetSize) {
+ Serial.print("connect: udpPackets(): PKTSZ: ");
+ Serial.println(packetSize);
+ Serial.print("connect: udpPackets(): REMOTEIP: ");
+ IPAddress remote = Udp.remoteIP();
+ for (int i =0; i < 4; i++) {
+ Serial.print(remote[i], DEC);
+ if (i < 3) {
+ Serial.print(".");
+ }
+ }
+ Serial.println("");
+ Serial.print("connect: udpPackets(): REMOTEPORT: ");
+ Serial.println(Udp.remotePort());
+
+ // read the packet into packetBufffer
+ Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
+ Serial.print("connect: udpPackets(): RECV: ");
+ Serial.println(packetBuffer);
+
+ // send the same message back
+ Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
+ Udp.write(packetBuffer);
+ Udp.endPacket();
+
+ packetSize = Udp.parsePacket();
+ }
+ Serial.println("connect: udpPackets(): CALL: UDP End");
+}
diff --git a/acts/tests/google/net/arduino/disconnect_wifi/disconnect_wifi.ino b/acts/tests/google/net/arduino/disconnect_wifi/disconnect_wifi.ino
new file mode 100644
index 0000000000..cacef95c18
--- /dev/null
+++ b/acts/tests/google/net/arduino/disconnect_wifi/disconnect_wifi.ino
@@ -0,0 +1,64 @@
+#include <ESP8266WiFi.h>
+
+void setup() {
+ delay(1000); // wait for a second to read from serial port after flashing
+ Serial.begin(9600);
+ Serial.println("disconnect: setup(): CALL: Setup Begin");
+ Serial.println("disconnect: setup(): INFO: Setting baud rate to 9600");
+
+ wifiStatus();
+ disconnectWifi();
+
+ Serial.println("disconnect: setup(): CALL: Setup End");
+}
+
+void loop() {
+ wifiStatus();
+ scanNetworks();
+}
+
+void disconnectWifi() {
+ Serial.println("disconnect: setup(): CALL: Disconnect Begin");
+ WiFi.disconnect();
+ while (WiFi.status() == WL_CONNECTED) {
+ Serial.println("disconnect: setup(): INFO: WiFi connected");
+ delay(1000);
+ }
+ Serial.println("disconnect: setup(): CALL: Disconnect End");
+}
+
+void wifiStatus() {
+ Serial.println("disconnect: wifiStatus(): CALL: Status Begin");
+ Serial.println("disconnect: loop(): INFO: WiFi disconnected");
+ Serial.print("disconnect: wifiStatus(): STATUS: ");
+ Serial.println(WiFi.status());
+ Serial.print("disconnect: wifiStatus(): IP: ");
+ Serial.println(WiFi.localIP());
+ Serial.print("disconnect: wifiStatus(): SSID: ");
+ Serial.println(WiFi.SSID());
+ delay(1000);
+ Serial.println("disconnect: wifiStatus(): CALL: Status End");
+}
+
+void scanNetworks() {
+ Serial.println("disconnect: scanNetworks(): CALL: Scan Begin");
+ int n = WiFi.scanNetworks();
+ if (n == 0) {
+ Serial.println("disconnect: scanNetworks(): INFO: No networks found");
+ Serial.println("disconnect: scanNetworks(): COUNT: 0");
+ } else {
+ Serial.println("disconnect: scanNetworks(): INFO: WiFi Networks Found");
+ Serial.print("COUNT: ");
+ Serial.println(n);
+
+ for (int i = 0; i < n; ++i) {
+ Serial.print("SSID: ");
+ Serial.println(WiFi.SSID(i));
+ Serial.print("RSSI: ");
+ Serial.println(WiFi.RSSI(i));
+ }
+ }
+
+ delay(5000); // Wait a bit before scanning again
+ Serial.println("disconnect: scanNetworks(): CALL: Scan End");
+}
diff --git a/acts/tests/google/wifi/WifiTetheringTest.py b/acts/tests/google/wifi/WifiTetheringTest.py
index fa20aa5cf9..080f9e47c4 100644
--- a/acts/tests/google/wifi/WifiTetheringTest.py
+++ b/acts/tests/google/wifi/WifiTetheringTest.py
@@ -29,6 +29,8 @@ from acts.test_utils.tel.tel_test_utils import get_operator_name
from acts.test_utils.tel.tel_test_utils import verify_http_connection
from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_2G
from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_5G
+from acts.test_utils.net import socket_test_utils as sutils
+from acts.test_utils.net import arduino_test_utils as dutils
from acts.test_utils.wifi import wifi_test_utils as wutils
WAIT_TIME = 2
@@ -162,6 +164,56 @@ class WifiTetheringTest(base_test.BaseTestClass):
wutils.wifi_connect(dut, self.network)
device_connected[dut_id] = not device_connected[dut_id]
+ def _connect_disconnect_android_device(self, dut_id, wifi_state):
+ """ Connect or disconnect wifi on android device depending on the
+ current wifi state
+
+ Args:
+ 1. dut_id: tethered device to change the wifi state
+ 2. wifi_state: current wifi state
+ """
+ ad = self.tethered_devices[dut_id]
+ if wifi_state:
+ self.log.info("Disconnecting wifi on android device")
+ wutils.wifi_forget_network(ad, self.network["SSID"])
+ else:
+ self.log.info("Connecting to wifi on android device")
+ wutils.wifi_connect(ad, self.network)
+
+ def _connect_disconnect_wifi_dongle(self, dut_id, wifi_state):
+ """ Connect or disconnect wifi on wifi dongle depending on the
+ current wifi state
+
+ Args:
+ 1. dut_id: wifi dongle to change the wifi state
+ 2. wifi_state: current wifi state
+ """
+ wd = self.arduino_wifi_dongles[dut_id]
+ if wifi_state:
+ self.log.info("Disconnecting wifi on dongle")
+ dutils.disconnect_wifi(wd)
+ else:
+ self.log.info("Connecting to wifi on dongle")
+ dutils.connect_wifi(wd, self.network)
+
+ def _connect_disconnect_tethered_devices(self):
+ """ Connect disconnect tethered devices to wifi hotspot """
+ num_android_devices = len(self.tethered_devices)
+ num_wifi_dongles = 0
+ if self.arduino_wifi_dongles:
+ num_wifi_dongles = len(self.arduino_wifi_dongles)
+ total_devices = num_android_devices + num_wifi_dongles
+ device_connected = [False] * total_devices
+ for _ in range(50):
+ dut_id = random.randint(0, total_devices-1)
+ wifi_state = device_connected[dut_id]
+ if dut_id < num_android_devices:
+ self._connect_disconnect_android_device(dut_id, wifi_state)
+ else:
+ self._connect_disconnect_wifi_dongle(dut_id-num_android_devices,
+ wifi_state)
+ device_connected[dut_id] = not device_connected[dut_id]
+
def _verify_ping(self, dut, ip, isIPv6=False):
""" Verify ping works from the dut to IP/hostname
@@ -191,25 +243,24 @@ class WifiTetheringTest(base_test.BaseTestClass):
return dut.droid.connectivityGetIPv4Addresses(iface_name) + \
dut.droid.connectivityGetIPv6Addresses(iface_name)
- def _test_traffic_between_two_tethered_devices(self, dut1, dut2):
+ def _test_traffic_between_two_tethered_devices(self, ad, wd):
""" Verify pinging interfaces of one DUT from another
Args:
- 1. dut1 - tethered device 1
- 2. dut2 - tethered device 2
+ 1. ad - android device
+ 2. wd - wifi dongle
"""
- wutils.wifi_connect(dut1, self.network)
- wutils.wifi_connect(dut2, self.network)
-
- dut1_ipaddrs = dut1.droid.connectivityGetIPv4Addresses("wlan0") + \
- dut1.droid.connectivityGetIPv6Addresses("wlan0")
- dut2_ipaddrs = dut2.droid.connectivityGetIPv4Addresses("wlan0") + \
- dut2.droid.connectivityGetIPv6Addresses("wlan0")
-
- for ip in dut1_ipaddrs:
- asserts.assert_true(self._verify_ping(dut2, ip), "%s " % ip)
- for ip in dut2_ipaddrs:
- asserts.assert_true(self._verify_ping(dut1, ip), "%s " % ip)
+ wutils.wifi_connect(ad, self.network)
+ dutils.connect_wifi(wd, self.network)
+ local_ip = ad.droid.connectivityGetIPv4Addresses('wlan0')[0]
+ remote_ip = wd.ip_address()
+ port = 8888
+
+ time.sleep(6) # wait until UDP packets method is invoked
+ socket = sutils.open_datagram_socket(ad, local_ip, port)
+ sutils.send_recv_data_datagram_sockets(
+ ad, ad, socket, socket, remote_ip, port)
+ sutils.close_datagram_socket(ad, socket)
def _ping_hotspot_interfaces_from_tethered_device(self, dut):
""" Ping hotspot interfaces from tethered device
@@ -331,7 +382,7 @@ class WifiTetheringTest(base_test.BaseTestClass):
wutils.stop_wifi_tethering(self.hotspot_device)
@test_tracker_info(uuid="110b61d1-8af2-4589-8413-11beac7a3025")
- def wifi_tethering_2ghz_traffic_between_2tethered_devices(self):
+ def test_wifi_tethering_2ghz_traffic_between_2tethered_devices(self):
""" Steps:
1. Start wifi hotspot with 2G band
@@ -341,7 +392,7 @@ class WifiTetheringTest(base_test.BaseTestClass):
wutils.toggle_wifi_off_and_on(self.hotspot_device)
self._start_wifi_tethering(WIFI_CONFIG_APBAND_2G)
self._test_traffic_between_two_tethered_devices(self.tethered_devices[0],
- self.tethered_devices[1])
+ self.arduino_wifi_dongles[0])
wutils.stop_wifi_tethering(self.hotspot_device)
@test_tracker_info(uuid="953f6e2e-27bd-4b73-85a6-d2eaa4e755d5")
@@ -355,7 +406,7 @@ class WifiTetheringTest(base_test.BaseTestClass):
wutils.toggle_wifi_off_and_on(self.hotspot_device)
self._start_wifi_tethering(WIFI_CONFIG_APBAND_5G)
self._test_traffic_between_two_tethered_devices(self.tethered_devices[0],
- self.tethered_devices[1])
+ self.arduino_wifi_dongles[0])
wutils.stop_wifi_tethering(self.hotspot_device)
@test_tracker_info(uuid="d7d5aa51-682d-4882-a334-61966d93b68c")
@@ -368,7 +419,7 @@ class WifiTetheringTest(base_test.BaseTestClass):
"""
wutils.toggle_wifi_off_and_on(self.hotspot_device)
self._start_wifi_tethering(WIFI_CONFIG_APBAND_2G)
- self._connect_disconnect_devices()
+ self._connect_disconnect_tethered_devices()
wutils.stop_wifi_tethering(self.hotspot_device)
@test_tracker_info(uuid="34abd6c9-c7f1-4d89-aa2b-a66aeabed9aa")