diff --git a/plugins/sonic-appium-uiautomator2-server-test.apk b/plugins/sonic-appium-uiautomator2-server-test.apk
index 81879526..40fbcd38 100644
Binary files a/plugins/sonic-appium-uiautomator2-server-test.apk and b/plugins/sonic-appium-uiautomator2-server-test.apk differ
diff --git a/plugins/sonic-appium-uiautomator2-server.apk b/plugins/sonic-appium-uiautomator2-server.apk
index e4dd668f..0afb318e 100644
Binary files a/plugins/sonic-appium-uiautomator2-server.apk and b/plugins/sonic-appium-uiautomator2-server.apk differ
diff --git a/plugins/sonic-ios-bridge.exe b/plugins/sonic-ios-bridge.exe
index 4ae03f13..67a4e24c 100644
Binary files a/plugins/sonic-ios-bridge.exe and b/plugins/sonic-ios-bridge.exe differ
diff --git a/pom.xml b/pom.xml
index 2af60a27..59526207 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,7 +69,7 @@
io.github.soniccloudorg
sonic-driver-core
- 1.1.7
+ 1.1.9
@@ -93,7 +93,7 @@
org.jsoup
jsoup
- 1.11.3
+ 1.15.3
io.github.soniccloudorg
diff --git a/src/main/java/org/cloud/sonic/agent/automation/AndroidStepHandler.java b/src/main/java/org/cloud/sonic/agent/automation/AndroidStepHandler.java
index 21f157ff..8435eb73 100644
--- a/src/main/java/org/cloud/sonic/agent/automation/AndroidStepHandler.java
+++ b/src/main/java/org/cloud/sonic/agent/automation/AndroidStepHandler.java
@@ -19,9 +19,6 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.android.ddmlib.IDevice;
-import org.apache.commons.exec.CommandLine;
-import org.apache.commons.exec.DefaultExecutor;
-import org.apache.commons.exec.PumpStreamHandler;
import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
import org.cloud.sonic.agent.bridge.android.AndroidDeviceThreadPool;
import org.cloud.sonic.agent.common.enums.AndroidKey;
@@ -39,6 +36,7 @@
import org.cloud.sonic.agent.tests.script.GroovyScriptImpl;
import org.cloud.sonic.agent.tools.BytesTool;
import org.cloud.sonic.agent.tools.PortTool;
+import org.cloud.sonic.agent.tools.ProcessCommandTool;
import org.cloud.sonic.agent.tools.SpringTool;
import org.cloud.sonic.agent.tools.file.DownloadTool;
import org.cloud.sonic.agent.tools.file.UploadTools;
@@ -49,6 +47,7 @@
import org.cloud.sonic.driver.common.tool.SonicRespException;
import org.cloud.sonic.driver.poco.PocoDriver;
import org.cloud.sonic.driver.poco.enums.PocoEngine;
+import org.cloud.sonic.driver.poco.enums.PocoSelector;
import org.cloud.sonic.driver.poco.models.PocoElement;
import org.cloud.sonic.vision.cv.AKAZEFinder;
import org.cloud.sonic.vision.cv.SIFTFinder;
@@ -63,10 +62,8 @@
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions;
-import org.testng.Assert;
import javax.imageio.stream.FileImageOutputStream;
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.util.*;
@@ -116,15 +113,26 @@ public void setGlobalParams(JSONObject jsonObject) {
*/
public void startAndroidDriver(IDevice iDevice, int uiaPort) throws Exception {
this.iDevice = iDevice;
- try {
- androidDriver = new AndroidDriver("http://127.0.0.1:" + uiaPort);
- androidDriver.disableLog();
- log.sendStepLog(StepType.PASS, "连接设备驱动成功", "");
- } catch (Exception e) {
- log.sendStepLog(StepType.ERROR, "连接设备驱动失败!", "");
+ int retry = 0;
+ Exception out = null;
+ while (retry <= 4) {
+ try {
+ androidDriver = new AndroidDriver("http://127.0.0.1:" + uiaPort);
+ break;
+ } catch (Exception e) {
+ log.sendStepLog(StepType.WARN, String.format("连接 UIAutomator2 Server 失败!重试第 %d 次...", retry + 1), "");
+ out = e;
+ }
+ retry++;
+ Thread.sleep(2000);
+ }
+ if (androidDriver == null) {
+ log.sendStepLog(StepType.ERROR, "连接 UIAutomator2 Server 失败!", "");
setResultDetailStatus(ResultDetailStatus.FAIL);
- throw e;
+ throw out;
}
+ androidDriver.disableLog();
+ log.sendStepLog(StepType.PASS, "连接 UIAutomator2 Server 成功", "");
log.androidInfo("Android", iDevice.getProperty(IDevice.PROP_BUILD_VERSION),
iDevice.getSerialNumber(), iDevice.getProperty(IDevice.PROP_DEVICE_MANUFACTURER),
iDevice.getProperty(IDevice.PROP_DEVICE_MODEL),
@@ -1216,20 +1224,41 @@ public void startPocoDriver(HandleDes handleDes, String engine, int port) {
pocoDriver = new PocoDriver(PocoEngine.valueOf(engine), pocoPort);
}
- public PocoElement findPocoEle(String expression) throws SonicRespException {
- return pocoDriver.findElement(expression);
+ public PocoElement findPocoEle(String selector, String pathValue) throws Throwable {
+ PocoElement pocoElement = null;
+ pathValue = TextHandler.replaceTrans(pathValue, globalParams);
+ pocoDriver.getPageSourceForXmlElement();
+ try {
+ switch (selector) {
+ case "poco":
+ pocoElement = pocoDriver.findElement(PocoSelector.POCO, pathValue);
+ break;
+ case "xpath":
+ pocoElement = pocoDriver.findElement(PocoSelector.XPATH, pathValue);
+ break;
+ case "cssSelector":
+ pocoElement = pocoDriver.findElement(PocoSelector.CSS_SELECTOR, pathValue);
+ break;
+ default:
+ log.sendStepLog(StepType.ERROR, "查找控件元素失败", "这个控件元素类型: " + selector + " 不存在!!!");
+ break;
+ }
+ } catch (Throwable e) {
+ throw e;
+ }
+ return pocoElement;
}
- public void isExistPocoEle(HandleDes handleDes, String des, String value, boolean expect) {
+ public void isExistPocoEle(HandleDes handleDes, String des, String selector, String value, boolean expect) {
handleDes.setStepDes("判断控件 " + des + " 是否存在");
handleDes.setDetail("期望值:" + (expect ? "存在" : "不存在"));
boolean hasEle = false;
try {
- PocoElement w = findPocoEle(value);
+ PocoElement w = findPocoEle(selector, value);
if (w != null) {
hasEle = true;
}
- } catch (Exception e) {
+ } catch (Throwable e) {
}
try {
assertEquals(hasEle, expect);
@@ -1238,11 +1267,11 @@ public void isExistPocoEle(HandleDes handleDes, String des, String value, boolea
}
}
- public void pocoClick(HandleDes handleDes, String des, String value) {
+ public void pocoClick(HandleDes handleDes, String des, String selector, String value) {
handleDes.setStepDes("点击" + des);
handleDes.setDetail("点击 " + value);
try {
- PocoElement w = findPocoEle(value);
+ PocoElement w = findPocoEle(selector, value);
if (w != null) {
List pos = w.getPayload().getPos();
int[] realCoordinates = getTheRealCoordinatesOfPoco(pos.get(0), pos.get(1));
@@ -1250,16 +1279,16 @@ public void pocoClick(HandleDes handleDes, String des, String value) {
} else {
throw new SonicRespException(value + " not found!");
}
- } catch (Exception e) {
+ } catch (Throwable e) {
handleDes.setE(e);
}
}
- public void pocoLongPress(HandleDes handleDes, String des, String value, int time) {
+ public void pocoLongPress(HandleDes handleDes, String des, String selector, String value, int time) {
handleDes.setStepDes("长按" + des);
handleDes.setDetail("长按 " + value);
try {
- PocoElement w = findPocoEle(value);
+ PocoElement w = findPocoEle(selector, value);
if (w != null) {
List pos = w.getPayload().getPos();
int[] realCoordinates = getTheRealCoordinatesOfPoco(pos.get(0), pos.get(1));
@@ -1267,17 +1296,17 @@ public void pocoLongPress(HandleDes handleDes, String des, String value, int tim
} else {
throw new SonicRespException(value + " not found!");
}
- } catch (Exception e) {
+ } catch (Throwable e) {
handleDes.setE(e);
}
}
- public void pocoSwipe(HandleDes handleDes, String des, String value, String des2, String value2) {
+ public void pocoSwipe(HandleDes handleDes, String des, String selector, String value, String des2, String selector2, String value2) {
handleDes.setStepDes("滑动拖拽" + des + "到" + des2);
handleDes.setDetail("拖拽 " + value + " 到 " + value2);
try {
- PocoElement w1 = findPocoEle(value);
- PocoElement w2 = findPocoEle(value2);
+ PocoElement w1 = findPocoEle(selector, value);
+ PocoElement w2 = findPocoEle(selector2, value2);
if (w1 != null && w2 != null) {
List pos1 = w1.getPayload().getPos();
int[] realCoordinates1 = getTheRealCoordinatesOfPoco(pos1.get(0), pos1.get(1));
@@ -1288,7 +1317,7 @@ public void pocoSwipe(HandleDes handleDes, String des, String value, String des2
} else {
throw new SonicRespException(value + " or " + value2 + " not found!");
}
- } catch (Exception e) {
+ } catch (Throwable e) {
handleDes.setE(e);
}
}
@@ -1578,29 +1607,16 @@ public void runScript(HandleDes handleDes, String script, String type) {
break;
case "Python":
File temp = new File("test-output" + File.separator + UUID.randomUUID() + ".py");
- if (!temp.exists()) {
- temp.createNewFile();
- FileWriter fileWriter = new FileWriter(temp);
- fileWriter.write(script);
- fileWriter.close();
- }
- CommandLine cmdLine = new CommandLine(String.format("python %s", temp.getAbsolutePath()));
- cmdLine.addArgument(androidDriver.getSessionId(), false);
- cmdLine.addArgument(iDevice.getSerialNumber(), false);
- cmdLine.addArgument(globalParams.toJSONString(), false);
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
+ temp.createNewFile();
+ FileWriter fileWriter = new FileWriter(temp);
+ fileWriter.write(script);
+ fileWriter.close();
try {
- DefaultExecutor executor = new DefaultExecutor();
- executor.setStreamHandler(streamHandler);
- int exit = executor.execute(cmdLine);
- log.sendStepLog(StepType.INFO, "", "Run result:
" + outputStream);
- Assert.assertEquals(exit, 0);
+ String re = ProcessCommandTool.getProcessLocalCommandStr(String.format("python %s %s %s %s", temp.getAbsolutePath(), androidDriver.getSessionId(), iDevice.getSerialNumber(), globalParams.toJSONString()));
+ log.sendStepLog(StepType.INFO, "", "Run result:
" + re);
} catch (Exception e) {
handleDes.setE(e);
} finally {
- outputStream.close();
- streamHandler.stop();
temp.delete();
}
break;
@@ -1789,20 +1805,21 @@ public void runStep(JSONObject stepJSON, HandleDes handleDes) throws Throwable {
startPocoDriver(handleDes, step.getString("content"), step.getInteger("text"));
break;
case "isExistPocoEle":
- isExistPocoEle(handleDes, eleList.getJSONObject(0).getString("eleName")
+ isExistPocoEle(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
, eleList.getJSONObject(0).getString("eleValue"), step.getBoolean("content"));
break;
case "pocoClick":
- pocoClick(handleDes, eleList.getJSONObject(0).getString("eleName")
+ pocoClick(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
, eleList.getJSONObject(0).getString("eleValue"));
break;
case "pocoLongPress":
- pocoLongPress(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")
+ pocoLongPress(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
+ , eleList.getJSONObject(0).getString("eleValue")
, Integer.parseInt(step.getString("content")));
break;
case "pocoSwipe":
- pocoSwipe(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")
- , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleValue"));
+ pocoSwipe(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue")
+ , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleType"), eleList.getJSONObject(1).getString("eleValue"));
break;
case "setTheRealPositionOfTheWindow":
setTheRealPositionOfTheWindow(handleDes, step.getString("content"));
diff --git a/src/main/java/org/cloud/sonic/agent/automation/IOSStepHandler.java b/src/main/java/org/cloud/sonic/agent/automation/IOSStepHandler.java
index f4edbdb0..ff7d74ca 100644
--- a/src/main/java/org/cloud/sonic/agent/automation/IOSStepHandler.java
+++ b/src/main/java/org/cloud/sonic/agent/automation/IOSStepHandler.java
@@ -18,9 +18,6 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
-import org.apache.commons.exec.CommandLine;
-import org.apache.commons.exec.DefaultExecutor;
-import org.apache.commons.exec.PumpStreamHandler;
import org.cloud.sonic.agent.bridge.ios.SibTool;
import org.cloud.sonic.agent.common.enums.ConditionEnum;
import org.cloud.sonic.agent.common.enums.SonicEnum;
@@ -35,6 +32,7 @@
import org.cloud.sonic.agent.tests.handlers.StepHandlers;
import org.cloud.sonic.agent.tests.script.GroovyScript;
import org.cloud.sonic.agent.tests.script.GroovyScriptImpl;
+import org.cloud.sonic.agent.tools.ProcessCommandTool;
import org.cloud.sonic.agent.tools.SpringTool;
import org.cloud.sonic.agent.tools.file.DownloadTool;
import org.cloud.sonic.agent.tools.file.UploadTools;
@@ -53,10 +51,8 @@
import org.jsoup.Jsoup;
import org.jsoup.nodes.Attribute;
import org.jsoup.nodes.Document;
-import org.testng.Assert;
import javax.imageio.stream.FileImageOutputStream;
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.nio.charset.StandardCharsets;
@@ -100,9 +96,9 @@ public void startIOSDriver(String udId, int wdaPort) throws Exception {
try {
iosDriver = new IOSDriver("http://127.0.0.1:" + wdaPort);
iosDriver.disableLog();
- log.sendStepLog(StepType.PASS, "连接设备驱动成功", "");
+ log.sendStepLog(StepType.PASS, "连接 WebDriverAgent 成功", "");
} catch (Exception e) {
- log.sendStepLog(StepType.ERROR, "连接设备驱动失败!", "");
+ log.sendStepLog(StepType.ERROR, "连接 WebDriverAgent 失败!", "");
setResultDetailStatus(ResultDetailStatus.FAIL);
throw e;
}
@@ -864,29 +860,16 @@ public void runScript(HandleDes handleDes, String script, String type) {
break;
case "Python":
File temp = new File("test-output" + File.separator + UUID.randomUUID() + ".py");
- if (!temp.exists()) {
- temp.createNewFile();
- FileWriter fileWriter = new FileWriter(temp);
- fileWriter.write(script);
- fileWriter.close();
- }
- CommandLine cmdLine = new CommandLine(String.format("python %s", temp.getAbsolutePath()));
- cmdLine.addArgument(iosDriver.getSessionId(), false);
- cmdLine.addArgument(udId, false);
- cmdLine.addArgument(globalParams.toJSONString(), false);
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
+ temp.createNewFile();
+ FileWriter fileWriter = new FileWriter(temp);
+ fileWriter.write(script);
+ fileWriter.close();
try {
- DefaultExecutor executor = new DefaultExecutor();
- executor.setStreamHandler(streamHandler);
- int exit = executor.execute(cmdLine);
- log.sendStepLog(StepType.INFO, "", "Run result:
" + outputStream);
- Assert.assertEquals(exit, 0);
+ String re = ProcessCommandTool.getProcessLocalCommandStr(String.format("python %s %s %s %s", temp.getAbsolutePath(), iosDriver.getSessionId(), udId, globalParams.toJSONString()));
+ log.sendStepLog(StepType.INFO, "", "Run result:
" + re);
} catch (Exception e) {
handleDes.setE(e);
} finally {
- outputStream.close();
- streamHandler.stop();
temp.delete();
}
break;
diff --git a/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java b/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java
index 6640a400..20fef347 100644
--- a/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java
+++ b/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java
@@ -491,7 +491,7 @@ public static int[] getDisplayOfAllScreen(IDevice iDevice, int width, int height
Pattern pattern = Pattern.compile(patten);
Matcher m = pattern.matcher(window);
while (m.find()) {
- if (m.groupCount()!=4)break;
+ if (m.groupCount() != 4) break;
offsetx = Integer.parseInt(m.group(1));
offsety = Integer.parseInt(m.group(2));
width = Integer.parseInt(m.group(3));
@@ -513,7 +513,7 @@ public static int[] getDisplayOfAllScreen(IDevice iDevice, int width, int height
}
}
}
- return new int[]{offsetx, offsety,width,height};
+ return new int[]{offsetx, offsety, width, height};
}
public static String getCurrentPackage(IDevice iDevice) {
@@ -679,6 +679,10 @@ true, new InstallReceiver(), 180L, 180L, TimeUnit.MINUTES
iDevice.installPackage("plugins/sonic-appium-uiautomator2-server-test.apk",
true, new InstallReceiver(), 180L, 180L, TimeUnit.MINUTES
, "-r", "-t");
+ executeCommand(iDevice, "appops set io.appium.uiautomator2.server RUN_IN_BACKGROUND allow");
+ executeCommand(iDevice, "appops set io.appium.uiautomator2.server.test RUN_IN_BACKGROUND allow");
+ executeCommand(iDevice, "dumpsys deviceidle whitelist +io.appium.uiautomator2.server");
+ executeCommand(iDevice, "dumpsys deviceidle whitelist +io.appium.uiautomator2.server.test");
}
int port = PortTool.getPort();
UiaThread uiaThread = new UiaThread(iDevice, port);
@@ -686,7 +690,7 @@ true, new InstallReceiver(), 180L, 180L, TimeUnit.MINUTES
int wait = 0;
while (!uiaThread.getIsOpen()) {
try {
- Thread.sleep(500);
+ Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
@@ -792,7 +796,7 @@ public static File getChromeDriver(IDevice iDevice, String packageName) throws I
String major = chromeVersion.substring(0, end);
HttpHeaders headers = new HttpHeaders();
ResponseEntity infoEntity =
- restTemplate.exchange(String.format("https://chromedriver.storage.googleapis.com/LATEST_RELEASE_%d", major), HttpMethod.GET, new HttpEntity(headers), String.class);
+ restTemplate.exchange(String.format("https://chromedriver.storage.googleapis.com/LATEST_RELEASE_%s", major), HttpMethod.GET, new HttpEntity(headers), String.class);
if (system.contains("win")) {
system = "win32";
} else if (system.contains("linux")) {
@@ -800,7 +804,16 @@ public static File getChromeDriver(IDevice iDevice, String packageName) throws I
} else {
String arch = System.getProperty("os.arch").toLowerCase();
if (arch.contains("aarch64")) {
- system = "mac64_m1";
+ // fix m1 arm version obtained is lower than 87 for special processing
+ String driverList = restTemplate.exchange(String.format("https://registry.npmmirror.com/-/binary/chromedriver/%s/", infoEntity.getBody()), HttpMethod.GET, new HttpEntity(headers), String.class).getBody();
+ for (Object obj : JSONArray.parseArray(driverList)) {
+ JSONObject jsonObject = JSONObject.parseObject(obj.toString());
+ String fullName = jsonObject.getString("name");
+ if (fullName.contains("m1") || fullName.contains("arm")) {
+ system = fullName.substring(fullName.indexOf("mac"), fullName.indexOf("."));
+ break;
+ }
+ }
} else {
system = "mac64";
}
diff --git a/src/main/java/org/cloud/sonic/agent/bridge/ios/SibTool.java b/src/main/java/org/cloud/sonic/agent/bridge/ios/SibTool.java
index f915d26d..6c5894b1 100644
--- a/src/main/java/org/cloud/sonic/agent/bridge/ios/SibTool.java
+++ b/src/main/java/org/cloud/sonic/agent/bridge/ios/SibTool.java
@@ -158,7 +158,9 @@ public static List getDeviceList() {
if (a.length() == 0) {
break;
}
- result.add(a.substring(0, a.indexOf(" ")));
+ if (a.indexOf(" ") != -1) {
+ result.add(a.substring(0, a.indexOf(" ")));
+ }
}
return result;
}
diff --git a/src/main/java/org/cloud/sonic/agent/tests/AndroidTests.java b/src/main/java/org/cloud/sonic/agent/tests/AndroidTests.java
index 7be11097..bf978a45 100644
--- a/src/main/java/org/cloud/sonic/agent/tests/AndroidTests.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/AndroidTests.java
@@ -83,7 +83,8 @@ public void run(JSONObject jsonObject) throws IOException {
// 启动任务
AndroidTestTaskBootThread bootThread = new AndroidTestTaskBootThread(jsonObject, androidStepHandler);
- if (!runningTestsMap.containsKey(rid + "")) {
+ // runningTestsMap的key在rid的基础上再加上udid,避免分发到设备上的用例不均,先执行的完的用例remove rid,导致用例执行不完全的问题
+ if (!runningTestsMap.containsKey(rid + "-" + udId)) {
logger.info("任务【{}】中断,跳过", bootThread.getName());
return;
}
diff --git a/src/main/java/org/cloud/sonic/agent/tests/IOSTests.java b/src/main/java/org/cloud/sonic/agent/tests/IOSTests.java
index 3b630c81..aa47a4e7 100644
--- a/src/main/java/org/cloud/sonic/agent/tests/IOSTests.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/IOSTests.java
@@ -85,7 +85,8 @@ public void run(JSONObject jsonObject) throws IOException {
// 启动任务
IOSTestTaskBootThread bootThread = new IOSTestTaskBootThread(jsonObject, iosStepHandler);
- if (!runningTestsMap.containsKey(rid + "")) {
+ // runningTestsMap的key在rid的基础上再加上udid,避免先执行完的会remove rid,导致用例执行不完全的问题
+ if (!runningTestsMap.containsKey(rid + "-" + udId)) {
logger.info("任务【{}】中断,跳过", bootThread.getName());
return;
}
diff --git a/src/main/java/org/cloud/sonic/agent/tests/SuiteListener.java b/src/main/java/org/cloud/sonic/agent/tests/SuiteListener.java
index b5c7a080..d93925c1 100644
--- a/src/main/java/org/cloud/sonic/agent/tests/SuiteListener.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/SuiteListener.java
@@ -17,6 +17,9 @@
package org.cloud.sonic.agent.tests;
import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.util.CollectionUtils;
import org.testng.ISuite;
import org.testng.ISuiteListener;
@@ -34,13 +37,38 @@ public class SuiteListener implements ISuiteListener {
@Override
public void onStart(ISuite suite) {
- String rid = JSON.parseObject(suite.getParameter("dataInfo")).getString("rid");
- runningTestsMap.put(rid, true);
+ String runningTestsMapKey = getRunningTestsMapKey(suite);
+ if (runningTestsMapKey == null || runningTestsMapKey.length() == 0){
+ return;
+ }
+ runningTestsMap.put(runningTestsMapKey, true);
}
@Override
public void onFinish(ISuite suite) {
- String rid = JSON.parseObject(suite.getParameter("dataInfo")).getString("rid");
- runningTestsMap.remove(rid);
+ String runningTestsMapKey = getRunningTestsMapKey(suite);
+ if (runningTestsMapKey == null || runningTestsMapKey.length() == 0){
+ return;
+ }
+ // 加上udId,避免先完成的设备移除后,后完成的设备无法执行后续操作
+ runningTestsMap.remove(runningTestsMapKey);
+ }
+
+ private String getRunningTestsMapKey(ISuite suite){
+ JSONObject dataInfoJson = JSON.parseObject(suite.getParameter("dataInfo"));
+ String rid = dataInfoJson.getString("rid");
+ JSONArray deviceArray = dataInfoJson.getJSONArray("device");
+ if (CollectionUtils.isEmpty(deviceArray)){
+ return null;
+ }
+ JSONObject jsonObject = deviceArray.getJSONObject(0);
+ if (jsonObject == null){
+ return null;
+ }
+ String udId = jsonObject.getString("udId");
+ if (udId == null || udId.length() == 0){
+ return null;
+ }
+ return rid + "-" + udId;
}
}
diff --git a/src/main/java/org/cloud/sonic/agent/tests/TaskManager.java b/src/main/java/org/cloud/sonic/agent/tests/TaskManager.java
index c0e76424..8a7ebe24 100644
--- a/src/main/java/org/cloud/sonic/agent/tests/TaskManager.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/TaskManager.java
@@ -258,7 +258,7 @@ public static void forceStopSuite(int platform, int resultId, int caseId, String
}
}
}
- runningTestsMap.remove(resultId + "");
+ runningTestsMap.remove(resultId + "-" + udId);
runningRidSet.remove(resultId + "-" + udId);
runningUdIdSet.remove(udId);
diff --git a/src/main/java/org/cloud/sonic/agent/tests/ios/IOSRunStepThread.java b/src/main/java/org/cloud/sonic/agent/tests/ios/IOSRunStepThread.java
index e33e5ccf..1bfda781 100644
--- a/src/main/java/org/cloud/sonic/agent/tests/ios/IOSRunStepThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/ios/IOSRunStepThread.java
@@ -54,12 +54,14 @@ public void run() {
JSONObject jsonObject = iosTestTaskBootThread.getJsonObject();
List steps = jsonObject.getJSONArray("steps").toJavaList(JSONObject.class);
+ // 复用同一个handleDes
+ HandleDes handleDes = new HandleDes();
for (JSONObject step : steps) {
if (isStopped()) {
return;
}
try {
- stepHandlers.runStep(step, new HandleDes(), this);
+ stepHandlers.runStep(step, handleDes, this);
} catch (Throwable e) {
break;
}
diff --git a/src/main/java/org/cloud/sonic/agent/tools/file/FileTool.java b/src/main/java/org/cloud/sonic/agent/tools/file/FileTool.java
index 69330dda..ecce0e9e 100644
--- a/src/main/java/org/cloud/sonic/agent/tools/file/FileTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/file/FileTool.java
@@ -84,6 +84,8 @@ public static File unZipChromeDriver(File source, String version) {
e.printStackTrace();
}
if (driver != null) {
+ driver.setExecutable(true);
+ driver.setWritable(true);
source.delete();
}
return driver;
diff --git a/src/main/java/org/cloud/sonic/agent/tools/file/UploadTools.java b/src/main/java/org/cloud/sonic/agent/tools/file/UploadTools.java
index bce06a0b..cd605d9f 100644
--- a/src/main/java/org/cloud/sonic/agent/tools/file/UploadTools.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/file/UploadTools.java
@@ -68,7 +68,12 @@ public static String upload(File uploadFile, String type) {
ResponseEntity responseEntity =
restTemplate.postForEntity(baseUrl + "/upload", param, JSONObject.class);
if (responseEntity.getBody().getInteger("code") == 2000) {
- transfer.delete();
+ if (uploadFile.exists()) {
+ uploadFile.delete();
+ }
+ if (transfer.exists()) {
+ transfer.delete();
+ }
} else {
logger.info("发送失败!" + responseEntity.getBody());
}
diff --git a/src/main/java/org/cloud/sonic/agent/websockets/AndroidTerminalWSServer.java b/src/main/java/org/cloud/sonic/agent/websockets/AndroidTerminalWSServer.java
index 21dab9ea..cb8590a0 100644
--- a/src/main/java/org/cloud/sonic/agent/websockets/AndroidTerminalWSServer.java
+++ b/src/main/java/org/cloud/sonic/agent/websockets/AndroidTerminalWSServer.java
@@ -77,14 +77,14 @@ public void onOpen(Session session, @PathParam("key") String secretKey,
udIdMap.put(session, iDevice);
String username = iDevice.getProperty("ro.product.device");
Future> terminal = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- logger.info(udId + "开启terminal");
+ logger.info(udId + "open terminal");
JSONObject ter = new JSONObject();
ter.put("msg", "terminal");
ter.put("user", username);
BytesTool.sendText(session, ter.toJSONString());
});
Future> logcat = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- logger.info(udId + "开启logcat");
+ logger.info(udId + "open logcat");
JSONObject ter = new JSONObject();
ter.put("msg", "logcat");
BytesTool.sendText(session, ter.toJSONString());
diff --git a/src/main/java/org/cloud/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/org/cloud/sonic/agent/websockets/AndroidWSServer.java
index 26ef4776..e863fb4e 100644
--- a/src/main/java/org/cloud/sonic/agent/websockets/AndroidWSServer.java
+++ b/src/main/java/org/cloud/sonic/agent/websockets/AndroidWSServer.java
@@ -59,7 +59,7 @@
import java.util.concurrent.TimeUnit;
@Component
-@ServerEndpoint(value = "/websockets/android/{key}/{udId}/{token}/{isAutoInit}", configurator = WsEndpointConfigure.class)
+@ServerEndpoint(value = "/websockets/android/{key}/{udId}/{token}", configurator = WsEndpointConfigure.class)
public class AndroidWSServer implements IAndroidWSServer {
private final Logger logger = LoggerFactory.getLogger(AndroidWSServer.class);
@@ -74,8 +74,8 @@ public class AndroidWSServer implements IAndroidWSServer {
@OnOpen
public void onOpen(Session session, @PathParam("key") String secretKey,
- @PathParam("udId") String udId, @PathParam("token") String token, @PathParam("isAutoInit") Integer isAutoInit) throws Exception {
- if (secretKey.length() == 0 || (!secretKey.equals(key)) || token.length() == 0 || isAutoInit == null) {
+ @PathParam("udId") String udId, @PathParam("token") String token) throws Exception {
+ if (secretKey.length() == 0 || (!secretKey.equals(key)) || token.length() == 0) {
logger.info("拦截访问!");
return;
}
@@ -110,22 +110,24 @@ public void onOpen(Session session, @PathParam("key") String secretKey,
.replaceAll("\n", "")
.replaceAll("\t", "");
if (path.length() > 0 && AndroidDeviceBridgeTool.checkSonicApkVersion(iDevice)) {
- logger.info("已安装Sonic插件,检查版本信息通过");
+ logger.info("Check Sonic Apk version and status pass...");
} else {
- logger.info("未安装Sonic插件或版本不是最新,正在安装...");
+ logger.info("Sonic Apk version not newest or not install, starting install...");
try {
iDevice.uninstallPackage("org.cloud.sonic.android");
} catch (InstallException e) {
- logger.info("卸载出错...");
+ logger.info("uninstall sonic Apk err...");
}
try {
iDevice.installPackage("plugins/sonic-android-apk.apk",
true, new InstallReceiver(), 180L, 180L, TimeUnit.MINUTES
, "-r", "-t", "-g");
- logger.info("Sonic插件安装完毕");
+ AndroidDeviceBridgeTool.executeCommand(iDevice, "appops set org.cloud.sonic.android RUN_IN_BACKGROUND allow");
+ AndroidDeviceBridgeTool.executeCommand(iDevice, "dumpsys deviceidle whitelist +org.cloud.sonic.android");
+ logger.info("Sonic Apk install successful.");
} catch (InstallException e) {
e.printStackTrace();
- logger.info("Sonic插件安装失败!");
+ logger.info("Sonic Apk install failed.");
return;
}
path = AndroidDeviceBridgeTool.executeCommand(iDevice, "pm path org.cloud.sonic.android").trim()
@@ -167,7 +169,7 @@ public boolean isCancelled() {
}
}, 0, TimeUnit.MILLISECONDS);
} catch (Exception e) {
- logger.info("{} 设备touch服务启动异常!"
+ logger.info("{} device touch service launch err"
, iDevice.getSerialNumber());
logger.error(e.getMessage());
}
@@ -240,9 +242,7 @@ public boolean isCancelled() {
AndroidSupplyTool.startShare(udId, session);
- if (isAutoInit == 1) {
- openDriver(iDevice, session);
- }
+ openDriver(iDevice, session);
}
@OnClose
@@ -377,7 +377,7 @@ public void onMessage(String message, Session session) {
androidStepHandler.startPocoDriver(new HandleDes(), msg.getString("engine"), msg.getInteger("port"));
JSONObject poco = new JSONObject();
try {
- poco.put("result", androidStepHandler.getPocoDriver().getPageSourceForJson());
+ poco.put("result", androidStepHandler.getPocoDriver().getPageSourceForJsonString());
} catch (SonicRespException e) {
poco.put("result", "");
e.printStackTrace();
@@ -495,7 +495,6 @@ public void onMessage(String message, Session session) {
}
case "eleScreen": {
if (androidStepHandler != null && androidStepHandler.getAndroidDriver() != null) {
- AndroidStepHandler finalAndroidStepHandler = androidStepHandler;
AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
JSONObject result = new JSONObject();
result.put("msg", "eleScreen");
@@ -528,28 +527,30 @@ public void onMessage(String message, Session session) {
}
private void openDriver(IDevice iDevice, Session session) {
- AndroidStepHandler androidStepHandler = new AndroidStepHandler();
- androidStepHandler.setTestMode(0, 0, iDevice.getSerialNumber(), DeviceStatus.DEBUGGING, session.getId());
- JSONObject result = new JSONObject();
- AndroidStepHandler finalAndroidStepHandler1 = androidStepHandler;
- AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
- try {
- AndroidDeviceLocalStatus.startDebug(iDevice.getSerialNumber());
- int port = AndroidDeviceBridgeTool.startUiaServer(iDevice);
- finalAndroidStepHandler1.startAndroidDriver(iDevice, port);
- result.put("status", "success");
- result.put("detail", "初始化Driver完成!");
- HandlerMap.getAndroidMap().put(session.getId(), finalAndroidStepHandler1);
- } catch (Exception e) {
- logger.error(e.getMessage());
- result.put("status", "error");
- result.put("detail", "初始化Driver失败!部分功能不可用!请联系管理员");
- finalAndroidStepHandler1.closeAndroidDriver();
- } finally {
- result.put("msg", "openDriver");
- BytesTool.sendText(session, result.toJSONString());
- }
- });
+ synchronized (session) {
+ AndroidStepHandler androidStepHandler = new AndroidStepHandler();
+ androidStepHandler.setTestMode(0, 0, iDevice.getSerialNumber(), DeviceStatus.DEBUGGING, session.getId());
+ JSONObject result = new JSONObject();
+ AndroidStepHandler finalAndroidStepHandler1 = androidStepHandler;
+ AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
+ try {
+ AndroidDeviceLocalStatus.startDebug(iDevice.getSerialNumber());
+ int port = AndroidDeviceBridgeTool.startUiaServer(iDevice);
+ finalAndroidStepHandler1.startAndroidDriver(iDevice, port);
+ result.put("status", "success");
+ result.put("detail", "初始化 UIAutomator2 Server 完成!");
+ HandlerMap.getAndroidMap().put(session.getId(), finalAndroidStepHandler1);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ result.put("status", "error");
+ result.put("detail", "初始化 UIAutomator2 Server 失败!");
+ finalAndroidStepHandler1.closeAndroidDriver();
+ } finally {
+ result.put("msg", "openDriver");
+ BytesTool.sendText(session, result.toJSONString());
+ }
+ });
+ }
}
private void exit(Session session) {
diff --git a/src/main/java/org/cloud/sonic/agent/websockets/IOSWSServer.java b/src/main/java/org/cloud/sonic/agent/websockets/IOSWSServer.java
index 25d5a911..5d3f910c 100644
--- a/src/main/java/org/cloud/sonic/agent/websockets/IOSWSServer.java
+++ b/src/main/java/org/cloud/sonic/agent/websockets/IOSWSServer.java
@@ -121,7 +121,7 @@ public void onOpen(Session session, @PathParam("key") String secretKey,
result.put("status", "success");
result.put("width", iosStepHandler.getDriver().getWindowSize().getWidth());
result.put("height", iosStepHandler.getDriver().getWindowSize().getHeight());
- result.put("detail", "初始化Driver完成!");
+ result.put("detail", "初始化 WebDriverAgent 完成!");
JSONObject appiumSettings = new JSONObject();
appiumSettings.put("mjpegServerFramerate", 100);
appiumSettings.put("mjpegScalingFactor", 100);
@@ -131,7 +131,7 @@ public void onOpen(Session session, @PathParam("key") String secretKey,
} catch (Exception e) {
logger.error(e.getMessage());
result.put("status", "error");
- result.put("detail", "初始化Driver失败!部分功能不可用!请联系管理员");
+ result.put("detail", "初始化 WebDriverAgent 失败!");
iosStepHandler.closeIOSDriver();
} finally {
result.put("msg", "openDriver");
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 930d9308..6e73ae2a 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -9,9 +9,9 @@ spring:
sonic:
saa: 2.0.1
sgm: 1.3.3
- sib: 1.2.3
+ sib: 1.2.4
sas: 0.0.2
- saus: 5.7.0
+ saus: 4.22.1
logging:
file: