From 519ab8a61eab40a5471aebcb9c9e78938d9819ea Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Sun, 12 Dec 2021 14:28:16 +0800 Subject: [PATCH 01/33] v1.3.0_start --- src/main/java/com/sonic/agent/tools/ScrcpyTool.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sonic/agent/tools/ScrcpyTool.java b/src/main/java/com/sonic/agent/tools/ScrcpyTool.java index 7836a335..84b07da5 100644 --- a/src/main/java/com/sonic/agent/tools/ScrcpyTool.java +++ b/src/main/java/com/sonic/agent/tools/ScrcpyTool.java @@ -17,7 +17,7 @@ public static void main(String[] args) throws IOException, InterruptedException InputStream inputStream; outputStream = capSocket.getOutputStream(); inputStream = capSocket.getInputStream(); -// outputStream.write(0); + outputStream.write(0); int readLength; int naluIndex = 0; From 4d87436460bf389b5ebe95bc17139b1dbe682b24 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Sun, 12 Dec 2021 18:48:17 +0800 Subject: [PATCH 02/33] save_is_windows_bug --- src/main/java/com/sonic/agent/automation/IOSStepHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java index 7abeae75..ccf045ca 100644 --- a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java @@ -65,7 +65,8 @@ public int startIOSDriver(String udId) throws InterruptedException, IOException desiredCapabilities.setCapability(IOSMobileCapabilityType.WEB_DRIVER_AGENT_URL, "http://127.0.0.1:" + wdaPort); desiredCapabilities.setCapability("useXctestrunFile", false); desiredCapabilities.setCapability("mjpegServerPort", imgPort); - desiredCapabilities.setCapability(IOSMobileCapabilityType.USE_PREBUILT_WDA, true); + //bug? + desiredCapabilities.setCapability(IOSMobileCapabilityType.USE_PREBUILT_WDA, false); try { iosDriver = new IOSDriver(AppiumServer.service.getUrl(), desiredCapabilities); iosDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); From be7ee94e9e2ebc89c39671d8d05e83081a6a8750 Mon Sep 17 00:00:00 2001 From: JayWenStar <1599603313@qq.com> Date: Sun, 12 Dec 2021 21:50:43 +0800 Subject: [PATCH 03/33] =?UTF-8?q?=E6=9B=B4=E6=94=B9dev=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-dev.yml | 8 ++++---- src/main/resources/application.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 94db2d2c..71bd84b3 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,10 +1,10 @@ sonic: agent: - host: 172.25.128.1 + host: 127.0.0.1 port: 7777 - key: 29002272-4659-4808-a804-08ce3388b136 + key: 7bbc50da-1c7b-43e7-9d5d-4e8a86fa896a server: - host: 172.25.128.1 + host: 127.0.0.1 folder-port: 8094 transport-port: 8095 @@ -20,7 +20,7 @@ modules: webview: enable: true chrome-driver-debug-port: 7778 - chrome-driver-path: C:\Program Files\Google\Chrome\Application\chromedriver.exe + chrome-driver-path: "/Applications/Google Chrome.app/Contents/MacOS/chromedriver" logging: file: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 56c09806..9473ce6c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,4 @@ spring: version: @project.version@ profiles: - active: prod,@profileActive@ \ No newline at end of file + active: dev,@profileActive@ \ No newline at end of file From 0e0c9673f8a958fe88a25ec93577bb48fce7d30e Mon Sep 17 00:00:00 2001 From: JayWenStar <1599603313@qq.com> Date: Mon, 13 Dec 2021 00:44:43 +0800 Subject: [PATCH 04/33] =?UTF-8?q?=F0=9F=90=9B=EF=BC=9A=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E7=AD=89=E5=BE=85=E8=B6=85=E6=97=B6=E5=90=8E=EF=BC=8C?= =?UTF-8?q?=E4=BB=8D=E7=84=B6=E6=9C=89=E4=BB=BB=E5=8A=A1=E5=9C=A8=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=EF=BC=8C=E4=BD=86=E8=AE=BE=E5=A4=87=E4=BC=9A=E8=A2=AB?= =?UTF-8?q?=E9=87=8A=E6=94=BE=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tests/android/AndroidTestTaskBootThread.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java b/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java index 1d9cf8fb..16815d35 100644 --- a/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java +++ b/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java @@ -144,6 +144,9 @@ public AndroidTestTaskBootThread setUdId(String udId) { @Override public void run() { + + boolean startTestSuccess = false; + try { int wait = 0; while (!AndroidDeviceLocalStatus.startTest(udId)) { @@ -161,6 +164,7 @@ public void run() { //启动测试 try { androidStepHandler.startAndroidDriver(udId); + startTestSuccess = true; } catch (Exception e) { log.error(e.getMessage()); androidStepHandler.closeAndroidDriver(); @@ -194,9 +198,11 @@ public void run() { log.error("任务异常,中断:{}", e.getMessage()); androidStepHandler.setResultDetailStatus(ResultDetailStatus.FAIL); } finally { - AndroidDeviceLocalStatus.finish(udId); - androidStepHandler.closeAndroidDriver(); - androidStepHandler.sendStatus(); + if (startTestSuccess) { + AndroidDeviceLocalStatus.finish(udId); + androidStepHandler.closeAndroidDriver(); + androidStepHandler.sendStatus(); + } } } } From 36c4287fe13a2b9a92cf85b371040e2d6f9314c5 Mon Sep 17 00:00:00 2001 From: JayWenStar <1599603313@qq.com> Date: Mon, 13 Dec 2021 02:16:17 +0800 Subject: [PATCH 05/33] =?UTF-8?q?=E4=BF=9D=E7=95=99sendStatus=E5=BC=BA?= =?UTF-8?q?=E5=88=B6=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sonic/agent/tests/android/AndroidTestTaskBootThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java b/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java index 16815d35..4c4b4448 100644 --- a/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java +++ b/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java @@ -201,8 +201,8 @@ public void run() { if (startTestSuccess) { AndroidDeviceLocalStatus.finish(udId); androidStepHandler.closeAndroidDriver(); - androidStepHandler.sendStatus(); } + androidStepHandler.sendStatus(); } } } From a5046d18aae04c53c0073dde37e38ad4cf2049af Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Mon, 13 Dec 2021 21:12:11 +0800 Subject: [PATCH 06/33] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sonic/agent/tests/android/AndroidTestTaskBootThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java b/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java index 4c4b4448..f2f3d804 100644 --- a/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java +++ b/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java @@ -161,10 +161,10 @@ public void run() { } } + startTestSuccess = true; //启动测试 try { androidStepHandler.startAndroidDriver(udId); - startTestSuccess = true; } catch (Exception e) { log.error(e.getMessage()); androidStepHandler.closeAndroidDriver(); From 1b67cbc06cc129dcbe3afdee95a67de4266b50d7 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Tue, 14 Dec 2021 20:04:36 +0800 Subject: [PATCH 07/33] =?UTF-8?q?ios=E5=88=86=E8=BE=A8=E7=8E=87=E5=8F=91?= =?UTF-8?q?=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sonic/agent/automation/IOSStepHandler.java | 4 ++++ .../sonic/agent/bridge/ios/IOSDeviceLocalStatus.java | 2 ++ .../java/com/sonic/agent/bridge/ios/TIDeviceTool.java | 4 +++- src/main/java/com/sonic/agent/maps/IOSSizeMap.java | 11 +++++++++++ 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/sonic/agent/maps/IOSSizeMap.java diff --git a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java index ccf045ca..a67b45f5 100644 --- a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java @@ -7,6 +7,7 @@ import com.sonic.agent.interfaces.ResultDetailStatus; import com.sonic.agent.interfaces.StepType; import com.sonic.agent.maps.IOSProcessMap; +import com.sonic.agent.maps.IOSSizeMap; import com.sonic.agent.tools.LogTool; import com.sonic.agent.tools.UploadTools; import io.appium.java_client.MobileBy; @@ -78,6 +79,9 @@ public int startIOSDriver(String udId) throws InterruptedException, IOException setResultDetailStatus(ResultDetailStatus.FAIL); throw e; } + int width = iosDriver.manage().window().getSize().width; + int height = iosDriver.manage().window().getSize().height; + IOSSizeMap.getMap().put(udId, width + "x" + height); return imgPort; } diff --git a/src/main/java/com/sonic/agent/bridge/ios/IOSDeviceLocalStatus.java b/src/main/java/com/sonic/agent/bridge/ios/IOSDeviceLocalStatus.java index c2c0fca6..960daeeb 100644 --- a/src/main/java/com/sonic/agent/bridge/ios/IOSDeviceLocalStatus.java +++ b/src/main/java/com/sonic/agent/bridge/ios/IOSDeviceLocalStatus.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSONObject; import com.sonic.agent.interfaces.DeviceStatus; import com.sonic.agent.maps.IOSDeviceManagerMap; +import com.sonic.agent.maps.IOSSizeMap; import com.sonic.agent.netty.NettyThreadPool; public class IOSDeviceLocalStatus { @@ -10,6 +11,7 @@ public class IOSDeviceLocalStatus { public static void send(String udId, String status) { JSONObject deviceDetail = new JSONObject(); deviceDetail.put("msg", "deviceDetail"); + deviceDetail.put("size", IOSSizeMap.getMap().get(udId)); deviceDetail.put("udId", udId); deviceDetail.put("status", status); NettyThreadPool.send(deviceDetail); diff --git a/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java b/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java index a89f48b3..673499ca 100644 --- a/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java +++ b/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java @@ -4,6 +4,7 @@ import com.sonic.agent.interfaces.PlatformType; import com.sonic.agent.maps.IOSDeviceManagerMap; import com.sonic.agent.maps.IOSProcessMap; +import com.sonic.agent.maps.IOSSizeMap; import com.sonic.agent.netty.NettyThreadPool; import com.sonic.agent.tools.PortTool; import com.sonic.agent.tools.ProcessCommandTool; @@ -90,6 +91,7 @@ public static void sendDisConnectStatus(String udId) { deviceStatus.put("msg", "deviceDetail"); deviceStatus.put("udId", udId); deviceStatus.put("status", "DISCONNECTED"); + deviceStatus.put("size", IOSSizeMap.getMap().get(udId)); logger.info("iOS设备:" + udId + " 下线!"); NettyThreadPool.send(deviceStatus); IOSDeviceManagerMap.getMap().remove(udId); @@ -105,7 +107,7 @@ public static void sendOnlineStatus(String udId) { deviceStatus.put("status", "ONLINE"); deviceStatus.put("platform", PlatformType.IOS); deviceStatus.put("version", info.getString("version")); - deviceStatus.put("size", "未知"); + deviceStatus.put("size", IOSSizeMap.getMap().get(udId)); deviceStatus.put("cpu", info.getString("cpu")); deviceStatus.put("manufacturer", "APPLE"); logger.info("iOS设备:" + udId + " 上线!"); diff --git a/src/main/java/com/sonic/agent/maps/IOSSizeMap.java b/src/main/java/com/sonic/agent/maps/IOSSizeMap.java new file mode 100644 index 00000000..1a89d365 --- /dev/null +++ b/src/main/java/com/sonic/agent/maps/IOSSizeMap.java @@ -0,0 +1,11 @@ +package com.sonic.agent.maps; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class IOSSizeMap { + private static Map sizeMap = new ConcurrentHashMap(); + public static Map getMap() { + return sizeMap; + } +} From 89bcee9927839f12e33d2bb116f689445eca93e9 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Wed, 15 Dec 2021 21:22:41 +0800 Subject: [PATCH 08/33] save --- .../com/sonic/agent/tests/android/AndroidTemperThread.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java b/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java new file mode 100644 index 00000000..97222397 --- /dev/null +++ b/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java @@ -0,0 +1,5 @@ +package com.sonic.agent.tests.android; + +public class AndroidTemperThread { + +} From e5b260269427129cfc92496901209dc350612411 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Fri, 17 Dec 2021 00:44:29 +0800 Subject: [PATCH 09/33] save --- .../agent/tests/android/AndroidTemperThread.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java b/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java index 97222397..c38f3e0d 100644 --- a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java +++ b/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java @@ -1,5 +1,16 @@ package com.sonic.agent.tests.android; -public class AndroidTemperThread { +import com.android.ddmlib.IDevice; +import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool; +import java.util.List; + +public class AndroidTemperThread extends Thread{ + @Override + public void run() { + IDevice[] deviceList = AndroidDeviceBridgeTool.getRealOnLineDevices(); + for(IDevice iDevice:deviceList){ + + } + } } From 1652dde5d82e2c62d0685707e1010cfc1a8d04de Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Sat, 18 Dec 2021 01:54:45 +0800 Subject: [PATCH 10/33] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E7=94=B5=E6=B1=A0?= =?UTF-8?q?=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sonic/agent/tests/android/AndroidTemperThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java b/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java index c38f3e0d..4f62d6ac 100644 --- a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java +++ b/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java @@ -10,7 +10,7 @@ public class AndroidTemperThread extends Thread{ public void run() { IDevice[] deviceList = AndroidDeviceBridgeTool.getRealOnLineDevices(); for(IDevice iDevice:deviceList){ - + AndroidDeviceBridgeTool.executeCommand(iDevice,"dumpsys battery"); } } } From 1ba75cab5142b5993206d2461051a93470cca5f7 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Sat, 18 Dec 2021 17:52:59 +0800 Subject: [PATCH 11/33] debugging --- .../com/sonic/agent/automation/AppiumServer.java | 2 +- .../sonic/agent/automation/IOSStepHandler.java | 3 ++- .../com/sonic/agent/bridge/ios/TIDeviceTool.java | 16 ++++++++++++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/sonic/agent/automation/AppiumServer.java b/src/main/java/com/sonic/agent/automation/AppiumServer.java index 83944a57..985f46b2 100644 --- a/src/main/java/com/sonic/agent/automation/AppiumServer.java +++ b/src/main/java/com/sonic/agent/automation/AppiumServer.java @@ -20,7 +20,7 @@ public class AppiumServer { */ public static void start() { service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder().usingAnyFreePort() - .withArgument(GeneralServerFlag.LOG_LEVEL, "error") +// .withArgument(GeneralServerFlag.LOG_LEVEL, "error") .withArgument(GeneralServerFlag.ALLOW_INSECURE, "chromedriver_autodownload") .withArgument(GeneralServerFlag.SESSION_OVERRIDE)); service.start(); diff --git a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java index a67b45f5..3865300c 100644 --- a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java @@ -67,7 +67,8 @@ public int startIOSDriver(String udId) throws InterruptedException, IOException desiredCapabilities.setCapability("useXctestrunFile", false); desiredCapabilities.setCapability("mjpegServerPort", imgPort); //bug? - desiredCapabilities.setCapability(IOSMobileCapabilityType.USE_PREBUILT_WDA, false); + desiredCapabilities.setCapability(IOSMobileCapabilityType.SHOW_XCODE_LOG, true); + desiredCapabilities.setCapability(IOSMobileCapabilityType.USE_PREBUILT_WDA, true); try { iosDriver = new IOSDriver(AppiumServer.service.getUrl(), desiredCapabilities); iosDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); diff --git a/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java b/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java index 673499ca..ef1aead7 100644 --- a/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java +++ b/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java @@ -169,8 +169,20 @@ public static int startWda(String udId) throws IOException, InterruptedException } else { wdaProcess = Runtime.getRuntime().exec(new String[]{"cmd", "/C", commandLine}); } -// BufferedReader stdInput = new BufferedReader(new -// InputStreamReader(wdaProcess.getInputStream())); + + new Thread(() -> { + BufferedReader stdInput = new BufferedReader(new + InputStreamReader(wdaProcess.getInputStream())); + String s = null; + while (wdaProcess.isAlive()) { + try { + if (!((s = stdInput.readLine()) != null)) break; + } catch (IOException e) { + e.printStackTrace(); + } + logger.info(s); + } + }).start(); // String s; // while ((s = stdInput.readLine()) != null) { // if (s.contains("WebDriverAgent start successfully")) { From 5e1431917a6e933a4c0c4e62e2b0fad9cbf57d61 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Sat, 18 Dec 2021 22:02:07 +0800 Subject: [PATCH 12/33] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E5=8A=A0=E5=BF=ABdrive?= =?UTF-8?q?r=E5=8A=A0=E8=BD=BD=E6=97=B6=E9=97=B4=E3=80=81=E8=A7=A6?= =?UTF-8?q?=E6=8E=A7socket=E5=85=81=E8=AE=B8=E5=87=86=E5=A4=87=E6=97=B6?= =?UTF-8?q?=E9=95=BF=E6=BC=94=E5=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sonic/agent/automation/AndroidStepHandler.java | 5 +++++ .../java/com/sonic/agent/websockets/AndroidWSServer.java | 2 +- src/main/resources/application.yml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java b/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java index b52e0467..d5e25c5d 100644 --- a/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java @@ -120,6 +120,11 @@ public void startAndroidDriver(String udId) throws InterruptedException { desiredCapabilities.setCapability(AndroidMobileCapabilityType.ADB_EXEC_TIMEOUT, 60000); //UIA2安装超时时间 desiredCapabilities.setCapability("uiautomator2ServerInstallTimeout", 30000); + + //io.appium.uiautomator2.server io.appium.uiautomator2.server.test //io.appium.settings +// desiredCapabilities.setCapability("skipServerInstallation",true); +// desiredCapabilities.setCapability("disableWindowAnimation",true); +// desiredCapabilities.setCapability("skipDeviceInitialization",true); //等待新命令超时时间 desiredCapabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 3600); //不重置应用 diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index 8dc727af..137cb4c4 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -202,7 +202,7 @@ public boolean isCancelled() { e.printStackTrace(); } // 超时就不继续等了,保证其它服务可运行 - if (wait > 6) { + if (wait > 18) { return; } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 56c09806..9473ce6c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,4 @@ spring: version: @project.version@ profiles: - active: prod,@profileActive@ \ No newline at end of file + active: dev,@profileActive@ \ No newline at end of file From 67069643d38da7c220e2d69fb2dba099e2808707 Mon Sep 17 00:00:00 2001 From: JayWenStar <1599603313@qq.com> Date: Sun, 19 Dec 2021 20:43:06 +0800 Subject: [PATCH 13/33] =?UTF-8?q?=E2=AD=90=EF=B8=8F=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=BF=9C=E6=8E=A7websocket=E9=94=81=EF=BC=8C=E9=98=B2?= =?UTF-8?q?=E6=AD=A2=E6=B5=8F=E8=A7=88=E5=99=A8=E5=88=B7=E6=96=B0=E7=9E=AC?= =?UTF-8?q?=E9=97=B4=E5=AF=BC=E8=87=B4=E8=B5=84=E6=BA=90close/start?= =?UTF-8?q?=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sonic/agent/maps/DevicesLockMap.java | 102 ++++++++++++++++++ .../sonic/agent/maps/WebSocketSessionMap.java | 62 ++++++++--- .../com/sonic/agent/netty/NettyClient.java | 1 + .../com/sonic/agent/tests/TaskManager.java | 6 +- .../java/com/sonic/agent/tools/LogTool.java | 2 +- .../agent/websockets/AndroidWSServer.java | 37 +++++-- .../sonic/agent/websockets/IOSWSServer.java | 18 +--- 7 files changed, 183 insertions(+), 45 deletions(-) create mode 100644 src/main/java/com/sonic/agent/maps/DevicesLockMap.java diff --git a/src/main/java/com/sonic/agent/maps/DevicesLockMap.java b/src/main/java/com/sonic/agent/maps/DevicesLockMap.java new file mode 100644 index 00000000..6b1de9bb --- /dev/null +++ b/src/main/java/com/sonic/agent/maps/DevicesLockMap.java @@ -0,0 +1,102 @@ +package com.sonic.agent.maps; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Assert; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +/** + * 设备逻辑锁 Map + * + * @author JayWenStar + * @date 2021/12/19 19:51 下午 + */ +public class DevicesLockMap { + + private final static Logger logger = LoggerFactory.getLogger(DevicesLockMap.class); + + /** + * key: udId(设备序列号) value: Semaphore + */ + private static Map devicesLockMap = new ConcurrentHashMap<>(); + + /**xxx + * 用设备序列号上锁(无) + * + * @see #lockByUdId(String, Long, TimeUnit) + */ + public static boolean lockByUdId(String udId) throws InterruptedException { + return lockByUdId(udId, null, null); + } + + /** + * 用设备序列号上锁(可设置超时) + * + * @param udId 设备序列号 + * @param timeOut 获取锁超时时间 此参数必须和 timeUnit 同时存在 + * @param timeUnit 时间单位 此参数必须和 timeOut 同时存在 + * @return true: 上锁成功 false: 上锁失败 + */ + public static boolean lockByUdId(String udId, Long timeOut, TimeUnit timeUnit) throws InterruptedException { + // 校验参数 + Assert.hasText(udId, "udId must not be blank"); + if (timeOut != null || timeUnit != null) { + Assert.isTrue( + timeOut != null && timeUnit != null, + "timeOut and timeUnit must not be null at the same time" + ); + } + Semaphore deviceLock; + + // 原子操作,避免put后被别的线程remove造成当前线程lock失效 + synchronized (WebSocketSessionMap.class) { + Semaphore res = devicesLockMap.get(udId); + if (res == null) { + deviceLock = new Semaphore(1); + devicesLockMap.put(udId, deviceLock); + } else { + deviceLock = res; + } + } + + // 无超时获取锁逻辑,直接锁并返回true + if (timeOut == null) { + deviceLock.acquire(); + return true; + } + + // 如果有超时,则成功返回true,超时返回false + try { + return deviceLock.tryAcquire(timeOut, timeUnit); + } catch (InterruptedException e) { + logger.error("获取锁被中断,返回false"); + return false; + } + } + + /** + * 解锁并从map中移除锁 + * + * @param udId 设备序列号 + */ + public static void unlockAndRemoveByUdId(String udId) { + Assert.hasText(udId, "udId must not be blank"); + Semaphore deviceLock; + synchronized (WebSocketSessionMap.class) { + deviceLock = devicesLockMap.get(udId); + removeLockByUdId(udId); + } + if (deviceLock != null) { + deviceLock.release(); + } + } + + public static void removeLockByUdId(String udId) { + devicesLockMap.remove(udId); + } + +} diff --git a/src/main/java/com/sonic/agent/maps/WebSocketSessionMap.java b/src/main/java/com/sonic/agent/maps/WebSocketSessionMap.java index 78b3a154..a9078f75 100644 --- a/src/main/java/com/sonic/agent/maps/WebSocketSessionMap.java +++ b/src/main/java/com/sonic/agent/maps/WebSocketSessionMap.java @@ -1,17 +1,45 @@ -package com.sonic.agent.maps; - -import javax.websocket.Session; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @author ZhouYiXun - * @des webSocket的sessionId与session储存 - * @date 2021/8/16 19:54 - */ -public class WebSocketSessionMap { - private static Map sessionMap = new ConcurrentHashMap(); - public static Map getMap() { - return sessionMap; - } -} +package com.sonic.agent.maps; + +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; + +import javax.websocket.Session; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author ZhouYiXun + * @des webSocket的sessionId与session储存 + * @date 2021/8/16 19:54 + */ +public class WebSocketSessionMap { + + /** + * key: sessionId value: session + */ + private static Map sessionMap = new ConcurrentHashMap<>(); + + + public static Map getSessionMap() { + return sessionMap; + } + + public static void addSession(@NonNull Session session) { + sessionMap.put(session.getId(), session); + } + + public static void removeSession(@NonNull Session session) { + removeSession(session.getId()); + } + + public static void removeSession(String sessionId) { + Assert.hasText(sessionId, "sessionId must not be blank"); + sessionMap.remove(sessionId); + } + + public static Session getSession(String sessionId) { + Assert.hasText(sessionId, "sessionId must not be blank"); + return sessionMap.get(sessionId); + } + +} diff --git a/src/main/java/com/sonic/agent/netty/NettyClient.java b/src/main/java/com/sonic/agent/netty/NettyClient.java index f168e79b..115a6a4f 100644 --- a/src/main/java/com/sonic/agent/netty/NettyClient.java +++ b/src/main/java/com/sonic/agent/netty/NettyClient.java @@ -35,6 +35,7 @@ public class NettyClient implements ApplicationRunner { @Override public void run(ApplicationArguments args) { + // todo 根据 https://netty.io/wiki/native-transports.html 可针对不同系统进行优化,server端的netty同理 group = new NioEventLoopGroup(); bootstrap = new Bootstrap() .group(group) diff --git a/src/main/java/com/sonic/agent/tests/TaskManager.java b/src/main/java/com/sonic/agent/tests/TaskManager.java index 135141c8..4226f11b 100644 --- a/src/main/java/com/sonic/agent/tests/TaskManager.java +++ b/src/main/java/com/sonic/agent/tests/TaskManager.java @@ -153,9 +153,11 @@ public static void clearTerminatedThread() { } /** - * 按照设备序列号强制停止手机正在执行的任务 + * 按照结果id、用例id、设备序列号强制停止手机正在执行的任务 * - * @param udid 设备序列号 + * @param resultId 结果id + * @param caseId 用例id + * @param udid 设备序列号 */ public static void forceStopSuite(int resultId, int caseId, String udid) { String key = String.format(AndroidTestTaskBootThread.ANDROID_TEST_TASK_BOOT_PRE, resultId, caseId, udid); diff --git a/src/main/java/com/sonic/agent/tools/LogTool.java b/src/main/java/com/sonic/agent/tools/LogTool.java index db9fddbb..577f58f1 100644 --- a/src/main/java/com/sonic/agent/tools/LogTool.java +++ b/src/main/java/com/sonic/agent/tools/LogTool.java @@ -39,7 +39,7 @@ public void send(JSONObject message) { message.put("rid", resultId); message.put("udId", udId); if (type.equals(DeviceStatus.DEBUGGING)) { - sendToWebSocket(WebSocketSessionMap.getMap().get(sessionId), message); + sendToWebSocket(WebSocketSessionMap.getSession(sessionId), message); } if (type.equals(DeviceStatus.TESTING)) { sendToServer(message); diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index 137cb4c4..5a69a5b1 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -13,12 +13,12 @@ import com.sonic.agent.bridge.android.AndroidDeviceLocalStatus; import com.sonic.agent.bridge.android.AndroidDeviceThreadPool; import com.sonic.agent.interfaces.DeviceStatus; -import com.sonic.agent.maps.GlobalProcessMap; -import com.sonic.agent.maps.HandlerMap; -import com.sonic.agent.maps.MiniCapMap; -import com.sonic.agent.maps.WebSocketSessionMap; +import com.sonic.agent.maps.*; import com.sonic.agent.netty.NettyThreadPool; -import com.sonic.agent.tools.*; +import com.sonic.agent.tools.MiniCapTool; +import com.sonic.agent.tools.PortTool; +import com.sonic.agent.tools.ProcessCommandTool; +import com.sonic.agent.tools.UploadTools; import org.openqa.selenium.OutputType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,6 +45,7 @@ @Component @ServerEndpoint(value = "/websockets/android/{key}/{udId}/{token}", configurator = MyEndpointConfigure.class) public class AndroidWSServer { + private final Logger logger = LoggerFactory.getLogger(AndroidWSServer.class); @Value("${sonic.agent.key}") private String key; @@ -66,15 +67,25 @@ public void onOpen(Session session, @PathParam("key") String secretKey, logger.info("拦截访问!"); return; } + + session.getUserProperties().put("udId", udId); + boolean lockSuccess = DevicesLockMap.lockByUdId(udId, 30L, TimeUnit.SECONDS); + if (!lockSuccess) { + sendText(session, "30s内获取设备锁失败,请确保设备无人使用"); + return; + } + logger.info("上锁udId:{}", udId); + JSONObject jsonDebug = new JSONObject(); jsonDebug.put("msg", "debugUser"); jsonDebug.put("token", token); jsonDebug.put("udId", udId); NettyThreadPool.send(jsonDebug); - WebSocketSessionMap.getMap().put(session.getId(), session); + WebSocketSessionMap.addSession(session); IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId); if (iDevice == null) { logger.info("设备未连接,请检查!"); + session.close(); return; } AndroidDeviceBridgeTool.screen(iDevice, "abort"); @@ -306,7 +317,13 @@ public boolean isCancelled() { @OnClose public void onClose(Session session) { - exit(session); + String udId = (String) session.getUserProperties().get("udId"); + try { + exit(session); + } finally { + DevicesLockMap.unlockAndRemoveByUdId(udId); + logger.info("解锁udId:{}", udId); + } } @OnError @@ -571,10 +588,12 @@ private void exit(Session session) { } outputMap.remove(session); udIdMap.remove(session); - rotationMap.get(session).interrupt(); + if (rotationMap.get(session) != null) { + rotationMap.get(session).interrupt(); + } rotationMap.remove(session); MiniCapMap.getMap().get(session).interrupt(); - WebSocketSessionMap.getMap().remove(session.getId()); + WebSocketSessionMap.removeSession(session); try { session.close(); } catch (IOException e) { diff --git a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java b/src/main/java/com/sonic/agent/websockets/IOSWSServer.java index 9b1f0b61..3b5f4b3b 100644 --- a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/IOSWSServer.java @@ -1,26 +1,16 @@ package com.sonic.agent.websockets; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.android.ddmlib.IDevice; -import com.sonic.agent.automation.AndroidStepHandler; import com.sonic.agent.automation.HandleDes; import com.sonic.agent.automation.IOSStepHandler; -import com.sonic.agent.automation.RemoteDebugDriver; -import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool; -import com.sonic.agent.bridge.android.AndroidDeviceThreadPool; import com.sonic.agent.bridge.ios.IOSDeviceLocalStatus; import com.sonic.agent.bridge.ios.IOSDeviceThreadPool; import com.sonic.agent.bridge.ios.TIDeviceTool; import com.sonic.agent.interfaces.DeviceStatus; import com.sonic.agent.maps.HandlerMap; -import com.sonic.agent.maps.MiniCapMap; import com.sonic.agent.maps.WebSocketSessionMap; import com.sonic.agent.netty.NettyThreadPool; -import com.sonic.agent.tools.MiniCapTool; -import com.sonic.agent.tools.PortTool; -import com.sonic.agent.tools.ProcessCommandTool; import com.sonic.agent.tools.UploadTools; import io.appium.java_client.TouchAction; import io.appium.java_client.touch.WaitOptions; @@ -29,19 +19,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; -import java.io.OutputStream; import java.time.Duration; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicReference; @Component @ServerEndpoint(value = "/websockets/ios/{key}/{udId}/{token}", configurator = MyEndpointConfigure.class) @@ -63,7 +49,7 @@ public void onOpen(Session session, @PathParam("key") String secretKey, jsonDebug.put("token", token); jsonDebug.put("udId", udId); NettyThreadPool.send(jsonDebug); - WebSocketSessionMap.getMap().put(session.getId(), session); + WebSocketSessionMap.addSession(session); if (!TIDeviceTool.getDeviceList().contains(udId)) { logger.info("设备未连接,请检查!"); return; @@ -264,7 +250,7 @@ private void exit(Session session) { } finally { HandlerMap.getIOSMap().remove(session.getId()); } - WebSocketSessionMap.getMap().remove(session.getId()); + WebSocketSessionMap.removeSession(session); try { session.close(); } catch (IOException e) { From aa4802e49f114d8d55a540db8df0e41da43cddca Mon Sep 17 00:00:00 2001 From: JayWenStar <1599603313@qq.com> Date: Sun, 19 Dec 2021 20:48:22 +0800 Subject: [PATCH 14/33] =?UTF-8?q?=E5=9B=9E=E9=80=80=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-dev.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 71bd84b3..94db2d2c 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,10 +1,10 @@ sonic: agent: - host: 127.0.0.1 + host: 172.25.128.1 port: 7777 - key: 7bbc50da-1c7b-43e7-9d5d-4e8a86fa896a + key: 29002272-4659-4808-a804-08ce3388b136 server: - host: 127.0.0.1 + host: 172.25.128.1 folder-port: 8094 transport-port: 8095 @@ -20,7 +20,7 @@ modules: webview: enable: true chrome-driver-debug-port: 7778 - chrome-driver-path: "/Applications/Google Chrome.app/Contents/MacOS/chromedriver" + chrome-driver-path: C:\Program Files\Google\Chrome\Application\chromedriver.exe logging: file: From 4e22774e73c80fc39295c1015c90300c2913aec2 Mon Sep 17 00:00:00 2001 From: Star <1599603313@qq.com> Date: Sun, 19 Dec 2021 21:09:56 +0800 Subject: [PATCH 15/33] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E9=94=99=E8=AF=AFsendt?= =?UTF-8?q?ext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/sonic/agent/websockets/AndroidWSServer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index 5a69a5b1..50467a31 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -71,7 +71,6 @@ public void onOpen(Session session, @PathParam("key") String secretKey, session.getUserProperties().put("udId", udId); boolean lockSuccess = DevicesLockMap.lockByUdId(udId, 30L, TimeUnit.SECONDS); if (!lockSuccess) { - sendText(session, "30s内获取设备锁失败,请确保设备无人使用"); return; } logger.info("上锁udId:{}", udId); @@ -601,4 +600,4 @@ private void exit(Session session) { } logger.info(session.getId() + "退出"); } -} \ No newline at end of file +} From 59171c0ab762f6aa07537c7f910ac8b72d941a41 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Sun, 19 Dec 2021 21:45:25 +0800 Subject: [PATCH 16/33] =?UTF-8?q?=E5=A4=84=E7=90=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/automation/IOSStepHandler.java | 645 ++++++++++++++++++ .../com/sonic/agent/tools/LaunchTool.java | 5 + .../agent/websockets/AndroidWSServer.java | 1 + 3 files changed, 651 insertions(+) diff --git a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java index 3865300c..8a9c8724 100644 --- a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java @@ -4,21 +4,31 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.sonic.agent.bridge.ios.TIDeviceTool; +import com.sonic.agent.cv.*; +import com.sonic.agent.interfaces.ErrorType; import com.sonic.agent.interfaces.ResultDetailStatus; import com.sonic.agent.interfaces.StepType; import com.sonic.agent.maps.IOSProcessMap; import com.sonic.agent.maps.IOSSizeMap; +import com.sonic.agent.tools.DownImageTool; import com.sonic.agent.tools.LogTool; import com.sonic.agent.tools.UploadTools; import io.appium.java_client.MobileBy; +import io.appium.java_client.MultiTouchAction; import io.appium.java_client.Setting; +import io.appium.java_client.TouchAction; import io.appium.java_client.android.appmanagement.AndroidTerminateApplicationOptions; import io.appium.java_client.android.nativekey.AndroidKey; import io.appium.java_client.android.nativekey.KeyEvent; +import io.appium.java_client.appmanagement.BaseInstallApplicationOptions; +import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions; import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.IOSStartScreenRecordingOptions; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.IOSMobileCapabilityType; import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.touch.WaitOptions; +import io.appium.java_client.touch.offset.PointOption; import org.jsoup.Jsoup; import org.jsoup.nodes.Attribute; import org.jsoup.nodes.Document; @@ -28,15 +38,25 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.support.ui.ExpectedConditions; +import org.springframework.util.Base64Utils; +import org.springframework.util.FileCopyUtils; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.time.Duration; +import java.util.Calendar; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; +import static org.testng.Assert.*; + public class IOSStepHandler { public LogTool log = new LogTool(); private IOSDriver iosDriver; + private JSONObject globalParams = new JSONObject(); private String testPackage = ""; private String udId = ""; //测试状态 @@ -118,6 +138,16 @@ public void closeIOSDriver() { } } + public void waitDevice(int waitCount) { + log.sendStepLog(StepType.INFO, "设备非空闲状态!第" + waitCount + "次等待连接...", ""); + } + + public void waitDeviceTimeOut() { + log.sendStepLog(StepType.ERROR, "等待设备超时!测试跳过!", ""); + //测试标记为异常 + setResultDetailStatus(ResultDetailStatus.WARN); + } + public IOSDriver getDriver() { return iosDriver; } @@ -128,6 +158,31 @@ public void setResultDetailStatus(int status) { } } + public void sendStatus() { + log.sendStatusLog(status); + } + + //判断有无出错 + public int getStatus() { + return status; + } + + //调试每次重设状态 + public void resetResultDetailStatus() { + status = 1; + } + + public boolean getBattery() { + double battery = iosDriver.getBatteryInfo().getLevel(); + if (battery <= 0.1) { + log.sendStepLog(StepType.ERROR, "设备电量过低!", "跳过本次测试..."); + return true; + } else { + return false; + } + } + + private int xpathId = 1; public JSONArray getResource() { @@ -176,6 +231,95 @@ public JSONArray getChild(org.jsoup.select.Elements elements, String xpath) { return elementList; } + public void startRecord() { + try { + IOSStartScreenRecordingOptions recordOption = new IOSStartScreenRecordingOptions(); + recordOption.withTimeLimit(Duration.ofMinutes(30)); + recordOption.withVideoQuality(IOSStartScreenRecordingOptions.VideoQuality.LOW); + recordOption.enableForcedRestart(); + recordOption.withFps(20); + recordOption.withVideoType("h264"); + iosDriver.startRecordingScreen(recordOption); + } catch (Exception e) { + log.sendRecordLog(false, "", ""); + } + } + + public void stopRecord() { + File recordDir = new File("./test-output/record"); + if (!recordDir.exists()) {//判断文件目录是否存在 + recordDir.mkdirs(); + } + long timeMillis = Calendar.getInstance().getTimeInMillis(); + String fileName = timeMillis + "_" + udId.substring(0, 4) + ".mp4"; + File uploadFile = new File(recordDir + File.separator + fileName); + try { + synchronized (IOSStepHandler.class) { + FileOutputStream fileOutputStream = new FileOutputStream(uploadFile); + byte[] bytes = Base64Utils.decodeFromString((iosDriver.stopRecordingScreen())); + fileOutputStream.write(bytes); + fileOutputStream.close(); + } + log.sendRecordLog(true, fileName, UploadTools.uploadPatchRecord(uploadFile)); + } catch (Exception e) { + log.sendRecordLog(false, fileName, ""); + } + } + + public void install(HandleDes handleDes, String path) { + handleDes.setStepDes("安装应用"); + handleDes.setDetail("App安装路径: " + path); + try { + iosDriver.installApp(path, new BaseInstallApplicationOptions() { + @Override + public Map build() { + Map map = new HashMap<>(); + map.put("timeout", 180000); + return map; + } + }); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void uninstall(HandleDes handleDes, String appPackage) { + handleDes.setStepDes("卸载应用"); + handleDes.setDetail("App包名: " + appPackage); + try { + iosDriver.removeApp(appPackage); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void terminate(HandleDes handleDes, String packageName) { + handleDes.setStepDes("终止应用"); + handleDes.setDetail("应用包名: " + packageName); + try { + iosDriver.terminateApp(packageName, new BaseTerminateApplicationOptions() { + @Override + public Map build() { + Map map = new HashMap<>(); + map.put("timeout", 2000); + return map; + } + }); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void runBackground(HandleDes handleDes, long time) { + handleDes.setStepDes("后台运行应用"); + handleDes.setDetail("后台运行App " + time + " ms"); + try { + iosDriver.runAppInBackground(Duration.ofMillis(time)); + } catch (Exception e) { + handleDes.setE(e); + } + } + public void openApp(HandleDes handleDes, String appPackage) { handleDes.setStepDes("打开应用"); handleDes.setDetail("App包名: " + appPackage); @@ -205,6 +349,333 @@ public void unLock(HandleDes handleDes) { } } + public void asserts(HandleDes handleDes, String actual, String expect, String type) { + handleDes.setDetail("真实值: " + actual + " 期望值: " + expect); + try { + switch (type) { + case "assertEquals": + handleDes.setStepDes("断言验证(相等)"); + assertEquals(actual, expect); + break; + case "assertTrue": + handleDes.setStepDes("断言验证(包含)"); + assertTrue(actual.contains(expect)); + break; + case "assertNotTrue": + handleDes.setStepDes("断言验证(不包含)"); + assertFalse(actual.contains(expect)); + break; + } + } catch (AssertionError e) { + handleDes.setE(e); + } + } + + public String getText(HandleDes handleDes, String des, String selector, String pathValue) { + String s = ""; + handleDes.setStepDes("获取" + des + "文本"); + handleDes.setDetail("获取" + selector + ":" + pathValue + "文本"); + try { + s = findEle(selector, pathValue).getText(); + log.sendStepLog(StepType.INFO, "", "文本获取结果: " + s); + } catch (Exception e) { + handleDes.setE(e); + } + return s; + } + + public void hideKey(HandleDes handleDes) { + handleDes.setStepDes("隐藏键盘"); + handleDes.setDetail("隐藏弹出键盘"); + try { + iosDriver.hideKeyboard(); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void click(HandleDes handleDes, String des, String selector, String pathValue) { + handleDes.setStepDes("点击" + des); + handleDes.setDetail("点击" + selector + ": " + pathValue); + try { + findEle(selector, pathValue).click(); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void sendKeys(HandleDes handleDes, String des, String selector, String pathValue, String keys) { + if (keys.contains("{{random}}")) { + String random = (int) (Math.random() * 10 + Math.random() * 10 * 2) + 5 + ""; + keys = keys.replace("{{random}}", random); + } + if (keys.contains("{{timestamp}}")) { + String timeMillis = Calendar.getInstance().getTimeInMillis() + ""; + keys = keys.replace("{{timestamp}}", timeMillis); + } + keys = replaceTrans(keys); + handleDes.setStepDes("对" + des + "输入内容"); + handleDes.setDetail("对" + selector + ": " + pathValue + " 输入: " + keys); + try { + findEle(selector, pathValue).sendKeys(keys); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void getTextAndAssert(HandleDes handleDes, String des, String selector, String pathValue, String expect) { + handleDes.setStepDes("获取" + des + "文本"); + handleDes.setDetail("获取" + selector + ":" + pathValue + "文本"); + try { + String s = findEle(selector, pathValue).getText(); + log.sendStepLog(StepType.INFO, "", "文本获取结果: " + s); + try { + expect = replaceTrans(expect); + assertEquals(s, expect); + log.sendStepLog(StepType.INFO, "验证文本", "真实值: " + s + " 期望值: " + expect); + } catch (AssertionError e) { + log.sendStepLog(StepType.ERROR, "验证" + des + "文本失败!", ""); + handleDes.setE(e); + } + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void longPressPoint(HandleDes handleDes, String des, String xy, int time) { + int x = Integer.parseInt(xy.substring(0, xy.indexOf(","))); + int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1)); + handleDes.setStepDes("长按" + des); + handleDes.setDetail("长按坐标" + time + "毫秒 (" + x + "," + y + ")"); + try { + TouchAction ta = new TouchAction(iosDriver); + ta.longPress(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(time))).release().perform(); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void keyCode(HandleDes handleDes, String key) { + handleDes.setStepDes("按系统按键" + key + "键"); + try { + iosDriver.executeScript("mobile:pressButton", JSON.parse("{name: \"" + key + "\"}")); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void multiAction(HandleDes handleDes, String des1, String xy1, String des2, String xy2, String des3, String xy3, String des4, String xy4) { + int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(","))); + int y1 = Integer.parseInt(xy1.substring(xy1.indexOf(",") + 1)); + int x2 = Integer.parseInt(xy2.substring(0, xy2.indexOf(","))); + int y2 = Integer.parseInt(xy2.substring(xy2.indexOf(",") + 1)); + int x3 = Integer.parseInt(xy3.substring(0, xy3.indexOf(","))); + int y3 = Integer.parseInt(xy3.substring(xy3.indexOf(",") + 1)); + int x4 = Integer.parseInt(xy4.substring(0, xy4.indexOf(","))); + int y4 = Integer.parseInt(xy4.substring(xy4.indexOf(",") + 1)); + String detail = "坐标" + des1 + "( " + x1 + ", " + y1 + " )移动到坐标" + des2 + "( " + x2 + ", " + y2 + " ),同时坐标" + des3 + "( " + x3 + ", " + y3 + " )移动到坐标" + des4 + "( " + x4 + ", " + y4 + " )"; + handleDes.setStepDes("双指操作"); + handleDes.setDetail(detail); + try { + TouchAction hand1 = new TouchAction(iosDriver); + TouchAction hand2 = new TouchAction(iosDriver); + MultiTouchAction multiTouchAction = new MultiTouchAction(iosDriver); + hand1.press(PointOption.point(x1, y1)).moveTo(PointOption.point(x2, y2)).release(); + hand2.press(PointOption.point(x3, y3)).moveTo(PointOption.point(x4, y4)).release(); + multiTouchAction.add(hand1); + multiTouchAction.add(hand2); + multiTouchAction.perform(); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void tap(HandleDes handleDes, String des, String xy) { + int x = Integer.parseInt(xy.substring(0, xy.indexOf(","))); + int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1)); + handleDes.setStepDes("点击" + des); + handleDes.setDetail("点击坐标(" + x + "," + y + ")"); + try { + TouchAction ta = new TouchAction(iosDriver); + ta.tap(PointOption.point(x, y)).perform(); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void swipe(HandleDes handleDes, String des1, String xy1, String des2, String xy2) { + int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(","))); + int y1 = Integer.parseInt(xy1.substring(xy1.indexOf(",") + 1)); + int x2 = Integer.parseInt(xy2.substring(0, xy2.indexOf(","))); + int y2 = Integer.parseInt(xy2.substring(xy2.indexOf(",") + 1)); + handleDes.setStepDes("滑动拖拽" + des1 + "到" + des2); + handleDes.setDetail("拖动坐标(" + x1 + "," + y1 + ")到(" + x2 + "," + y2 + ")"); + try { + TouchAction ta = new TouchAction(iosDriver); + ta.press(PointOption.point(x1, y1)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(300))).moveTo(PointOption.point(x2, y2)).release().perform(); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void longPress(HandleDes handleDes, String des, String selector, String pathValue, int time) { + handleDes.setStepDes("长按" + des); + handleDes.setDetail("长按控件元素" + time + "毫秒 "); + try { + TouchAction ta = new TouchAction(iosDriver); + WebElement webElement = findEle(selector, pathValue); + int x = webElement.getLocation().getX(); + int y = webElement.getLocation().getY(); + Duration duration = Duration.ofMillis(time); + ta.longPress(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(duration)).release().perform(); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void clear(HandleDes handleDes, String des, String selector, String pathValue) { + handleDes.setStepDes("清空" + des); + handleDes.setDetail("清空" + selector + ": " + pathValue); + try { + findEle(selector, pathValue).clear(); + } catch (Exception e) { + handleDes.setE(e); + } + } + + public void getTitle(HandleDes handleDes, String expect) { + String title = iosDriver.getTitle(); + handleDes.setStepDes("验证网页标题"); + handleDes.setDetail("标题:" + title + ",期望值:" + expect); + try { + assertEquals(title, expect); + } catch (AssertionError e) { + handleDes.setE(e); + } + } + + public void clickByImg(HandleDes handleDes, String des, String pathValue) throws Exception { + handleDes.setStepDes("点击图片" + des); + handleDes.setDetail(pathValue); + File file = null; + if (pathValue.startsWith("http")) { + try { + file = DownImageTool.download(pathValue); + } catch (Exception e) { + handleDes.setE(e); + return; + } + } + FindResult findResult = null; + try { + SIFTFinder siftFinder = new SIFTFinder(); + findResult = siftFinder.getSIFTFindResult(file, getScreenToLocal()); + } catch (Exception e) { + log.sendStepLog(StepType.WARN, "SIFT图像算法出错,切换算法中...", + ""); + } + if (findResult != null) { + log.sendStepLog(StepType.INFO, "图片定位到坐标:(" + findResult.getX() + "," + findResult.getY() + ") 耗时:" + findResult.getTime() + " ms", + findResult.getUrl()); + } else { + log.sendStepLog(StepType.INFO, "SIFT算法无法定位图片,切换AKAZE算法中...", + ""); + try { + AKAZEFinder akazeFinder = new AKAZEFinder(); + findResult = akazeFinder.getAKAZEFindResult(file, getScreenToLocal()); + } catch (Exception e) { + log.sendStepLog(StepType.WARN, "AKAZE图像算法出错,切换模版匹配算法中...", + ""); + } + if (findResult != null) { + log.sendStepLog(StepType.INFO, "图片定位到坐标:(" + findResult.getX() + "," + findResult.getY() + ") 耗时:" + findResult.getTime() + " ms", + findResult.getUrl()); + } else { + log.sendStepLog(StepType.INFO, "AKAZE算法无法定位图片,切换模版匹配算法中...", + ""); + try { + TemMatcher temMatcher = new TemMatcher(); + findResult = temMatcher.getTemMatchResult(file, getScreenToLocal()); + } catch (Exception e) { + log.sendStepLog(StepType.WARN, "模版匹配算法出错", + ""); + } + if (findResult != null) { + log.sendStepLog(StepType.INFO, "图片定位到坐标:(" + findResult.getX() + "," + findResult.getY() + ") 耗时:" + findResult.getTime() + " ms", + findResult.getUrl()); + } else { + handleDes.setE(new Exception("图片定位失败!")); + } + } + } + if (findResult != null) { + try { + TouchAction ta = new TouchAction(iosDriver); + ta.tap(PointOption.point(findResult.getX(), findResult.getY())).perform(); + } catch (Exception e) { + log.sendStepLog(StepType.ERROR, "点击" + des + "失败!", ""); + handleDes.setE(e); + } + } + } + + + public void readText(HandleDes handleDes, String language, String text) throws Exception { + TextReader textReader = new TextReader(); + String result = textReader.getTessResult(getScreenToLocal(), language); + log.sendStepLog(StepType.INFO, "", + "图像文字识别结果:
" + result); + String filter = result.replaceAll(" ", ""); + handleDes.setStepDes("图像文字识别"); + handleDes.setDetail("期望包含文本:" + text); + if (!filter.contains(text)) { + handleDes.setE(new Exception("图像文字识别不通过!")); + } + } + + public File getScreenToLocal() { + File file = ((TakesScreenshot) iosDriver).getScreenshotAs(OutputType.FILE); + File resultFile = new File("test-output/" + log.udId + Calendar.getInstance().getTimeInMillis() + ".jpg"); + try { + FileCopyUtils.copy(file, resultFile); + } catch (IOException e) { + e.printStackTrace(); + } + return resultFile; + } + + public String replaceTrans(String text) { + if (text.contains("{{") && text.contains("}}")) { + String tail = text.substring(text.indexOf("{{") + 2); + if (tail.contains("}}")) { + String child = tail.substring(tail.indexOf("}}") + 2); + String middle = tail.substring(0, tail.indexOf("}}")); + text = text.substring(0, text.indexOf("}}") + 2); + if (globalParams.getString(middle) != null) { + text = text.replace("{{" + middle + "}}", globalParams.getString(middle)); + } + text = text + replaceTrans(child); + } + } + return text; + } + + public void checkImage(HandleDes handleDes, String des, String pathValue, double matchThreshold) throws Exception { + log.sendStepLog(StepType.INFO, "开始检测" + des + "兼容", "检测与当前设备截图相似度,期望相似度为" + matchThreshold + "%"); + File file = null; + if (pathValue.startsWith("http")) { + file = DownImageTool.download(pathValue); + } + double score = SimilarityChecker.getSimilarMSSIMScore(file, getScreenToLocal(), true); + handleDes.setStepDes("检测" + des + "图片相似度"); + handleDes.setDetail("相似度为" + score * 100 + "%"); + if (score == 0) { + handleDes.setE(new Exception("图片相似度检测不通过!比对图片分辨率不一致!")); + } else if (score < (matchThreshold / 100)) { + handleDes.setE(new Exception("图片相似度检测不通过!expect " + matchThreshold + " but " + score * 100)); + } + } + public void siriCommand(HandleDes handleDes, String command) { handleDes.setStepDes("siri指令"); handleDes.setDetail("对siri发送指令: " + command); @@ -215,6 +686,20 @@ public void siriCommand(HandleDes handleDes, String command) { } } + public void exceptionLog(Throwable e) { + log.sendStepLog(StepType.WARN, "", "异常信息: " + e.fillInStackTrace().toString()); + } + + public void errorScreen() { + try { + iosDriver.context("NATIVE_APP");//先切换回app + log.sendStepLog(StepType.WARN, "获取异常截图", UploadTools + .upload(((TakesScreenshot) iosDriver).getScreenshotAs(OutputType.FILE), "imageFiles")); + } catch (Exception e) { + log.sendStepLog(StepType.ERROR, "捕获截图失败", ""); + } + } + public String stepScreen(HandleDes handleDes) { handleDes.setStepDes("获取截图"); String url = ""; @@ -228,6 +713,30 @@ public String stepScreen(HandleDes handleDes) { return url; } + public void pause(HandleDes handleDes, int time) { + handleDes.setStepDes("强制等待"); + handleDes.setDetail("等待" + time + " ms"); + try { + Thread.sleep(time); + } catch (InterruptedException e) { + handleDes.setE(e); + } + } + + public void publicStep(HandleDes handleDes, String name, JSONArray stepArray) { + handleDes.setStepDes("执行公共步骤 " + name); + log.sendStepLog(StepType.WARN, "公共步骤 " + name + " 开始执行", ""); + for (Object publicStep : stepArray) { + JSONObject stepDetail = (JSONObject) publicStep; + try { + runStep(stepDetail); + } catch (Throwable e) { + handleDes.setE(e); + break; + } + } + } + public WebElement findEle(String selector, String pathValue) { WebElement we = null; switch (selector) { @@ -267,4 +776,140 @@ public WebElement findEle(String selector, String pathValue) { } return we; } + + public void runStep(JSONObject stepJSON) throws Throwable { + JSONObject step = stepJSON.getJSONObject("step"); + JSONArray eleList = step.getJSONArray("elements"); + HandleDes handleDes = new HandleDes(); + switch (step.getString("stepType")) { + case "siriCommand": + siriCommand(handleDes, step.getString("content")); + break; + case "readText": + readText(handleDes, step.getString("content"), step.getString("text")); + break; + case "clickByImg": + clickByImg(handleDes, eleList.getJSONObject(0).getString("eleName") + , eleList.getJSONObject(0).getString("eleValue")); + break; + case "click": + click(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType") + , eleList.getJSONObject(0).getString("eleValue")); + break; + case "getTitle": + getTitle(handleDes, step.getString("content")); + break; + case "sendKeys": + sendKeys(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType") + , eleList.getJSONObject(0).getString("eleValue"), step.getString("content")); + break; + case "getText": + getTextAndAssert(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType") + , eleList.getJSONObject(0).getString("eleValue"), step.getString("content")); + break; + case "clear": + clear(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType") + , eleList.getJSONObject(0).getString("eleValue")); + break; + case "longPress": + longPress(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType") + , eleList.getJSONObject(0).getString("eleValue"), Integer.parseInt(step.getString("content"))); + break; + case "swipe": + swipe(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue") + , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleValue")); + break; + case "tap": + tap(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")); + break; + case "longPressPoint": + longPressPoint(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue") + , Integer.parseInt(step.getString("content"))); + break; + case "pause": + pause(handleDes, Integer.parseInt(step.getString("content"))); + break; + case "checkImage": + checkImage(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue") + , step.getDouble("content")); + break; + case "stepScreen": + stepScreen(handleDes); + break; + case "openApp": + openApp(handleDes, step.getString("text")); + break; + case "terminate": + terminate(handleDes, step.getString("text")); + break; + case "install": + install(handleDes, step.getString("text")); + break; + case "uninstall": + uninstall(handleDes, step.getString("text")); + break; + case "runBack": + runBackground(handleDes, Long.parseLong(step.getString("content"))); + break; + case "lock": + lock(handleDes); + break; + case "unLock": + unLock(handleDes); + break; + case "zoom": + multiAction(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue") + , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleValue") + , eleList.getJSONObject(2).getString("eleName"), eleList.getJSONObject(2).getString("eleValue") + , eleList.getJSONObject(3).getString("eleName"), eleList.getJSONObject(3).getString("eleValue")); + break; + case "keyCode": + keyCode(handleDes, step.getString("content")); + break; + case "assertEquals": + case "assertTrue": + case "assertNotTrue": + String actual = replaceTrans(step.getString("text")); + String expect = replaceTrans(step.getString("content")); + asserts(handleDes, actual, expect, step.getString("stepType")); + break; + case "getTextValue": + globalParams.put(step.getString("content"), getText(handleDes, eleList.getJSONObject(0).getString("eleName") + , eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue"))); + break; + case "hideKey": + hideKey(handleDes); + break; +// case "monkey": +// runMonkey(handleDes, step.getJSONObject("content"), step.getJSONArray("text").toJavaList(JSONObject.class)); +// break; + case "publicStep": + publicStep(handleDes, step.getString("content"), stepJSON.getJSONArray("pubSteps")); + } + switchType(step.getInteger("error"), handleDes.getStepDes(), handleDes.getDetail(), handleDes.getE()); + } + + public void switchType(int error, String step, String detail, Throwable e) throws Throwable { + if (e != null) { + switch (error) { + case ErrorType.IGNORE: + log.sendStepLog(StepType.PASS, step + "异常!已忽略...", detail); + break; + case ErrorType.WARNING: + log.sendStepLog(StepType.WARN, step + "异常!", detail); + setResultDetailStatus(ResultDetailStatus.WARN); + errorScreen(); + exceptionLog(e); + break; + case ErrorType.SHUTDOWN: + log.sendStepLog(StepType.ERROR, step + "异常!", detail); + setResultDetailStatus(ResultDetailStatus.FAIL); + errorScreen(); + exceptionLog(e); + throw e; + } + } else { + log.sendStepLog(StepType.PASS, step, detail); + } + } } diff --git a/src/main/java/com/sonic/agent/tools/LaunchTool.java b/src/main/java/com/sonic/agent/tools/LaunchTool.java index 3d88647d..35531291 100644 --- a/src/main/java/com/sonic/agent/tools/LaunchTool.java +++ b/src/main/java/com/sonic/agent/tools/LaunchTool.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Component; import javax.annotation.PreDestroy; +import java.io.File; @Component @DependsOn("nettyMsgInit") @@ -19,6 +20,10 @@ public class LaunchTool implements ApplicationRunner { @Override public void run(ApplicationArguments args) { + File testFile = new File("test-output"); + if (!testFile.exists()) { + testFile.mkdirs(); + } AppiumServer.start(); } diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index 50467a31..45adf84d 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -71,6 +71,7 @@ public void onOpen(Session session, @PathParam("key") String secretKey, session.getUserProperties().put("udId", udId); boolean lockSuccess = DevicesLockMap.lockByUdId(udId, 30L, TimeUnit.SECONDS); if (!lockSuccess) { + logger.info("30s内获取设备锁失败,请确保设备无人使用"); return; } logger.info("上锁udId:{}", udId); From e4a1e3cb61a7270803be5c8e9bd5e2259d7adc22 Mon Sep 17 00:00:00 2001 From: JayWenStar <1599603313@qq.com> Date: Sun, 19 Dec 2021 21:55:11 +0800 Subject: [PATCH 17/33] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B0=8Fbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sonic/agent/tests/android/OutputSocketThread.java | 6 +++++- .../java/com/sonic/agent/websockets/AndroidWSServer.java | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java b/src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java index bed56806..a5fc493b 100644 --- a/src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java +++ b/src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java @@ -169,7 +169,11 @@ public void run() { if (count % 4 == 0) { count = 0; oldBytes = finalBytes; - sendByte(session, finalBytes); + if (session.isOpen()) { + sendByte(session, finalBytes); + } else { + return; + } } } } diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index 45adf84d..a69ff6eb 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -85,7 +85,6 @@ public void onOpen(Session session, @PathParam("key") String secretKey, IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId); if (iDevice == null) { logger.info("设备未连接,请检查!"); - session.close(); return; } AndroidDeviceBridgeTool.screen(iDevice, "abort"); From 5b003ffac4952e573f1a44e343f5593c2597d149 Mon Sep 17 00:00:00 2001 From: JayWenStar <1599603313@qq.com> Date: Sun, 19 Dec 2021 22:10:57 +0800 Subject: [PATCH 18/33] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=BF=9C=E6=8E=A7?= =?UTF-8?q?=E9=A2=91=E7=B9=81=E5=88=B7=E6=96=B0=E6=97=B6=EF=BC=8C=E5=81=B6?= =?UTF-8?q?=E5=B0=94=E5=87=BA=E7=8E=B0=E5=85=B3=E9=97=AD=E7=9A=84session?= =?UTF-8?q?=E8=BF=98=E5=9C=A8=E5=8F=91=E9=80=81=E6=B5=81=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sonic/agent/tests/android/OutputSocketThread.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java b/src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java index a5fc493b..c3359ccc 100644 --- a/src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java +++ b/src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java @@ -70,6 +70,9 @@ public void run() { byte[] oldBytes = new byte[0]; int count = 0; while (sendImg.isAlive()) { + if (session == null || !session.isOpen()) { + return; + } Queue dataQueue = sendImg.getDataQueue(); if (dataQueue.isEmpty()) { continue; @@ -169,11 +172,7 @@ public void run() { if (count % 4 == 0) { count = 0; oldBytes = finalBytes; - if (session.isOpen()) { - sendByte(session, finalBytes); - } else { - return; - } + sendByte(session, finalBytes); } } } From bee99f122a677ae2be67e0537085404042b35cab Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Sun, 19 Dec 2021 22:18:31 +0800 Subject: [PATCH 19/33] =?UTF-8?q?=E5=AE=8C=E5=96=84ios=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/automation/AndroidStepHandler.java | 3 +- .../agent/automation/IOSStepHandler.java | 4 + .../sonic/agent/netty/NettyClientHandler.java | 15 ++ .../java/com/sonic/agent/tests/IOSTests.java | 56 +++++ .../tests/android/AndroidRecordThread.java | 2 +- .../agent/tests/ios/IOSPerfDataThread.java | 35 +++ .../agent/tests/ios/IOSRecordThread.java | 77 +++++++ .../agent/tests/ios/IOSRunStepThread.java | 46 ++++ .../tests/ios/IOSTestTaskBootThread.java | 199 ++++++++++++++++++ 9 files changed, 434 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/sonic/agent/tests/ios/IOSPerfDataThread.java create mode 100644 src/main/java/com/sonic/agent/tests/ios/IOSRecordThread.java create mode 100644 src/main/java/com/sonic/agent/tests/ios/IOSRunStepThread.java create mode 100644 src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java diff --git a/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java b/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java index d5e25c5d..2d2f713f 100644 --- a/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java @@ -366,13 +366,12 @@ public void startRecord() { } /** - * @param udId * @return void * @author ZhouYiXun * @des 停止录像 * @date 2021/8/16 23:56 */ - public void stopRecord(String udId) { + public void stopRecord() { File recordDir = new File("test-output/record"); if (!recordDir.exists()) { recordDir.mkdirs(); diff --git a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java index 8a9c8724..bc6cac99 100644 --- a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java @@ -70,6 +70,10 @@ public void setTestMode(int caseId, int resultId, String udId, String type, Stri log.sessionId = sessionId; } + public void setGlobalParams(JSONObject jsonObject) { + globalParams = jsonObject; + } + public int startIOSDriver(String udId) throws InterruptedException, IOException { this.udId = udId; int wdaPort = TIDeviceTool.startWda(udId); diff --git a/src/main/java/com/sonic/agent/netty/NettyClientHandler.java b/src/main/java/com/sonic/agent/netty/NettyClientHandler.java index f91fcc02..586b258f 100644 --- a/src/main/java/com/sonic/agent/netty/NettyClientHandler.java +++ b/src/main/java/com/sonic/agent/netty/NettyClientHandler.java @@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject; import com.android.ddmlib.IDevice; import com.sonic.agent.automation.AndroidStepHandler; +import com.sonic.agent.automation.IOSStepHandler; import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool; import com.sonic.agent.bridge.ios.TIDeviceTool; import com.sonic.agent.interfaces.DeviceStatus; @@ -87,6 +88,20 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception } androidStepHandler.sendStatus(); } + if (jsonObject.getInteger("pf") == PlatformType.IOS) { + IOSStepHandler iosStepHandler = HandlerMap.getIOSMap().get(jsonObject.getString("sessionId")); + iosStepHandler.resetResultDetailStatus(); + iosStepHandler.setGlobalParams(jsonObject.getJSONObject("gp")); + List steps = jsonObject.getJSONArray("steps").toJavaList(JSONObject.class); + for (JSONObject step : steps) { + try { + iosStepHandler.runStep(step); + } catch (Throwable e) { + break; + } + } + iosStepHandler.sendStatus(); + } break; case "suite": List cases = jsonObject.getJSONArray("cases").toJavaList(JSONObject.class); diff --git a/src/main/java/com/sonic/agent/tests/IOSTests.java b/src/main/java/com/sonic/agent/tests/IOSTests.java index 59cf3b8c..01415c56 100644 --- a/src/main/java/com/sonic/agent/tests/IOSTests.java +++ b/src/main/java/com/sonic/agent/tests/IOSTests.java @@ -1,9 +1,65 @@ package com.sonic.agent.tests; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.sonic.agent.automation.IOSStepHandler; +import com.sonic.agent.bridge.ios.TIDeviceTool; +import com.sonic.agent.interfaces.DeviceStatus; +import com.sonic.agent.tests.ios.IOSTestTaskBootThread; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.ITestContext; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + /** * @author ZhouYiXun * @des iOS测试执行类 * @date 2021/8/25 20:51 */ public class IOSTests { + private final Logger logger = LoggerFactory.getLogger(IOSTests.class); + + @DataProvider(name = "testData", parallel = true) + public Object[][] getTestData(ITestContext context) { + JSONObject dataInfo = JSON.parseObject(context.getCurrentXmlTest().getParameter("dataInfo")); + List dataProvider = new ArrayList<>(); + for (JSONObject device : dataInfo.getJSONArray("device").toJavaList(JSONObject.class)) { + String udId = device.getString("udId"); + if (!TIDeviceTool.getDeviceList().contains(udId)) { + continue; + } + JSONObject deviceTestData = new JSONObject(); + deviceTestData.put("steps", dataInfo.getJSONArray("steps")); + deviceTestData.put("rid", dataInfo.getInteger("rid")); + deviceTestData.put("cid", dataInfo.getInteger("cid")); + deviceTestData.put("gp", dataInfo.getJSONObject("gp")); + deviceTestData.put("device", device); + dataProvider.add(deviceTestData); + } + Object[][] testDataProvider = new Object[dataProvider.size()][]; + for (int i = 0; i < dataProvider.size(); i++) { + testDataProvider[i] = new Object[]{dataProvider.get(i)}; + } + return testDataProvider; + } + + @Test(dataProvider = "testData") + public void run(JSONObject jsonObject) throws IOException { + IOSStepHandler iosStepHandler = new IOSStepHandler(); + int rid = jsonObject.getInteger("rid"); + int cid = jsonObject.getInteger("cid"); + String udId = jsonObject.getJSONObject("device").getString("udId"); + JSONObject gp = jsonObject.getJSONObject("gp"); + iosStepHandler.setGlobalParams(gp); + iosStepHandler.setTestMode(cid, rid, udId, DeviceStatus.TESTING, ""); + + // 启动任务 + IOSTestTaskBootThread bootThread = new IOSTestTaskBootThread(jsonObject, iosStepHandler); + TaskManager.startBootThread(bootThread); + } } diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidRecordThread.java b/src/main/java/com/sonic/agent/tests/android/AndroidRecordThread.java index 5cd33da6..3eae38bb 100644 --- a/src/main/java/com/sonic/agent/tests/android/AndroidRecordThread.java +++ b/src/main/java/com/sonic/agent/tests/android/AndroidRecordThread.java @@ -90,7 +90,7 @@ public void run() { //处理录像 if (isSupportRecord) { if (androidStepHandler.getStatus() == 3) { - androidStepHandler.stopRecord(udId); + androidStepHandler.stopRecord(); return; } else { androidStepHandler.getAndroidDriver().stopRecordingScreen(); diff --git a/src/main/java/com/sonic/agent/tests/ios/IOSPerfDataThread.java b/src/main/java/com/sonic/agent/tests/ios/IOSPerfDataThread.java new file mode 100644 index 00000000..b3993396 --- /dev/null +++ b/src/main/java/com/sonic/agent/tests/ios/IOSPerfDataThread.java @@ -0,0 +1,35 @@ +package com.sonic.agent.tests.ios; + +import com.sonic.agent.automation.AndroidStepHandler; +import com.sonic.agent.tests.android.AndroidRunStepThread; +import com.sonic.agent.tests.android.AndroidTestTaskBootThread; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 暂未开放 + */ +public class IOSPerfDataThread extends Thread { + + private final Logger log = LoggerFactory.getLogger(IOSPerfDataThread.class); + + public final static String IOS_PERF_DATA_TASK_PRE = "ios-perf-data-task-%s-%s-%s"; + + private final IOSTestTaskBootThread iosTestTaskBootThread; + + public IOSPerfDataThread(IOSTestTaskBootThread iosTestTaskBootThread) { + this.iosTestTaskBootThread = iosTestTaskBootThread; + + this.setDaemon(true); + this.setName(iosTestTaskBootThread.formatThreadName(IOS_PERF_DATA_TASK_PRE)); + } + + public IOSTestTaskBootThread getIosTestTaskBootThread() { + return iosTestTaskBootThread; + } + + @Override + public void run() { + return; + } +} diff --git a/src/main/java/com/sonic/agent/tests/ios/IOSRecordThread.java b/src/main/java/com/sonic/agent/tests/ios/IOSRecordThread.java new file mode 100644 index 00000000..f6b97d2b --- /dev/null +++ b/src/main/java/com/sonic/agent/tests/ios/IOSRecordThread.java @@ -0,0 +1,77 @@ +package com.sonic.agent.tests.ios; + +import com.android.ddmlib.IDevice; +import com.sonic.agent.automation.AndroidStepHandler; +import com.sonic.agent.automation.IOSStepHandler; +import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool; +import com.sonic.agent.cv.RecordHandler; +import com.sonic.agent.tests.android.AndroidRunStepThread; +import com.sonic.agent.tests.android.AndroidTestTaskBootThread; +import com.sonic.agent.tools.MiniCapTool; +import org.bytedeco.javacv.FrameRecorder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +public class IOSRecordThread extends Thread { + + private final Logger log = LoggerFactory.getLogger(IOSRecordThread.class); + + public final static String IOS_RECORD_TASK_PRE = "ios-record-task-%s-%s-%s"; + + private final IOSTestTaskBootThread iosTestTaskBootThread; + + public IOSRecordThread(IOSTestTaskBootThread iosTestTaskBootThread) { + this.iosTestTaskBootThread = iosTestTaskBootThread; + + this.setDaemon(true); + this.setName(iosTestTaskBootThread.formatThreadName(IOS_RECORD_TASK_PRE)); + } + + public IOSTestTaskBootThread getIosTestTaskBootThread() { + return iosTestTaskBootThread; + } + + @Override + public void run() { + IOSStepHandler iosStepHandler = iosTestTaskBootThread.getIosStepHandler(); + IOSRunStepThread runStepThread = iosTestTaskBootThread.getRunStepThread(); + + while (runStepThread.isAlive()) { + if (iosStepHandler.getDriver() == null) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + log.error(e.getMessage()); + } + continue; + } + try { + iosStepHandler.startRecord(); + } catch (Exception e) { + log.error(e.getMessage()); + } + int w = 0; + while (w < 10 && (runStepThread.isAlive())) { + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + log.error(e.getMessage()); + } + w++; + } + //处理录像 + if (iosStepHandler.getStatus() == 3) { + iosStepHandler.stopRecord(); + return; + } else { + iosStepHandler.getDriver().stopRecordingScreen(); + } + } + } +} diff --git a/src/main/java/com/sonic/agent/tests/ios/IOSRunStepThread.java b/src/main/java/com/sonic/agent/tests/ios/IOSRunStepThread.java new file mode 100644 index 00000000..976563f1 --- /dev/null +++ b/src/main/java/com/sonic/agent/tests/ios/IOSRunStepThread.java @@ -0,0 +1,46 @@ +package com.sonic.agent.tests.ios; + +import com.alibaba.fastjson.JSONObject; +import com.sonic.agent.automation.AndroidStepHandler; +import com.sonic.agent.automation.IOSStepHandler; +import com.sonic.agent.tests.android.AndroidTestTaskBootThread; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class IOSRunStepThread extends Thread { + + private final Logger log = LoggerFactory.getLogger(IOSRunStepThread.class); + + public final static String IOS_RUN_STEP_TASK_PRE = "ios-run-step-task-%s-%s-%s"; + + private final IOSTestTaskBootThread iosTestTaskBootThread; + + public IOSRunStepThread(IOSTestTaskBootThread iosTestTaskBootThread) { + this.iosTestTaskBootThread = iosTestTaskBootThread; + + this.setDaemon(true); + this.setName(iosTestTaskBootThread.formatThreadName(IOS_RUN_STEP_TASK_PRE)); + } + + public IOSTestTaskBootThread getIosTestTaskBootThread() { + return iosTestTaskBootThread; + } + + @Override + public void run() { + JSONObject jsonObject = iosTestTaskBootThread.getJsonObject(); + IOSStepHandler iosStepHandler = iosTestTaskBootThread.getIosStepHandler(); + List steps = jsonObject.getJSONArray("steps").toJavaList(JSONObject.class); + + for (JSONObject step : steps) { + try { + iosStepHandler.runStep(step); + } catch (Throwable e) { + break; + } + } + + } +} \ No newline at end of file diff --git a/src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java b/src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java new file mode 100644 index 00000000..dd2a1d1b --- /dev/null +++ b/src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java @@ -0,0 +1,199 @@ +package com.sonic.agent.tests.ios; + +import com.alibaba.fastjson.JSONObject; +import com.sonic.agent.automation.IOSStepHandler; +import com.sonic.agent.bridge.ios.IOSDeviceLocalStatus; +import com.sonic.agent.interfaces.ResultDetailStatus; +import com.sonic.agent.tests.TaskManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.Semaphore; + +public class IOSTestTaskBootThread extends Thread { + + private final Logger log = LoggerFactory.getLogger(IOSTestTaskBootThread.class); + + /** + * ios-test-task-boot-{resultId}-{caseId}-{udid} + */ + public final static String IOS_TEST_TASK_BOOT_PRE = "ios-test-task-boot-%s-%s-%s"; + + /** + * 控制不同线程执行的信号量 + */ + private Semaphore runStepSemaphore = new Semaphore(1); + + + /** + * 一些任务信息 + */ + private JSONObject jsonObject; + + private IOSStepHandler iosStepHandler; + + /** + * 测试步骤线程 + */ + private IOSRunStepThread runStepThread; + + /** + * 性能数据采集线程 + */ + private IOSPerfDataThread perfDataThread; + + /** + * 录像线程 + */ + private IOSRecordThread recordThread; + + /** + * 测试结果id 0表示debug线程 + */ + private int resultId = 0; + + /** + * 测试用例id 0表示debug线程 + */ + private int caseId = 0; + + /** + * 设备序列号 + */ + private String udId; + + public String formatThreadName(String baseFormat) { + return String.format(baseFormat, this.resultId, this.caseId, this.udId); + } + + /** + * debug线程构造 + */ + public IOSTestTaskBootThread() { + this.setName(this.formatThreadName(IOS_TEST_TASK_BOOT_PRE)); + this.setDaemon(true); + } + + /** + * 任务线程构造 + * + * @param jsonObject 任务数据 + * @param iosStepHandler ios步骤执行器 + */ + public IOSTestTaskBootThread(JSONObject jsonObject, IOSStepHandler iosStepHandler) { + this.iosStepHandler = iosStepHandler; + this.jsonObject = jsonObject; + this.resultId = jsonObject.getInteger("rid"); + this.caseId = jsonObject.getInteger("cid"); + this.udId = jsonObject.getJSONObject("device").getString("udId"); + + // 比如:test-task-thread-af80d1e4 + this.setName(String.format(IOS_TEST_TASK_BOOT_PRE, resultId, caseId, udId)); + this.setDaemon(true); + } + + public Semaphore getRunStepSemaphore() { + return runStepSemaphore; + } + + public JSONObject getJsonObject() { + return jsonObject; + } + + public IOSStepHandler getIosStepHandler() { + return iosStepHandler; + } + + public IOSRunStepThread getRunStepThread() { + return runStepThread; + } + + public IOSPerfDataThread getPerfDataThread() { + return perfDataThread; + } + + public IOSRecordThread getRecordThread() { + return recordThread; + } + + public int getResultId() { + return resultId; + } + + public int getCaseId() { + return caseId; + } + + public String getUdId() { + return udId; + } + + public IOSTestTaskBootThread setUdId(String udId) { + this.udId = udId; + return this; + } + + @Override + public void run() { + + boolean startTestSuccess = false; + + try { + int wait = 0; + while (!IOSDeviceLocalStatus.startTest(udId)) { + wait++; + iosStepHandler.waitDevice(wait); + if (wait >= 6 * 10) { + iosStepHandler.waitDeviceTimeOut(); + iosStepHandler.sendStatus(); + return; + } else { + Thread.sleep(10000); + } + } + + startTestSuccess = true; + //启动测试 + try { + iosStepHandler.startIOSDriver(udId); + } catch (Exception e) { + log.error(e.getMessage()); + iosStepHandler.closeIOSDriver(); + iosStepHandler.sendStatus(); + IOSDeviceLocalStatus.finishError(udId); + return; + } + + //电量过低退出测试 + if (iosStepHandler.getBattery()) { + iosStepHandler.closeIOSDriver(); + iosStepHandler.sendStatus(); + IOSDeviceLocalStatus.finish(udId); + return; + } + + //正常运行步骤的线程 + runStepThread = new IOSRunStepThread(this); + //性能数据获取线程 + perfDataThread = new IOSPerfDataThread(this); + //录像线程 + recordThread = new IOSRecordThread(this); + TaskManager.startChildThread(this.getName(), runStepThread, perfDataThread, recordThread); + + + //等待两个线程结束了才结束方法 + while ((recordThread.isAlive()) || (runStepThread.isAlive())) { + Thread.sleep(1000); + } + } catch (InterruptedException e) { + log.error("任务异常,中断:{}", e.getMessage()); + iosStepHandler.setResultDetailStatus(ResultDetailStatus.FAIL); + } finally { + if (startTestSuccess) { + IOSDeviceLocalStatus.finish(udId); + iosStepHandler.closeIOSDriver(); + } + iosStepHandler.sendStatus(); + } + } +} From e8c95230b25831d37059f873a6a56912c85f0329 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Sun, 19 Dec 2021 22:52:27 +0800 Subject: [PATCH 20/33] =?UTF-8?q?=E4=BF=9D=E5=AD=98suite=E5=92=8Cforce?= =?UTF-8?q?=E5=8A=A0=E5=85=A5ios=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sonic/agent/netty/NettyClientHandler.java | 10 +++- .../com/sonic/agent/tests/TaskManager.java | 26 +++++---- .../sonic/agent/websockets/IOSWSServer.java | 54 +++++++++---------- 3 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/sonic/agent/netty/NettyClientHandler.java b/src/main/java/com/sonic/agent/netty/NettyClientHandler.java index 586b258f..7808a12c 100644 --- a/src/main/java/com/sonic/agent/netty/NettyClientHandler.java +++ b/src/main/java/com/sonic/agent/netty/NettyClientHandler.java @@ -14,6 +14,7 @@ import com.sonic.agent.maps.AndroidPasswordMap; import com.sonic.agent.maps.HandlerMap; import com.sonic.agent.tests.AndroidTests; +import com.sonic.agent.tests.IOSTests; import com.sonic.agent.tests.TaskManager; import com.sonic.agent.tools.SpringTool; import io.netty.channel.Channel; @@ -114,7 +115,12 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception parameters.put("dataInfo", dataInfo.toJSONString()); xmlTest.setParameters(parameters); List classes = new ArrayList<>(); - classes.add(new XmlClass(AndroidTests.class)); + if (jsonObject.getInteger("pf") == PlatformType.ANDROID) { + classes.add(new XmlClass(AndroidTests.class)); + } + if (jsonObject.getInteger("pf") == PlatformType.IOS) { + classes.add(new XmlClass(IOSTests.class)); + } xmlTest.setXmlClasses(classes); } suiteList.add(xmlSuite); @@ -130,7 +136,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception List deviceList = devices.toJavaList(JSONObject.class); for (JSONObject device : deviceList) { String udId = (String) device.get("udId"); - TaskManager.forceStopSuite(resultId, caseId, udId); + TaskManager.forceStopSuite(jsonObject.getInteger("pf"), resultId, caseId, udId); } } break; diff --git a/src/main/java/com/sonic/agent/tests/TaskManager.java b/src/main/java/com/sonic/agent/tests/TaskManager.java index 4226f11b..987a02b3 100644 --- a/src/main/java/com/sonic/agent/tests/TaskManager.java +++ b/src/main/java/com/sonic/agent/tests/TaskManager.java @@ -1,6 +1,8 @@ package com.sonic.agent.tests; +import com.sonic.agent.interfaces.PlatformType; import com.sonic.agent.tests.android.AndroidTestTaskBootThread; +import com.sonic.agent.tests.ios.IOSTestTaskBootThread; import org.springframework.util.CollectionUtils; import java.util.HashSet; @@ -45,7 +47,7 @@ public static void startBootThread(Thread bootThread) { * * @param bootThreads boot线程 */ - public static void startBootThread(Thread...bootThreads) { + public static void startBootThread(Thread... bootThreads) { for (Thread bootThread : bootThreads) { startBootThread(bootThread); } @@ -62,7 +64,7 @@ public static void startChildThread(String key, Thread childThread) { /** * 启动子线程(批量) */ - public static void startChildThread(String key, Thread...childThreads) { + public static void startChildThread(String key, Thread... childThreads) { for (Thread childThread : childThreads) { startChildThread(key, childThread); } @@ -72,8 +74,8 @@ public static void startChildThread(String key, Thread...childThreads) { /** * 添加boot线程 * - * @param key 用boot线程名作为key - * @param bootThread boot线程 + * @param key 用boot线程名作为key + * @param bootThread boot线程 */ public static void addBootThread(String key, Thread bootThread) { clearTerminatedThread(); @@ -155,12 +157,18 @@ public static void clearTerminatedThread() { /** * 按照结果id、用例id、设备序列号强制停止手机正在执行的任务 * - * @param resultId 结果id - * @param caseId 用例id - * @param udid 设备序列号 + * @param resultId 结果id + * @param caseId 用例id + * @param udId 设备序列号 */ - public static void forceStopSuite(int resultId, int caseId, String udid) { - String key = String.format(AndroidTestTaskBootThread.ANDROID_TEST_TASK_BOOT_PRE, resultId, caseId, udid); + public static void forceStopSuite(int platform, int resultId, int caseId, String udId) { + String key = ""; + if (platform == PlatformType.ANDROID) { + key = String.format(AndroidTestTaskBootThread.ANDROID_TEST_TASK_BOOT_PRE, resultId, caseId, udId); + } + if (platform == PlatformType.IOS) { + key = String.format(IOSTestTaskBootThread.IOS_TEST_TASK_BOOT_PRE, resultId, caseId, udId); + } // 停止boot线程 Thread bootThread = bootThreadsMap.get(key); if (bootThread != null) { diff --git a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java b/src/main/java/com/sonic/agent/websockets/IOSWSServer.java index 3b5f4b3b..bca784ff 100644 --- a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/IOSWSServer.java @@ -160,23 +160,23 @@ public void onMessage(String message, Session session) throws InterruptedExcepti finalIOSStepHandler.siriCommand(new HandleDes(), msg.getString("command")); }); } -// if (msg.getString("detail").equals("install")) { -// androidStepHandler = HandlerMap.getAndroidMap().get(session.getId()); -// AndroidStepHandler finalAndroidStepHandler = androidStepHandler; -// AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { -// JSONObject result = new JSONObject(); -// result.put("msg", "installFinish"); -// HandleDes handleDes = new HandleDes(); -// finalAndroidStepHandler.install(handleDes, msg.getString("apk")); -// if (handleDes.getE() == null) { -// result.put("status", "success"); -// } else { -// System.out.println(handleDes.getE()); -// result.put("status", "fail"); -// } -// sendText(session, result.toJSONString()); -// }); -// } + if (msg.getString("detail").equals("install")) { + iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); + IOSStepHandler finalIosStepHandler = iosStepHandler; + IOSDeviceThreadPool.cachedThreadPool.execute(() -> { + JSONObject result = new JSONObject(); + result.put("msg", "installFinish"); + HandleDes handleDes = new HandleDes(); + finalIosStepHandler.install(handleDes, msg.getString("ipa")); + if (handleDes.getE() == null) { + result.put("status", "success"); + } else { + System.out.println(handleDes.getE()); + result.put("status", "fail"); + } + sendText(session, result.toJSONString()); + }); + } if (msg.getString("detail").equals("tree")) { iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); IOSStepHandler finalIOSStepHandler = iosStepHandler; @@ -217,16 +217,16 @@ public void onMessage(String message, Session session) throws InterruptedExcepti sendText(session, result.toJSONString()); }); } -// if (msg.getString("detail").equals("runStep")) { -// JSONObject jsonDebug = new JSONObject(); -// jsonDebug.put("msg", "findSteps"); -// jsonDebug.put("key", key); -// jsonDebug.put("udId", udIdMap.get(session).getSerialNumber()); -// jsonDebug.put("pwd", msg.getString("pwd")); -// jsonDebug.put("sessionId", session.getId()); -// jsonDebug.put("caseId", msg.getInteger("caseId")); -// NettyThreadPool.send(jsonDebug); -// } + if (msg.getString("detail").equals("runStep")) { + JSONObject jsonDebug = new JSONObject(); + jsonDebug.put("msg", "findSteps"); + jsonDebug.put("key", key); + jsonDebug.put("udId", udIdMap.get(session)); + jsonDebug.put("pwd", msg.getString("pwd")); + jsonDebug.put("sessionId", session.getId()); + jsonDebug.put("caseId", msg.getInteger("caseId")); + NettyThreadPool.send(jsonDebug); + } break; } } From f3b39f2fe4bca07f54a4d7824f112f212874cca1 Mon Sep 17 00:00:00 2001 From: JayWenStar <1599603313@qq.com> Date: Mon, 20 Dec 2021 00:34:11 +0800 Subject: [PATCH 21/33] =?UTF-8?q?=E2=AD=90=EF=B8=8F=EF=BC=9AIOS=E8=BF=9C?= =?UTF-8?q?=E6=8E=A7=E9=94=81=20&=20NettyClient=E5=A2=9E=E5=8A=A0=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sonic/agent/netty/NettyClient.java | 4 +++- .../agent/websockets/AndroidWSServer.java | 4 ++-- .../sonic/agent/websockets/IOSWSServer.java | 19 ++++++++++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/sonic/agent/netty/NettyClient.java b/src/main/java/com/sonic/agent/netty/NettyClient.java index 115a6a4f..2e216124 100644 --- a/src/main/java/com/sonic/agent/netty/NettyClient.java +++ b/src/main/java/com/sonic/agent/netty/NettyClient.java @@ -5,6 +5,7 @@ import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.util.concurrent.DefaultThreadFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -36,7 +37,8 @@ public class NettyClient implements ApplicationRunner { @Override public void run(ApplicationArguments args) { // todo 根据 https://netty.io/wiki/native-transports.html 可针对不同系统进行优化,server端的netty同理 - group = new NioEventLoopGroup(); + DefaultThreadFactory factory = new DefaultThreadFactory("AgentNettyClient", true); + group = new NioEventLoopGroup(factory); bootstrap = new Bootstrap() .group(group) .option(ChannelOption.TCP_NODELAY, true) diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index a69ff6eb..8e006eae 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -74,7 +74,7 @@ public void onOpen(Session session, @PathParam("key") String secretKey, logger.info("30s内获取设备锁失败,请确保设备无人使用"); return; } - logger.info("上锁udId:{}", udId); + logger.info("android上锁udId:{}", udId); JSONObject jsonDebug = new JSONObject(); jsonDebug.put("msg", "debugUser"); @@ -321,7 +321,7 @@ public void onClose(Session session) { exit(session); } finally { DevicesLockMap.unlockAndRemoveByUdId(udId); - logger.info("解锁udId:{}", udId); + logger.info("android解锁udId:{}", udId); } } diff --git a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java b/src/main/java/com/sonic/agent/websockets/IOSWSServer.java index bca784ff..e5ccafb9 100644 --- a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/IOSWSServer.java @@ -8,6 +8,7 @@ import com.sonic.agent.bridge.ios.IOSDeviceThreadPool; import com.sonic.agent.bridge.ios.TIDeviceTool; import com.sonic.agent.interfaces.DeviceStatus; +import com.sonic.agent.maps.DevicesLockMap; import com.sonic.agent.maps.HandlerMap; import com.sonic.agent.maps.WebSocketSessionMap; import com.sonic.agent.netty.NettyThreadPool; @@ -28,6 +29,7 @@ import java.time.Duration; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; @Component @ServerEndpoint(value = "/websockets/ios/{key}/{udId}/{token}", configurator = MyEndpointConfigure.class) @@ -44,6 +46,15 @@ public void onOpen(Session session, @PathParam("key") String secretKey, logger.info("拦截访问!"); return; } + + session.getUserProperties().put("udId", udId); + boolean lockSuccess = DevicesLockMap.lockByUdId(udId, 30L, TimeUnit.SECONDS); + if (!lockSuccess) { + logger.info("30s内获取设备锁失败,请确保设备无人使用"); + return; + } + logger.info("ios上锁udId:{}", udId); + JSONObject jsonDebug = new JSONObject(); jsonDebug.put("msg", "debugUser"); jsonDebug.put("token", token); @@ -86,7 +97,13 @@ public void onOpen(Session session, @PathParam("key") String secretKey, @OnClose public void onClose(Session session) { - exit(session); + String udId = (String) session.getUserProperties().get("udId"); + try { + exit(session); + } finally { + DevicesLockMap.unlockAndRemoveByUdId(udId); + logger.info("ios解锁udId:{}", udId); + } } @OnError From 73254fdddc4812df4147030662806bd6e59ca846 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Mon, 20 Dec 2021 20:09:53 +0800 Subject: [PATCH 22/33] =?UTF-8?q?=E4=BF=9D=E5=AD=98showxcodelogfalse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/sonic/agent/automation/IOSStepHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java index bc6cac99..c3390326 100644 --- a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java @@ -91,7 +91,7 @@ public int startIOSDriver(String udId) throws InterruptedException, IOException desiredCapabilities.setCapability("useXctestrunFile", false); desiredCapabilities.setCapability("mjpegServerPort", imgPort); //bug? - desiredCapabilities.setCapability(IOSMobileCapabilityType.SHOW_XCODE_LOG, true); + desiredCapabilities.setCapability(IOSMobileCapabilityType.SHOW_XCODE_LOG, false); desiredCapabilities.setCapability(IOSMobileCapabilityType.USE_PREBUILT_WDA, true); try { iosDriver = new IOSDriver(AppiumServer.service.getUrl(), desiredCapabilities); From 0799ff03c62f64534689a9dd27e6f81edf56b6f7 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Tue, 21 Dec 2021 00:07:31 +0800 Subject: [PATCH 23/33] =?UTF-8?q?=E5=8E=BB=E6=8E=89ios=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E4=BC=A0=E8=BE=93=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/sonic/agent/websockets/IOSWSServer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java b/src/main/java/com/sonic/agent/websockets/IOSWSServer.java index e5ccafb9..dc3207a5 100644 --- a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/IOSWSServer.java @@ -239,7 +239,6 @@ public void onMessage(String message, Session session) throws InterruptedExcepti jsonDebug.put("msg", "findSteps"); jsonDebug.put("key", key); jsonDebug.put("udId", udIdMap.get(session)); - jsonDebug.put("pwd", msg.getString("pwd")); jsonDebug.put("sessionId", session.getId()); jsonDebug.put("caseId", msg.getInteger("caseId")); NettyThreadPool.send(jsonDebug); From e6272b6a1aaee0122077fc3d4154899d0c6a37d0 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Tue, 21 Dec 2021 00:28:24 +0800 Subject: [PATCH 24/33] =?UTF-8?q?=E6=B8=A9=E5=BA=A6=E7=BA=BF=E7=A8=8Bdemo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/AndroidDeviceBridgeTool.java | 2 ++ .../tests/android/AndroidTemperThread.java | 20 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java index a95e2cb4..a8515531 100644 --- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java +++ b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java @@ -1,6 +1,7 @@ package com.sonic.agent.bridge.android; import com.android.ddmlib.*; +import com.sonic.agent.tests.android.AndroidTemperThread; import com.sonic.agent.tools.DownImageTool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -85,6 +86,7 @@ public void init() { break; } } + new AndroidTemperThread().start(); } /** diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java b/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java index 4f62d6ac..38496d51 100644 --- a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java +++ b/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java @@ -5,12 +5,24 @@ import java.util.List; -public class AndroidTemperThread extends Thread{ +public class AndroidTemperThread extends Thread { @Override public void run() { - IDevice[] deviceList = AndroidDeviceBridgeTool.getRealOnLineDevices(); - for(IDevice iDevice:deviceList){ - AndroidDeviceBridgeTool.executeCommand(iDevice,"dumpsys battery"); + while (true) { + IDevice[] deviceList = AndroidDeviceBridgeTool.getRealOnLineDevices(); + for (IDevice iDevice : deviceList) { + String temper = AndroidDeviceBridgeTool + .executeCommand(iDevice, "dumpsys battery") + .trim(); + String real = temper.substring(temper.indexOf("temperature")); + float total = (float) Integer.parseInt(real.substring(13, real.indexOf("\n"))) / 10; + System.out.println(iDevice.getSerialNumber() + "当前温度:" + total + "摄氏度"); + } + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } } } } From 3446d7c6c311a3b57934d94cccc00d3ef2440dec Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Wed, 22 Dec 2021 20:42:46 +0800 Subject: [PATCH 25/33] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dadbkit=E5=9C=A8mac?= =?UTF-8?q?=E5=A4=B1=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sonic/agent/tools/ProcessCommandTool.java | 7 ++++--- .../java/com/sonic/agent/websockets/AndroidWSServer.java | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/sonic/agent/tools/ProcessCommandTool.java b/src/main/java/com/sonic/agent/tools/ProcessCommandTool.java index b2ffa451..bd218727 100644 --- a/src/main/java/com/sonic/agent/tools/ProcessCommandTool.java +++ b/src/main/java/com/sonic/agent/tools/ProcessCommandTool.java @@ -17,10 +17,11 @@ public static List getProcessLocalCommand(String commandLine) { List sdrResult = new ArrayList(); List sdrErrorResult = new ArrayList(); try { - if (System.getProperty("os.name").contains("Mac")) { - process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", commandLine}); - } else { + String system = System.getProperty("os.name").toLowerCase(); + if (system.contains("win")) { process = Runtime.getRuntime().exec(new String[]{"cmd", "/C", commandLine}); + } else { + process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", commandLine}); } inputStreamReader = new InputStreamReader(process.getInputStream()); consoleInput = new LineNumberReader(inputStreamReader); diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index 8e006eae..80bc60ef 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -212,7 +212,7 @@ public boolean isCancelled() { e.printStackTrace(); } // 超时就不继续等了,保证其它服务可运行 - if (wait > 18) { + if (wait > 20) { return; } } @@ -266,11 +266,12 @@ public boolean isCancelled() { String system = System.getProperty("os.name").toLowerCase(); Process ps = null; int port = PortTool.getPort(); + String command = String.format("adbkit usb-device-to-tcp -p %d %s", port, udId); if (system.contains("win")) { - ps = Runtime.getRuntime().exec(String.format("cmd /c adbkit usb-device-to-tcp -p %d %s", port, udId)); + ps = Runtime.getRuntime().exec(new String[]{"cmd", "/c", command}); } if (system.contains("linux") || system.contains("mac")) { - ps = Runtime.getRuntime().exec(String.format("sh -c adbkit usb-device-to-tcp -p %d %s", port, udId)); + ps = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", command}); } GlobalProcessMap.getMap().put(processName, ps); JSONObject adbkit = new JSONObject(); From 34edc0a4805380668d8e3c4583f6f4a7231bb695 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Wed, 22 Dec 2021 22:11:14 +0800 Subject: [PATCH 26/33] =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=B8=A9=E5=BA=A6?= =?UTF-8?q?=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/AndroidDeviceBridgeTool.java | 2 +- .../sonic/agent/netty/NettyClientHandler.java | 1 - .../tests/android/AndroidTemperThread.java | 26 ++++++++++++++----- src/main/resources/application-dev.yml | 4 +-- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java index a8515531..9deca46b 100644 --- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java +++ b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java @@ -27,7 +27,7 @@ @Component public class AndroidDeviceBridgeTool implements ApplicationListener { private static final Logger logger = LoggerFactory.getLogger(AndroidDeviceBridgeTool.class); - private static AndroidDebugBridge androidDebugBridge = null; + public static AndroidDebugBridge androidDebugBridge = null; @Autowired private AndroidDeviceStatusListener androidDeviceStatusListener; diff --git a/src/main/java/com/sonic/agent/netty/NettyClientHandler.java b/src/main/java/com/sonic/agent/netty/NettyClientHandler.java index 7808a12c..5d483705 100644 --- a/src/main/java/com/sonic/agent/netty/NettyClientHandler.java +++ b/src/main/java/com/sonic/agent/netty/NettyClientHandler.java @@ -147,7 +147,6 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { logger.info("服务器: {} 发生异常 {}", ctx.channel().remoteAddress(), cause.fillInStackTrace()); - ctx.close(); } @Override diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java b/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java index 38496d51..4ed375a7 100644 --- a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java +++ b/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java @@ -1,25 +1,37 @@ package com.sonic.agent.tests.android; +import com.alibaba.fastjson.JSONObject; import com.android.ddmlib.IDevice; import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool; +import com.sonic.agent.netty.NettyThreadPool; +import java.util.ArrayList; import java.util.List; public class AndroidTemperThread extends Thread { @Override public void run() { - while (true) { + while (AndroidDeviceBridgeTool.androidDebugBridge != null) { IDevice[] deviceList = AndroidDeviceBridgeTool.getRealOnLineDevices(); + List detail = new ArrayList<>(); for (IDevice iDevice : deviceList) { + JSONObject jsonObject = new JSONObject(); String temper = AndroidDeviceBridgeTool - .executeCommand(iDevice, "dumpsys battery") - .trim(); - String real = temper.substring(temper.indexOf("temperature")); - float total = (float) Integer.parseInt(real.substring(13, real.indexOf("\n"))) / 10; - System.out.println(iDevice.getSerialNumber() + "当前温度:" + total + "摄氏度"); + .executeCommand(iDevice, "dumpsys battery"); + if (temper != null && temper.length() > 0) { + String real = temper.substring(temper.indexOf("temperature")).trim(); + int total = Integer.parseInt(real.substring(13, real.indexOf("\n"))); + jsonObject.put("udId", iDevice.getSerialNumber()); + jsonObject.put("tem", total); + detail.add(jsonObject); + } } + JSONObject result = new JSONObject(); + result.put("msg", "temperature"); + result.put("detail", detail); + NettyThreadPool.send(result); try { - Thread.sleep(5000); + Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 94db2d2c..355813ec 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,10 +1,10 @@ sonic: agent: - host: 172.25.128.1 + host: 192.168.1.10 port: 7777 key: 29002272-4659-4808-a804-08ce3388b136 server: - host: 172.25.128.1 + host: 192.168.1.10 folder-port: 8094 transport-port: 8095 From 18c0d58df8fcc2b54469166d22587ec86c571fe2 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Thu, 23 Dec 2021 00:41:10 +0800 Subject: [PATCH 27/33] =?UTF-8?q?=E4=BF=AE=E5=A4=8DiOS=E4=B8=8D=E8=83=BDwi?= =?UTF-8?q?n=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/automation/IOSStepHandler.java | 6 ++-- .../sonic/agent/bridge/ios/TIDeviceTool.java | 28 ++++++++++--------- .../sonic/agent/tools/ProcessCommandTool.java | 4 +-- .../agent/websockets/AndroidWSServer.java | 5 ++-- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java index c3390326..461ac7d5 100644 --- a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java @@ -89,10 +89,10 @@ public int startIOSDriver(String udId) throws InterruptedException, IOException desiredCapabilities.setCapability("wdaConnectionTimeout", 60000); desiredCapabilities.setCapability(IOSMobileCapabilityType.WEB_DRIVER_AGENT_URL, "http://127.0.0.1:" + wdaPort); desiredCapabilities.setCapability("useXctestrunFile", false); - desiredCapabilities.setCapability("mjpegServerPort", imgPort); - //bug? + desiredCapabilities.setCapability(IOSMobileCapabilityType.SHOW_IOS_LOG, false); desiredCapabilities.setCapability(IOSMobileCapabilityType.SHOW_XCODE_LOG, false); - desiredCapabilities.setCapability(IOSMobileCapabilityType.USE_PREBUILT_WDA, true); + desiredCapabilities.setCapability("skipLogCapture", true); + desiredCapabilities.setCapability(IOSMobileCapabilityType.USE_PREBUILT_WDA, false); try { iosDriver = new IOSDriver(AppiumServer.service.getUrl(), desiredCapabilities); iosDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); diff --git a/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java b/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java index ef1aead7..71048dab 100644 --- a/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java +++ b/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java @@ -160,21 +160,22 @@ public static int startWda(String udId) throws IOException, InterruptedException } } int port = PortTool.getPort(); - Process wdaProcess; + Process wdaProcess = null; String commandLine = "tidevice -u " + udId + " wdaproxy" + " -B " + bundleId + " --port " + port; - if (System.getProperty("os.name").contains("Mac")) { - wdaProcess = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", commandLine}); - } else { - wdaProcess = Runtime.getRuntime().exec(new String[]{"cmd", "/C", commandLine}); + String system = System.getProperty("os.name").toLowerCase(); + if (system.contains("win")) { + wdaProcess = Runtime.getRuntime().exec(new String[]{"cmd", "/c", commandLine}); + } else if (system.contains("linux") || system.contains("mac")) { + wdaProcess = Runtime.getRuntime().exec(new String[]{"sh", "-c", commandLine}); } - + Process finalWdaProcess = wdaProcess; new Thread(() -> { BufferedReader stdInput = new BufferedReader(new - InputStreamReader(wdaProcess.getInputStream())); + InputStreamReader(finalWdaProcess.getInputStream())); String s = null; - while (wdaProcess.isAlive()) { + while (finalWdaProcess.isAlive()) { try { if (!((s = stdInput.readLine()) != null)) break; } catch (IOException e) { @@ -202,13 +203,14 @@ public static int startWda(String udId) throws IOException, InterruptedException public static int relayImg(String udId) throws IOException { int port = PortTool.getPort(); - Process relayProcess; + Process relayProcess = null; String commandLine = "tidevice -u " + udId + " relay " + port + " " + 9100; - if (System.getProperty("os.name").contains("Mac")) { - relayProcess = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", commandLine}); - } else { - relayProcess = Runtime.getRuntime().exec(new String[]{"cmd", "/C", commandLine}); + String system = System.getProperty("os.name").toLowerCase(); + if (system.contains("win")) { + relayProcess = Runtime.getRuntime().exec(new String[]{"cmd", "/c", commandLine}); + } else if (system.contains("linux") || system.contains("mac")) { + relayProcess = Runtime.getRuntime().exec(new String[]{"sh", "-c", commandLine}); } List processList; if (IOSProcessMap.getMap().get(udId) != null) { diff --git a/src/main/java/com/sonic/agent/tools/ProcessCommandTool.java b/src/main/java/com/sonic/agent/tools/ProcessCommandTool.java index bd218727..c39ae265 100644 --- a/src/main/java/com/sonic/agent/tools/ProcessCommandTool.java +++ b/src/main/java/com/sonic/agent/tools/ProcessCommandTool.java @@ -19,9 +19,9 @@ public static List getProcessLocalCommand(String commandLine) { try { String system = System.getProperty("os.name").toLowerCase(); if (system.contains("win")) { - process = Runtime.getRuntime().exec(new String[]{"cmd", "/C", commandLine}); + process = Runtime.getRuntime().exec(new String[]{"cmd", "/c", commandLine}); } else { - process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", commandLine}); + process = Runtime.getRuntime().exec(new String[]{"sh", "-c", commandLine}); } inputStreamReader = new InputStreamReader(process.getInputStream()); consoleInput = new LineNumberReader(inputStreamReader); diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index 80bc60ef..345392c9 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -269,9 +269,8 @@ public boolean isCancelled() { String command = String.format("adbkit usb-device-to-tcp -p %d %s", port, udId); if (system.contains("win")) { ps = Runtime.getRuntime().exec(new String[]{"cmd", "/c", command}); - } - if (system.contains("linux") || system.contains("mac")) { - ps = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", command}); + } else if (system.contains("linux") || system.contains("mac")) { + ps = Runtime.getRuntime().exec(new String[]{"sh", "-c", command}); } GlobalProcessMap.getMap().put(processName, ps); JSONObject adbkit = new JSONObject(); From d50fcb51ddf01c1106b4bef512c631a0bf057816 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Thu, 23 Dec 2021 20:26:20 +0800 Subject: [PATCH 28/33] =?UTF-8?q?=E4=BF=9D=E5=AD=98ios=E8=BF=9C=E6=8E=A7?= =?UTF-8?q?=E9=80=9F=E5=BA=A6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/automation/IOSStepHandler.java | 5 +- .../sonic/agent/bridge/ios/TIDeviceTool.java | 36 +-- .../tests/ios/IOSTestTaskBootThread.java | 8 +- .../agent/websockets/AndroidWSServer.java | 174 +++++++------- .../sonic/agent/websockets/IOSWSServer.java | 226 +++++++++--------- 5 files changed, 222 insertions(+), 227 deletions(-) diff --git a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java index 461ac7d5..91742b1f 100644 --- a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/IOSStepHandler.java @@ -74,10 +74,8 @@ public void setGlobalParams(JSONObject jsonObject) { globalParams = jsonObject; } - public int startIOSDriver(String udId) throws InterruptedException, IOException { + public void startIOSDriver(String udId, int wdaPort) throws InterruptedException, IOException { this.udId = udId; - int wdaPort = TIDeviceTool.startWda(udId); - int imgPort = TIDeviceTool.relayImg(udId); Thread.sleep(2000); DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, Platform.IOS); @@ -107,7 +105,6 @@ public int startIOSDriver(String udId) throws InterruptedException, IOException int width = iosDriver.manage().window().getSize().width; int height = iosDriver.manage().window().getSize().height; IOSSizeMap.getMap().put(udId, width + "x" + height); - return imgPort; } public void closeIOSDriver() { diff --git a/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java b/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java index 71048dab..c6fbd876 100644 --- a/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java +++ b/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java @@ -170,30 +170,19 @@ public static int startWda(String udId) throws IOException, InterruptedException } else if (system.contains("linux") || system.contains("mac")) { wdaProcess = Runtime.getRuntime().exec(new String[]{"sh", "-c", commandLine}); } - Process finalWdaProcess = wdaProcess; - new Thread(() -> { - BufferedReader stdInput = new BufferedReader(new - InputStreamReader(finalWdaProcess.getInputStream())); - String s = null; - while (finalWdaProcess.isAlive()) { - try { - if (!((s = stdInput.readLine()) != null)) break; - } catch (IOException e) { - e.printStackTrace(); + BufferedReader stdInput = new BufferedReader(new + InputStreamReader(wdaProcess.getInputStream())); + String s; + while (wdaProcess.isAlive()) { + if ((s = stdInput.readLine()) != null) { + if (s.contains("WebDriverAgent start successfully")) { + break; } - logger.info(s); + } else { + Thread.sleep(500); } - }).start(); -// String s; -// while ((s = stdInput.readLine()) != null) { -// if (s.contains("WebDriverAgent start successfully")) { -// logger.info(udId + " wda启动完毕!"); -// break; -// } else { -// Thread.sleep(500); -// } -// } - Thread.sleep(3000); + logger.info(s); + } processList = new ArrayList<>(); processList.add(wdaProcess); IOSProcessMap.getMap().put(udId, processList); @@ -201,7 +190,7 @@ public static int startWda(String udId) throws IOException, InterruptedException } } - public static int relayImg(String udId) throws IOException { + public static int relayImg(String udId) throws IOException, InterruptedException { int port = PortTool.getPort(); Process relayProcess = null; String commandLine = "tidevice -u " + udId + @@ -220,6 +209,7 @@ public static int relayImg(String udId) throws IOException { } processList.add(relayProcess); IOSProcessMap.getMap().put(udId, processList); + Thread.sleep(1000); return port; } diff --git a/src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java b/src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java index dd2a1d1b..5861e17e 100644 --- a/src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java +++ b/src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSONObject; import com.sonic.agent.automation.IOSStepHandler; import com.sonic.agent.bridge.ios.IOSDeviceLocalStatus; +import com.sonic.agent.bridge.ios.TIDeviceTool; import com.sonic.agent.interfaces.ResultDetailStatus; import com.sonic.agent.tests.TaskManager; import org.slf4j.Logger; @@ -77,8 +78,8 @@ public IOSTestTaskBootThread() { /** * 任务线程构造 * - * @param jsonObject 任务数据 - * @param iosStepHandler ios步骤执行器 + * @param jsonObject 任务数据 + * @param iosStepHandler ios步骤执行器 */ public IOSTestTaskBootThread(JSONObject jsonObject, IOSStepHandler iosStepHandler) { this.iosStepHandler = iosStepHandler; @@ -155,7 +156,8 @@ public void run() { startTestSuccess = true; //启动测试 try { - iosStepHandler.startIOSDriver(udId); + int wdaPort = TIDeviceTool.startWda(udId); + iosStepHandler.startIOSDriver(udId, wdaPort); } catch (Exception e) { log.error(e.getMessage()); iosStepHandler.closeIOSDriver(); diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index 345392c9..050c343a 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -461,92 +461,6 @@ public void onMessage(String message, Session session) throws InterruptedExcepti AndroidDeviceBridgeTool.pressKey(udIdMap.get(session), msg.getInteger("detail")); break; case "debug": - AndroidStepHandler androidStepHandler = HandlerMap.getAndroidMap().get(session.getId()); - try { - if (msg.getString("detail").equals("tap")) { - String xy = msg.getString("point"); - int x = Integer.parseInt(xy.substring(0, xy.indexOf(","))); - int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1)); - AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input tap " + x + " " + y); - } - if (msg.getString("detail").equals("longPress")) { - String xy = msg.getString("point"); - int x = Integer.parseInt(xy.substring(0, xy.indexOf(","))); - int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1)); - AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input swipe " + x + " " + y + " " + x + " " + y + " 1500"); - } - if (msg.getString("detail").equals("swipe")) { - String xy1 = msg.getString("pointA"); - String xy2 = msg.getString("pointB"); - int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(","))); - int y1 = Integer.parseInt(xy1.substring(xy1.indexOf(",") + 1)); - int x2 = Integer.parseInt(xy2.substring(0, xy2.indexOf(","))); - int y2 = Integer.parseInt(xy2.substring(xy2.indexOf(",") + 1)); - AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " 200"); - } - } catch (Exception e) { - e.printStackTrace(); - } - if (msg.getString("detail").equals("install")) { - AndroidStepHandler finalAndroidStepHandler = androidStepHandler; - AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { - JSONObject result = new JSONObject(); - result.put("msg", "installFinish"); - HandleDes handleDes = new HandleDes(); - finalAndroidStepHandler.install(handleDes, msg.getString("apk")); - if (handleDes.getE() == null) { - result.put("status", "success"); - } else { - System.out.println(handleDes.getE()); - result.put("status", "fail"); - } - sendText(session, result.toJSONString()); - }); - } - if (msg.getString("detail").equals("tree")) { - androidStepHandler = HandlerMap.getAndroidMap().get(session.getId()); - AndroidStepHandler finalAndroidStepHandler = androidStepHandler; - AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { - try { - JSONObject result = new JSONObject(); - result.put("msg", "tree"); - result.put("detail", finalAndroidStepHandler.getResource()); - HandleDes handleDes = new HandleDes(); - if (!msg.getBoolean("hasScreen")) { - result.put("img", finalAndroidStepHandler.stepScreen(handleDes)); - } - if (handleDes.getE() != null) { - logger.error(handleDes.getE().getMessage()); - JSONObject resultFail = new JSONObject(); - resultFail.put("msg", "treeFail"); - sendText(session, resultFail.toJSONString()); - } else { - result.put("webView", finalAndroidStepHandler.getWebView()); - result.put("activity", finalAndroidStepHandler.getCurrentActivity()); - sendText(session, result.toJSONString()); - } - } catch (Throwable e) { - logger.error(e.getMessage()); - JSONObject result = new JSONObject(); - result.put("msg", "treeFail"); - sendText(session, result.toJSONString()); - } - }); - } - if (msg.getString("detail").equals("eleScreen")) { - androidStepHandler = HandlerMap.getAndroidMap().get(session.getId()); - AndroidStepHandler finalAndroidStepHandler = androidStepHandler; - AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { - JSONObject result = new JSONObject(); - result.put("msg", "eleScreen"); - try { - result.put("img", UploadTools.upload(finalAndroidStepHandler.findEle("xpath", msg.getString("xpath")).getScreenshotAs(OutputType.FILE), "keepFiles")); - } catch (Exception e) { - result.put("errMsg", "获取元素截图失败!"); - } - sendText(session, result.toJSONString()); - }); - } if (msg.getString("detail").equals("runStep")) { JSONObject jsonDebug = new JSONObject(); jsonDebug.put("msg", "findSteps"); @@ -556,6 +470,94 @@ public void onMessage(String message, Session session) throws InterruptedExcepti jsonDebug.put("sessionId", session.getId()); jsonDebug.put("caseId", msg.getInteger("caseId")); NettyThreadPool.send(jsonDebug); + } else { + AndroidStepHandler androidStepHandler = HandlerMap.getAndroidMap().get(session.getId()); + if (androidStepHandler == null || androidStepHandler.getAndroidDriver() == null) { + break; + } + try { + if (msg.getString("detail").equals("tap")) { + String xy = msg.getString("point"); + int x = Integer.parseInt(xy.substring(0, xy.indexOf(","))); + int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1)); + AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input tap " + x + " " + y); + } + if (msg.getString("detail").equals("longPress")) { + String xy = msg.getString("point"); + int x = Integer.parseInt(xy.substring(0, xy.indexOf(","))); + int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1)); + AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input swipe " + x + " " + y + " " + x + " " + y + " 1500"); + } + if (msg.getString("detail").equals("swipe")) { + String xy1 = msg.getString("pointA"); + String xy2 = msg.getString("pointB"); + int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(","))); + int y1 = Integer.parseInt(xy1.substring(xy1.indexOf(",") + 1)); + int x2 = Integer.parseInt(xy2.substring(0, xy2.indexOf(","))); + int y2 = Integer.parseInt(xy2.substring(xy2.indexOf(",") + 1)); + AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " 200"); + } + } catch (Exception e) { + e.printStackTrace(); + } + if (msg.getString("detail").equals("install")) { + AndroidStepHandler finalAndroidStepHandler = androidStepHandler; + AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { + JSONObject result = new JSONObject(); + result.put("msg", "installFinish"); + HandleDes handleDes = new HandleDes(); + finalAndroidStepHandler.install(handleDes, msg.getString("apk")); + if (handleDes.getE() == null) { + result.put("status", "success"); + } else { + System.out.println(handleDes.getE()); + result.put("status", "fail"); + } + sendText(session, result.toJSONString()); + }); + } + if (msg.getString("detail").equals("tree")) { + AndroidStepHandler finalAndroidStepHandler = androidStepHandler; + AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { + try { + JSONObject result = new JSONObject(); + result.put("msg", "tree"); + result.put("detail", finalAndroidStepHandler.getResource()); + HandleDes handleDes = new HandleDes(); + if (!msg.getBoolean("hasScreen")) { + result.put("img", finalAndroidStepHandler.stepScreen(handleDes)); + } + if (handleDes.getE() != null) { + logger.error(handleDes.getE().getMessage()); + JSONObject resultFail = new JSONObject(); + resultFail.put("msg", "treeFail"); + sendText(session, resultFail.toJSONString()); + } else { + result.put("webView", finalAndroidStepHandler.getWebView()); + result.put("activity", finalAndroidStepHandler.getCurrentActivity()); + sendText(session, result.toJSONString()); + } + } catch (Throwable e) { + logger.error(e.getMessage()); + JSONObject result = new JSONObject(); + result.put("msg", "treeFail"); + sendText(session, result.toJSONString()); + } + }); + } + if (msg.getString("detail").equals("eleScreen")) { + AndroidStepHandler finalAndroidStepHandler = androidStepHandler; + AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { + JSONObject result = new JSONObject(); + result.put("msg", "eleScreen"); + try { + result.put("img", UploadTools.upload(finalAndroidStepHandler.findEle("xpath", msg.getString("xpath")).getScreenshotAs(OutputType.FILE), "keepFiles")); + } catch (Exception e) { + result.put("errMsg", "获取元素截图失败!"); + } + sendText(session, result.toJSONString()); + }); + } } break; } diff --git a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java b/src/main/java/com/sonic/agent/websockets/IOSWSServer.java index dc3207a5..02ab5b11 100644 --- a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/IOSWSServer.java @@ -31,6 +31,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; +import static com.sonic.agent.tools.AgentTool.sendText; + @Component @ServerEndpoint(value = "/websockets/ios/{key}/{udId}/{token}", configurator = MyEndpointConfigure.class) public class IOSWSServer { @@ -66,15 +68,21 @@ public void onOpen(Session session, @PathParam("key") String secretKey, return; } udIdMap.put(session, udId); + int wdaPort = TIDeviceTool.startWda(udId); + int imgPort = TIDeviceTool.relayImg(udId); + JSONObject picFinish = new JSONObject(); + picFinish.put("msg", "picFinish"); + picFinish.put("port", imgPort); + sendText(session, picFinish.toJSONString()); + IOSDeviceThreadPool.cachedThreadPool.execute(() -> { IOSStepHandler iosStepHandler = new IOSStepHandler(); iosStepHandler.setTestMode(0, 0, udId, DeviceStatus.DEBUGGING, session.getId()); JSONObject result = new JSONObject(); try { IOSDeviceLocalStatus.startDebug(udId); - int imgPort = iosStepHandler.startIOSDriver(udId); + iosStepHandler.startIOSDriver(udId, wdaPort); result.put("status", "success"); - result.put("port", imgPort); result.put("width", iosStepHandler.getDriver().manage().window().getSize().width); result.put("height", iosStepHandler.getDriver().manage().window().getSize().height); result.put("detail", "初始化Driver完成!"); @@ -120,128 +128,124 @@ public void onMessage(String message, Session session) throws InterruptedExcepti logger.info(session.getId() + " 发送 " + msg); switch (msg.getString("type")) { case "debug": - IOSStepHandler iosStepHandler; - try { - if (msg.getString("detail").equals("tap")) { - iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); - TouchAction ta = new TouchAction(iosStepHandler.getDriver()); - String xy = msg.getString("point"); - int x = Integer.parseInt(xy.substring(0, xy.indexOf(","))); - int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1)); - ta.tap(PointOption.point(x, y)).perform(); - } - if (msg.getString("detail").equals("longPress")) { - iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); - TouchAction ta = new TouchAction(iosStepHandler.getDriver()); - String xy = msg.getString("point"); - int x = Integer.parseInt(xy.substring(0, xy.indexOf(","))); - int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1)); - ta.longPress(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(1500))).release().perform(); - } - if (msg.getString("detail").equals("swipe")) { - iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); - TouchAction ta = new TouchAction(iosStepHandler.getDriver()); - String xy1 = msg.getString("pointA"); - String xy2 = msg.getString("pointB"); - int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(","))); - int y1 = Integer.parseInt(xy1.substring(xy1.indexOf(",") + 1)); - int x2 = Integer.parseInt(xy2.substring(0, xy2.indexOf(","))); - int y2 = Integer.parseInt(xy2.substring(xy2.indexOf(",") + 1)); - ta.press(PointOption.point(x1, y1)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(300))).moveTo(PointOption.point(x2, y2)).release().perform(); + if (msg.getString("detail").equals("runStep")) { + JSONObject jsonDebug = new JSONObject(); + jsonDebug.put("msg", "findSteps"); + jsonDebug.put("key", key); + jsonDebug.put("udId", udIdMap.get(session)); + jsonDebug.put("sessionId", session.getId()); + jsonDebug.put("caseId", msg.getInteger("caseId")); + NettyThreadPool.send(jsonDebug); + } else { + IOSStepHandler iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); + if (iosStepHandler == null || iosStepHandler.getDriver() == null) { + break; } - } catch (Exception e) { - e.printStackTrace(); - } - if (msg.getString("detail").equals("keyEvent")) { - iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); try { - if (msg.getString("key").equals("home") || msg.getString("key").equals("volumeup") || msg.getString("key").equals("volumedown")) { - iosStepHandler.getDriver().executeScript("mobile:pressButton", JSON.parse("{name: \"" + msg.getString("key") + "\"}")); - } else if (msg.getString("key").equals("lock")) { - if (iosStepHandler.getDriver().isDeviceLocked()) { - iosStepHandler.unLock(new HandleDes()); - } else { - iosStepHandler.lock(new HandleDes()); - } - } else { - iosStepHandler.openApp(new HandleDes(), "com.apple." + msg.getString("key")); + if (msg.getString("detail").equals("tap")) { + TouchAction ta = new TouchAction(iosStepHandler.getDriver()); + String xy = msg.getString("point"); + int x = Integer.parseInt(xy.substring(0, xy.indexOf(","))); + int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1)); + ta.tap(PointOption.point(x, y)).perform(); + } + if (msg.getString("detail").equals("longPress")) { + TouchAction ta = new TouchAction(iosStepHandler.getDriver()); + String xy = msg.getString("point"); + int x = Integer.parseInt(xy.substring(0, xy.indexOf(","))); + int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1)); + ta.longPress(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(1500))).release().perform(); + } + if (msg.getString("detail").equals("swipe")) { + TouchAction ta = new TouchAction(iosStepHandler.getDriver()); + String xy1 = msg.getString("pointA"); + String xy2 = msg.getString("pointB"); + int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(","))); + int y1 = Integer.parseInt(xy1.substring(xy1.indexOf(",") + 1)); + int x2 = Integer.parseInt(xy2.substring(0, xy2.indexOf(","))); + int y2 = Integer.parseInt(xy2.substring(xy2.indexOf(",") + 1)); + ta.press(PointOption.point(x1, y1)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(300))).moveTo(PointOption.point(x2, y2)).release().perform(); } - } catch (Throwable e) { + } catch (Exception e) { e.printStackTrace(); } - } - if (msg.getString("detail").equals("siri")) { - iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); - IOSStepHandler finalIOSStepHandler = iosStepHandler; - IOSDeviceThreadPool.cachedThreadPool.execute(() -> { - finalIOSStepHandler.siriCommand(new HandleDes(), msg.getString("command")); - }); - } - if (msg.getString("detail").equals("install")) { - iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); - IOSStepHandler finalIosStepHandler = iosStepHandler; - IOSDeviceThreadPool.cachedThreadPool.execute(() -> { - JSONObject result = new JSONObject(); - result.put("msg", "installFinish"); - HandleDes handleDes = new HandleDes(); - finalIosStepHandler.install(handleDes, msg.getString("ipa")); - if (handleDes.getE() == null) { - result.put("status", "success"); - } else { - System.out.println(handleDes.getE()); - result.put("status", "fail"); - } - sendText(session, result.toJSONString()); - }); - } - if (msg.getString("detail").equals("tree")) { - iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); - IOSStepHandler finalIOSStepHandler = iosStepHandler; - IOSDeviceThreadPool.cachedThreadPool.execute(() -> { + if (msg.getString("detail").equals("keyEvent")) { try { + if (msg.getString("key").equals("home") || msg.getString("key").equals("volumeup") || msg.getString("key").equals("volumedown")) { + iosStepHandler.getDriver().executeScript("mobile:pressButton", JSON.parse("{name: \"" + msg.getString("key") + "\"}")); + } else if (msg.getString("key").equals("lock")) { + if (iosStepHandler.getDriver().isDeviceLocked()) { + iosStepHandler.unLock(new HandleDes()); + } else { + iosStepHandler.lock(new HandleDes()); + } + } else { + iosStepHandler.openApp(new HandleDes(), "com.apple." + msg.getString("key")); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + if (msg.getString("detail").equals("siri")) { + IOSStepHandler finalIOSStepHandler = iosStepHandler; + IOSDeviceThreadPool.cachedThreadPool.execute(() -> { + finalIOSStepHandler.siriCommand(new HandleDes(), msg.getString("command")); + }); + } + if (msg.getString("detail").equals("install")) { + IOSStepHandler finalIosStepHandler = iosStepHandler; + IOSDeviceThreadPool.cachedThreadPool.execute(() -> { JSONObject result = new JSONObject(); - result.put("msg", "tree"); - result.put("detail", finalIOSStepHandler.getResource()); + result.put("msg", "installFinish"); HandleDes handleDes = new HandleDes(); - result.put("img", finalIOSStepHandler.stepScreen(handleDes)); - if (handleDes.getE() != null) { - logger.error(handleDes.getE().getMessage()); - JSONObject resultFail = new JSONObject(); - resultFail.put("msg", "treeFail"); - sendText(session, resultFail.toJSONString()); + finalIosStepHandler.install(handleDes, msg.getString("ipa")); + if (handleDes.getE() == null) { + result.put("status", "success"); } else { + System.out.println(handleDes.getE()); + result.put("status", "fail"); + } + sendText(session, result.toJSONString()); + }); + } + if (msg.getString("detail").equals("tree")) { + IOSStepHandler finalIOSStepHandler = iosStepHandler; + IOSDeviceThreadPool.cachedThreadPool.execute(() -> { + try { + JSONObject result = new JSONObject(); + result.put("msg", "tree"); + result.put("detail", finalIOSStepHandler.getResource()); + HandleDes handleDes = new HandleDes(); + result.put("img", finalIOSStepHandler.stepScreen(handleDes)); + if (handleDes.getE() != null) { + logger.error(handleDes.getE().getMessage()); + JSONObject resultFail = new JSONObject(); + resultFail.put("msg", "treeFail"); + sendText(session, resultFail.toJSONString()); + } else { + sendText(session, result.toJSONString()); + } + } catch (Throwable e) { + logger.error(e.getMessage()); + JSONObject result = new JSONObject(); + result.put("msg", "treeFail"); sendText(session, result.toJSONString()); } - } catch (Throwable e) { - logger.error(e.getMessage()); + }); + } + if (msg.getString("detail").equals("eleScreen")) { + IOSStepHandler finalIOSStepHandler = iosStepHandler; + IOSDeviceThreadPool.cachedThreadPool.execute(() -> { JSONObject result = new JSONObject(); - result.put("msg", "treeFail"); + result.put("msg", "eleScreen"); + try { + result.put("img", UploadTools.upload(finalIOSStepHandler.findEle("xpath", msg.getString("xpath")).getScreenshotAs(OutputType.FILE), "keepFiles")); + } catch (Exception e) { + result.put("errMsg", "获取元素截图失败!"); + } sendText(session, result.toJSONString()); - } - }); - } - if (msg.getString("detail").equals("eleScreen")) { - iosStepHandler = HandlerMap.getIOSMap().get(session.getId()); - IOSStepHandler finalIOSStepHandler = iosStepHandler; - IOSDeviceThreadPool.cachedThreadPool.execute(() -> { - JSONObject result = new JSONObject(); - result.put("msg", "eleScreen"); - try { - result.put("img", UploadTools.upload(finalIOSStepHandler.findEle("xpath", msg.getString("xpath")).getScreenshotAs(OutputType.FILE), "keepFiles")); - } catch (Exception e) { - result.put("errMsg", "获取元素截图失败!"); - } - sendText(session, result.toJSONString()); - }); - } - if (msg.getString("detail").equals("runStep")) { - JSONObject jsonDebug = new JSONObject(); - jsonDebug.put("msg", "findSteps"); - jsonDebug.put("key", key); - jsonDebug.put("udId", udIdMap.get(session)); - jsonDebug.put("sessionId", session.getId()); - jsonDebug.put("caseId", msg.getInteger("caseId")); - NettyThreadPool.send(jsonDebug); + }); + } } break; } From 8e74443e8ef0a7ea2c2e1d827f772f83dc5d2080 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Thu, 23 Dec 2021 20:48:08 +0800 Subject: [PATCH 29/33] =?UTF-8?q?=E7=94=B5=E6=B1=A0=E6=A8=A1=E6=8B=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/bridge/android/AndroidDeviceBridgeTool.java | 9 +++++++++ .../java/com/sonic/agent/websockets/AndroidWSServer.java | 3 +++ 2 files changed, 12 insertions(+) diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java index 9deca46b..470b3a40 100644 --- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java +++ b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java @@ -368,6 +368,15 @@ public static void searchDevice(IDevice iDevice) { executeCommand(iDevice, "am start -n com.sonic.plugins.assist/com.sonic.plugins.assist.SearchActivity"); } + public static void controlBattery(IDevice iDevice, int type) { + if (type == 0) { + executeCommand(iDevice, "dumpsys battery unplug && dumpsys battery set status 1"); + } + if (type == 1) { + executeCommand(iDevice, "dumpsys battery reset"); + } + } + /** * @param udId * @param packageName diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index 050c343a..c0c8a713 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -414,6 +414,9 @@ public void onMessage(String message, Session session) throws InterruptedExcepti case "find": AndroidDeviceBridgeTool.searchDevice(udIdMap.get(session)); break; + case "battery": + AndroidDeviceBridgeTool.controlBattery(udIdMap.get(session), msg.getInteger("detail")); + break; case "scan": AndroidDeviceBridgeTool.pushToCamera(udIdMap.get(session), msg.getString("url")); break; From 7d5cc3008cbdbd2594235be2ff01ae83f3f5c26b Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Thu, 23 Dec 2021 20:49:38 +0800 Subject: [PATCH 30/33] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=83=A8=E5=88=86webvi?= =?UTF-8?q?ew?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/sonic/agent/websockets/AndroidWSServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index c0c8a713..1f6b531d 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -341,7 +341,7 @@ public void onMessage(String message, Session session) throws InterruptedExcepti case "forwardView": { JSONObject forwardView = new JSONObject(); IDevice iDevice = udIdMap.get(session); - List wList = Arrays.asList("webview", "WebView"); + List wList = Arrays.asList("webview", "WebView", "chrome_devtools_remote", "Terrace_devtools_remote"); List webViewList = new ArrayList<>(); for (String w : wList) { webViewList.addAll(Arrays.asList(AndroidDeviceBridgeTool From 100fe4b1576241d1801f8cb120efee25ec93825a Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Thu, 23 Dec 2021 21:01:28 +0800 Subject: [PATCH 31/33] =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=8B=94=E6=8F=92?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java index 470b3a40..068aa9ca 100644 --- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java +++ b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java @@ -166,7 +166,7 @@ public static String getScreenSize(IDevice iDevice) { size = "未知"; } } catch (Exception e) { - logger.info("获取屏幕尺寸失败!"); + logger.info("获取屏幕尺寸失败!拔插瞬间可忽略该错误..."); } return size; } From 80885651677aff2b20b0f55b4196f273ad463ed9 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Thu, 23 Dec 2021 23:25:51 +0800 Subject: [PATCH 32/33] save --- src/main/java/com/sonic/agent/automation/AppiumServer.java | 2 +- src/main/resources/application-dev.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sonic/agent/automation/AppiumServer.java b/src/main/java/com/sonic/agent/automation/AppiumServer.java index 985f46b2..83944a57 100644 --- a/src/main/java/com/sonic/agent/automation/AppiumServer.java +++ b/src/main/java/com/sonic/agent/automation/AppiumServer.java @@ -20,7 +20,7 @@ public class AppiumServer { */ public static void start() { service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder().usingAnyFreePort() -// .withArgument(GeneralServerFlag.LOG_LEVEL, "error") + .withArgument(GeneralServerFlag.LOG_LEVEL, "error") .withArgument(GeneralServerFlag.ALLOW_INSECURE, "chromedriver_autodownload") .withArgument(GeneralServerFlag.SESSION_OVERRIDE)); service.start(); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 355813ec..f4a33965 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -11,7 +11,7 @@ sonic: modules: android: enable: true - use-adbkit: false + use-adbkit: true ios: enable: false wda-bundle-id: com.sonic.wda.xctrunner From 93dde3d83a7167700742d116406d5d8703066692 Mon Sep 17 00:00:00 2001 From: ZhouYixun <291028775@qq.com> Date: Fri, 24 Dec 2021 00:49:03 +0800 Subject: [PATCH 33/33] beta --- pom.xml | 2 +- src/main/resources/application.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7e96cc33..016e9094 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.sonic sonic-agent - v1.2.0-release + v1.3.0-beta1 jar diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9473ce6c..56c09806 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,4 @@ spring: version: @project.version@ profiles: - active: dev,@profileActive@ \ No newline at end of file + active: prod,@profileActive@ \ No newline at end of file