Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat.: support Linux command running during tests #506

Merged
merged 6 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import com.microsoft.hydralab.common.entity.common.DeviceAction;
import com.microsoft.hydralab.common.entity.common.TestTask;
import com.microsoft.hydralab.common.util.Const;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

Expand All @@ -19,6 +20,7 @@
*/
@Service
public class DeviceScriptCommandLoader {
// preset commands in agent application.yml
@Resource(name = "DeviceCommandProperty")
private List<DeviceScriptCommand> commands;

Expand Down Expand Up @@ -55,7 +57,7 @@ private List<DeviceAction> command2Action(DeviceScriptCommand deviceCommand) {
String[] commandLines = deviceCommand.getInline().split("\n");
for (String commandLine : commandLines) {
if (!StringUtils.isEmpty(commandLine)) {
actionList.add(converter.getAction(commandLine));
actionList.add(converter.getAction(commandLine, deviceCommand.getDevice()));
}
}
return actionList;
Expand All @@ -65,21 +67,29 @@ private enum ActionConverter {
//generate action by command type
ADBShell() {
@Override
public DeviceAction getAction(String commandline) {
DeviceAction deviceAction = new DeviceAction("Android", "execCommandOnDevice");
public DeviceAction getAction(String commandline, String deviceType) {
String type = deviceType;
if (StringUtils.isEmpty(type)) {
type = Const.OperatedDevice.ANDROID;
}
DeviceAction deviceAction = new DeviceAction(type, "execCommandOnDevice");
deviceAction.getArgs().add(commandline);
return deviceAction;
}
},
AgentShell() {
@Override
public DeviceAction getAction(String commandline) {
DeviceAction deviceAction = new DeviceAction("Windows", "execCommandOnAgent");
public DeviceAction getAction(String commandline, String deviceType) {
String type = deviceType;
if (StringUtils.isEmpty(type)) {
type = Const.OperatedDevice.ANDROID;
}
DeviceAction deviceAction = new DeviceAction(type, "execCommandOnAgent");
deviceAction.getArgs().add(commandline);
return deviceAction;
}
};

public abstract DeviceAction getAction(String commandline);
public abstract DeviceAction getAction(String commandline, String deviceType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.microsoft.hydralab.common.entity.common.DeviceInfo;
import com.microsoft.hydralab.common.entity.common.TestRunDevice;
import com.microsoft.hydralab.common.management.device.DeviceDriver;
import com.microsoft.hydralab.common.util.Const;
import com.microsoft.hydralab.common.util.HydraLabRuntimeException;
import com.microsoft.hydralab.common.util.ThreadUtils;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -24,6 +25,7 @@
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* @author zhoule
Expand All @@ -35,20 +37,25 @@ public class ActionExecutor {
/**
* the implementation of supported actions should not be overload
*/
private Set<String> actionTypes =
private final Set<String> actionTypes =
Set.of("setProperty", "setDefaultLauncher", "backToHome", "changeGlobalSetting",
"changeSystemSetting", "execCommandOnDevice", "execCommandOnAgent", "pushFileToDevice",
"pullFileFromDevice");

public List<Exception> doActions(@NotNull DeviceDriver deviceDriverManager,
@NotNull TestRunDevice testRunDevice,
@NotNull Logger logger,
@NotNull Map<String, List<DeviceAction>> actions, @NotNull String when) {
@NotNull Map<String, List<DeviceAction>> actions, @NotNull String when, boolean runOnAgentOnly) {
List<Exception> exceptions = new ArrayList<>();
//filter todoActions
List<DeviceAction> todoActions = actions.getOrDefault(when, new ArrayList<>()).stream()
.filter(deviceAction -> actionTypes.contains(deviceAction.getMethod()))
.collect(Collectors.toList());
Stream<DeviceAction> legalActionStream = actions.getOrDefault(when, new ArrayList<>()).stream()
.filter(deviceAction -> actionTypes.contains(deviceAction.getMethod()) && StringUtils.isNotEmpty(deviceAction.getDeviceType()));
if (runOnAgentOnly) {
legalActionStream = legalActionStream.filter(deviceAction -> Const.OperatedDevice.AGENT.equalsIgnoreCase(deviceAction.getDeviceType()));
} else {
legalActionStream = legalActionStream.filter(deviceAction -> testRunDevice.getDeviceInfo().getType().equalsIgnoreCase(deviceAction.getDeviceType()));
}
List<DeviceAction> todoActions = legalActionStream.collect(Collectors.toList());

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

public void doAction(@NotNull DeviceDriver deviceDriverManager,
private void doAction(@NotNull DeviceDriver deviceDriverManager,
@NotNull TestRunDevice testRunDevice,
@NotNull Logger logger,
@NotNull DeviceAction deviceAction)
throws InvocationTargetException, IllegalAccessException {
if (!actionTypes.contains(deviceAction.getMethod())) {
return;
}
if (!StringUtils.isEmpty(deviceAction.getDeviceType()) && !testRunDevice.getDeviceInfo().getType().equalsIgnoreCase(deviceAction.getDeviceType())){
return;
}
DeviceInfo deviceInfo = testRunDevice.getDeviceInfo();
logger.info("Start to analysis action type! Current action is {}", deviceAction.getMethod());
Method method = Arrays.stream(deviceDriverManager.getClass().getMethods())
Expand Down Expand Up @@ -122,5 +126,4 @@ private Object[] convertArgs(@NotNull DeviceInfo deviceInfo, @NotNull Logger log
}
return methodArgs;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -336,14 +336,15 @@ public Logger getDeviceLogger(TestRunDevice testRunDevice) {
}

public List<Exception> doActions(TestRunDevice testRunDevice, Logger logger, Map<String, List<DeviceAction>> deviceActions, String when) {
List<Exception> exceptions = actionExecutor.doActions(deviceDriverManager, testRunDevice, logger, deviceActions, when, true);

if (testRunDevice instanceof TestRunDeviceCombo) {
List<Exception> exceptions = new ArrayList<>();
for (TestRunDevice testRunDevice1 : ((TestRunDeviceCombo) testRunDevice).getDevices()) {
exceptions.addAll(actionExecutor.doActions(deviceDriverManager, testRunDevice1, logger, deviceActions, when));
for (TestRunDevice subTestRunDevice : ((TestRunDeviceCombo) testRunDevice).getDevices()) {
exceptions.addAll(actionExecutor.doActions(deviceDriverManager, subTestRunDevice, logger, deviceActions, when, false));
}
return exceptions;
} else {
return actionExecutor.doActions(deviceDriverManager, testRunDevice, logger, deviceActions, when);
exceptions.addAll(actionExecutor.doActions(deviceDriverManager, testRunDevice, logger, deviceActions, when, false));
}
return exceptions;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,23 @@ void createAndExecuteActions() throws InvocationTargetException, IllegalAccessEx
DeviceAction action1 = JSONObject.parseObject(actionJson.toJSONString(), DeviceAction.class);
List<String> args1 = List.of("paramA", "paramB");
action1.setArgs(args1);
actionExecutor.doAction(deviceDriver, new TestRunDevice(deviceInfo, deviceInfo.getType()), baseLogger, action1);
verify(deviceDriver).setProperty(deviceInfo, args1.get(0), args1.get(1), baseLogger);
List<DeviceAction> actions1 = new ArrayList<>();
actions1.add(action1);
List<Exception> exceptions1 = actionExecutor.doActions(deviceDriver, new TestRunDevice(deviceInfo, deviceInfo.getType()), baseLogger,
Map.of(DeviceAction.When.SET_UP, actions1), DeviceAction.When.SET_UP, true);
Assertions.assertEquals(0, exceptions1.size(), () -> exceptions1.get(0).getMessage());
verify(deviceDriver, times(0)).setProperty(deviceInfo, args1.get(0), args1.get(1), baseLogger);

DeviceAction action2 = new DeviceAction("Android", "changeGlobalSetting");
List<String> args2 = List.of("paramC", "paramD");
action2.setArgs(args2);
List<DeviceAction> actions = new ArrayList<>();
actions.add(action1);
actions.add(action2);
List<Exception> exceptions = actionExecutor.doActions(deviceDriver, new TestRunDevice(deviceInfo, deviceInfo.getType()), baseLogger,
Map.of(DeviceAction.When.SET_UP, actions), DeviceAction.When.SET_UP);
Assertions.assertEquals(0, exceptions.size(), () -> exceptions.get(0).getMessage());
verify(deviceDriver, times(2)).setProperty(deviceInfo, args1.get(0), args1.get(1), baseLogger);
List<DeviceAction> actions2 = new ArrayList<>();
actions2.add(action1);
actions2.add(action2);
List<Exception> exceptions2 = actionExecutor.doActions(deviceDriver, new TestRunDevice(deviceInfo, deviceInfo.getType()), baseLogger,
Map.of(DeviceAction.When.SET_UP, actions2), DeviceAction.When.SET_UP, false);
Assertions.assertEquals(0, exceptions2.size(), () -> exceptions2.get(0).getMessage());
verify(deviceDriver, times(1)).setProperty(deviceInfo, args1.get(0), args1.get(1), baseLogger);
verify(deviceDriver, times(1)).changeGlobalSetting(deviceInfo, args2.get(0), args2.get(1), baseLogger);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,10 @@ interface TestDeviceTag {
String TERTIARY_PHONE = "TERTIARY_PHONE";
String PRIMARY_PC = "PRIMARY_PC";
}

interface OperatedDevice {
String ANY = "Any";
String AGENT = "Agent";
String ANDROID = "Android";
}
}