Skip to content

Commit 1a26a8e

Browse files
Feat.: support Linux command running during tests (#506)
* Feat.: add AGENT type for a list of deviceActions to run on an agent separately, rather than being run together with commands for all or mobile devices (to ensure being run only once per test). * Remove ambiguous ANY type
1 parent 9e498ea commit 1a26a8e

File tree

5 files changed

+54
-30
lines changed

5 files changed

+54
-30
lines changed

agent/src/main/java/com/microsoft/hydralab/agent/command/DeviceScriptCommandLoader.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import com.microsoft.hydralab.common.entity.common.DeviceAction;
77
import com.microsoft.hydralab.common.entity.common.TestTask;
8+
import com.microsoft.hydralab.common.util.Const;
89
import org.springframework.stereotype.Service;
910
import org.springframework.util.StringUtils;
1011

@@ -19,6 +20,7 @@
1920
*/
2021
@Service
2122
public class DeviceScriptCommandLoader {
23+
// preset commands in agent application.yml
2224
@Resource(name = "DeviceCommandProperty")
2325
private List<DeviceScriptCommand> commands;
2426

@@ -55,7 +57,7 @@ private List<DeviceAction> command2Action(DeviceScriptCommand deviceCommand) {
5557
String[] commandLines = deviceCommand.getInline().split("\n");
5658
for (String commandLine : commandLines) {
5759
if (!StringUtils.isEmpty(commandLine)) {
58-
actionList.add(converter.getAction(commandLine));
60+
actionList.add(converter.getAction(commandLine, deviceCommand.getDevice()));
5961
}
6062
}
6163
return actionList;
@@ -65,21 +67,29 @@ private enum ActionConverter {
6567
//generate action by command type
6668
ADBShell() {
6769
@Override
68-
public DeviceAction getAction(String commandline) {
69-
DeviceAction deviceAction = new DeviceAction("Android", "execCommandOnDevice");
70+
public DeviceAction getAction(String commandline, String deviceType) {
71+
String type = deviceType;
72+
if (StringUtils.isEmpty(type)) {
73+
type = Const.OperatedDevice.ANDROID;
74+
}
75+
DeviceAction deviceAction = new DeviceAction(type, "execCommandOnDevice");
7076
deviceAction.getArgs().add(commandline);
7177
return deviceAction;
7278
}
7379
},
7480
AgentShell() {
7581
@Override
76-
public DeviceAction getAction(String commandline) {
77-
DeviceAction deviceAction = new DeviceAction("Windows", "execCommandOnAgent");
82+
public DeviceAction getAction(String commandline, String deviceType) {
83+
String type = deviceType;
84+
if (StringUtils.isEmpty(type)) {
85+
type = Const.OperatedDevice.ANDROID;
86+
}
87+
DeviceAction deviceAction = new DeviceAction(type, "execCommandOnAgent");
7888
deviceAction.getArgs().add(commandline);
7989
return deviceAction;
8090
}
8191
};
8292

83-
public abstract DeviceAction getAction(String commandline);
93+
public abstract DeviceAction getAction(String commandline, String deviceType);
8494
}
8595
}

agent/src/main/java/com/microsoft/hydralab/agent/runner/ActionExecutor.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.microsoft.hydralab.common.entity.common.DeviceInfo;
99
import com.microsoft.hydralab.common.entity.common.TestRunDevice;
1010
import com.microsoft.hydralab.common.management.device.DeviceDriver;
11+
import com.microsoft.hydralab.common.util.Const;
1112
import com.microsoft.hydralab.common.util.HydraLabRuntimeException;
1213
import com.microsoft.hydralab.common.util.ThreadUtils;
1314
import org.apache.commons.lang3.StringUtils;
@@ -24,6 +25,7 @@
2425
import java.util.Map;
2526
import java.util.Set;
2627
import java.util.stream.Collectors;
28+
import java.util.stream.Stream;
2729

2830
/**
2931
* @author zhoule
@@ -35,20 +37,25 @@ public class ActionExecutor {
3537
/**
3638
* the implementation of supported actions should not be overload
3739
*/
38-
private Set<String> actionTypes =
40+
private final Set<String> actionTypes =
3941
Set.of("setProperty", "setDefaultLauncher", "backToHome", "changeGlobalSetting",
4042
"changeSystemSetting", "execCommandOnDevice", "execCommandOnAgent", "pushFileToDevice",
4143
"pullFileFromDevice");
4244

4345
public List<Exception> doActions(@NotNull DeviceDriver deviceDriverManager,
4446
@NotNull TestRunDevice testRunDevice,
4547
@NotNull Logger logger,
46-
@NotNull Map<String, List<DeviceAction>> actions, @NotNull String when) {
48+
@NotNull Map<String, List<DeviceAction>> actions, @NotNull String when, boolean runOnAgentOnly) {
4749
List<Exception> exceptions = new ArrayList<>();
4850
//filter todoActions
49-
List<DeviceAction> todoActions = actions.getOrDefault(when, new ArrayList<>()).stream()
50-
.filter(deviceAction -> actionTypes.contains(deviceAction.getMethod()))
51-
.collect(Collectors.toList());
51+
Stream<DeviceAction> legalActionStream = actions.getOrDefault(when, new ArrayList<>()).stream()
52+
.filter(deviceAction -> actionTypes.contains(deviceAction.getMethod()) && StringUtils.isNotEmpty(deviceAction.getDeviceType()));
53+
if (runOnAgentOnly) {
54+
legalActionStream = legalActionStream.filter(deviceAction -> Const.OperatedDevice.AGENT.equalsIgnoreCase(deviceAction.getDeviceType()));
55+
} else {
56+
legalActionStream = legalActionStream.filter(deviceAction -> testRunDevice.getDeviceInfo().getType().equalsIgnoreCase(deviceAction.getDeviceType()));
57+
}
58+
List<DeviceAction> todoActions = legalActionStream.collect(Collectors.toList());
5259

5360
logger.info("Start to execute actions! Current timing is {}, action size is {}", when, todoActions.size());
5461
for (DeviceAction deviceAction : todoActions) {
@@ -64,17 +71,14 @@ public List<Exception> doActions(@NotNull DeviceDriver deviceDriverManager,
6471
return exceptions;
6572
}
6673

67-
public void doAction(@NotNull DeviceDriver deviceDriverManager,
74+
private void doAction(@NotNull DeviceDriver deviceDriverManager,
6875
@NotNull TestRunDevice testRunDevice,
6976
@NotNull Logger logger,
7077
@NotNull DeviceAction deviceAction)
7178
throws InvocationTargetException, IllegalAccessException {
7279
if (!actionTypes.contains(deviceAction.getMethod())) {
7380
return;
7481
}
75-
if (!StringUtils.isEmpty(deviceAction.getDeviceType()) && !testRunDevice.getDeviceInfo().getType().equalsIgnoreCase(deviceAction.getDeviceType())){
76-
return;
77-
}
7882
DeviceInfo deviceInfo = testRunDevice.getDeviceInfo();
7983
logger.info("Start to analysis action type! Current action is {}", deviceAction.getMethod());
8084
Method method = Arrays.stream(deviceDriverManager.getClass().getMethods())
@@ -122,5 +126,4 @@ private Object[] convertArgs(@NotNull DeviceInfo deviceInfo, @NotNull Logger log
122126
}
123127
return methodArgs;
124128
}
125-
126129
}

agent/src/main/java/com/microsoft/hydralab/agent/runner/TestRunDeviceOrchestrator.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -336,14 +336,15 @@ public Logger getDeviceLogger(TestRunDevice testRunDevice) {
336336
}
337337

338338
public List<Exception> doActions(TestRunDevice testRunDevice, Logger logger, Map<String, List<DeviceAction>> deviceActions, String when) {
339+
List<Exception> exceptions = actionExecutor.doActions(deviceDriverManager, testRunDevice, logger, deviceActions, when, true);
340+
339341
if (testRunDevice instanceof TestRunDeviceCombo) {
340-
List<Exception> exceptions = new ArrayList<>();
341-
for (TestRunDevice testRunDevice1 : ((TestRunDeviceCombo) testRunDevice).getDevices()) {
342-
exceptions.addAll(actionExecutor.doActions(deviceDriverManager, testRunDevice1, logger, deviceActions, when));
342+
for (TestRunDevice subTestRunDevice : ((TestRunDeviceCombo) testRunDevice).getDevices()) {
343+
exceptions.addAll(actionExecutor.doActions(deviceDriverManager, subTestRunDevice, logger, deviceActions, when, false));
343344
}
344-
return exceptions;
345345
} else {
346-
return actionExecutor.doActions(deviceDriverManager, testRunDevice, logger, deviceActions, when);
346+
exceptions.addAll(actionExecutor.doActions(deviceDriverManager, testRunDevice, logger, deviceActions, when, false));
347347
}
348+
return exceptions;
348349
}
349350
}

agent/src/test/java/com/microsoft/hydralab/agent/runner/ActionExecutorTest.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,23 @@ void createAndExecuteActions() throws InvocationTargetException, IllegalAccessEx
3737
DeviceAction action1 = JSONObject.parseObject(actionJson.toJSONString(), DeviceAction.class);
3838
List<String> args1 = List.of("paramA", "paramB");
3939
action1.setArgs(args1);
40-
actionExecutor.doAction(deviceDriver, new TestRunDevice(deviceInfo, deviceInfo.getType()), baseLogger, action1);
41-
verify(deviceDriver).setProperty(deviceInfo, args1.get(0), args1.get(1), baseLogger);
40+
List<DeviceAction> actions1 = new ArrayList<>();
41+
actions1.add(action1);
42+
List<Exception> exceptions1 = actionExecutor.doActions(deviceDriver, new TestRunDevice(deviceInfo, deviceInfo.getType()), baseLogger,
43+
Map.of(DeviceAction.When.SET_UP, actions1), DeviceAction.When.SET_UP, true);
44+
Assertions.assertEquals(0, exceptions1.size(), () -> exceptions1.get(0).getMessage());
45+
verify(deviceDriver, times(0)).setProperty(deviceInfo, args1.get(0), args1.get(1), baseLogger);
4246

4347
DeviceAction action2 = new DeviceAction("Android", "changeGlobalSetting");
4448
List<String> args2 = List.of("paramC", "paramD");
4549
action2.setArgs(args2);
46-
List<DeviceAction> actions = new ArrayList<>();
47-
actions.add(action1);
48-
actions.add(action2);
49-
List<Exception> exceptions = actionExecutor.doActions(deviceDriver, new TestRunDevice(deviceInfo, deviceInfo.getType()), baseLogger,
50-
Map.of(DeviceAction.When.SET_UP, actions), DeviceAction.When.SET_UP);
51-
Assertions.assertEquals(0, exceptions.size(), () -> exceptions.get(0).getMessage());
52-
verify(deviceDriver, times(2)).setProperty(deviceInfo, args1.get(0), args1.get(1), baseLogger);
50+
List<DeviceAction> actions2 = new ArrayList<>();
51+
actions2.add(action1);
52+
actions2.add(action2);
53+
List<Exception> exceptions2 = actionExecutor.doActions(deviceDriver, new TestRunDevice(deviceInfo, deviceInfo.getType()), baseLogger,
54+
Map.of(DeviceAction.When.SET_UP, actions2), DeviceAction.When.SET_UP, false);
55+
Assertions.assertEquals(0, exceptions2.size(), () -> exceptions2.get(0).getMessage());
56+
verify(deviceDriver, times(1)).setProperty(deviceInfo, args1.get(0), args1.get(1), baseLogger);
5357
verify(deviceDriver, times(1)).changeGlobalSetting(deviceInfo, args2.get(0), args2.get(1), baseLogger);
5458
}
5559

common/src/main/java/com/microsoft/hydralab/common/util/Const.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,10 @@ interface TestDeviceTag {
187187
String TERTIARY_PHONE = "TERTIARY_PHONE";
188188
String PRIMARY_PC = "PRIMARY_PC";
189189
}
190+
191+
interface OperatedDevice {
192+
String ANY = "Any";
193+
String AGENT = "Agent";
194+
String ANDROID = "Android";
195+
}
190196
}

0 commit comments

Comments
 (0)