Skip to content

Commit 48bf344

Browse files
ci: add first Flash test
1 parent fa049a6 commit 48bf344

File tree

5 files changed

+145
-25
lines changed

5 files changed

+145
-25
lines changed

bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/DfuCommandsUtil.java

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77
import java.io.File;
88
import java.util.ArrayList;
99
import java.util.Arrays;
10+
import java.util.HashMap;
1011
import java.util.List;
1112
import java.util.Map;
1213
import java.util.Map.Entry;
14+
import java.util.Objects;
15+
import java.util.stream.Collectors;
16+
import java.util.stream.Stream;
1317

1418
import org.eclipse.cdt.utils.CommandLineUtil;
1519
import org.eclipse.core.resources.IProject;
@@ -129,17 +133,38 @@ public static void flashDfuBins(ILaunchConfiguration configuration, IProject pro
129133
commands.addAll(flashCommandList);
130134
File workingDir = null;
131135
workingDir = new File(project.getLocationURI());
132-
Map<String, String> envMap = new IDFEnvironmentVariables().getSystemEnvMap();
133-
List<String> strings = new ArrayList<>(envMap.size());
134-
for (Entry<String, String> entry : envMap.entrySet())
136+
Map<String, String> idfEnvMap = new IDFEnvironmentVariables().getSystemEnvMap();
137+
138+
// Disable buffering of output
139+
idfEnvMap.put("PYTHONUNBUFFERED", "1"); //$NON-NLS-1$ //$NON-NLS-2$
140+
141+
// Update with the CDT build environment variables
142+
Map<String, String> environment = new HashMap<>(IDFUtil.getSystemEnv());
143+
environment.putAll(idfEnvMap);
144+
145+
Logger.log(environment.toString());
146+
147+
// Merge PATH and Path
148+
String mergedPath = Stream.of(environment.get("PATH"), environment.get("Path")).filter(Objects::nonNull) //$NON-NLS-1$ //$NON-NLS-2$
149+
.collect(Collectors.joining(";")); //$NON-NLS-1$
150+
151+
// Remove duplicate Path
152+
if (!mergedPath.isEmpty())
153+
{
154+
environment.put("PATH", mergedPath); //$NON-NLS-1$
155+
environment.remove("Path"); //$NON-NLS-1$
156+
}
157+
158+
List<String> strings = new ArrayList<>(environment.size());
159+
for (Entry<String, String> entry : environment.entrySet())
160+
135161
{
136162
StringBuilder buffer = new StringBuilder(entry.getKey());
137163
buffer.append('=').append(entry.getValue()); // $NON-NLS-1$
138164
strings.add(buffer.toString());
139165
}
140-
141-
String[] envArray = strings.toArray(new String[strings.size()]);
142166
Process p = null;
167+
String[] envArray = strings.toArray(new String[strings.size()]);
143168
try
144169
{
145170
p = DebugPlugin.exec(commands.toArray(new String[0]), workingDir, envArray);

bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -850,10 +850,30 @@ public static String resolveEnvVariable(String path)
850850

851851
public static Map<String, String> getSystemEnv()
852852
{
853-
Map<String, String> env = new HashMap<String, String>(System.getenv());
853+
Map<String, String> env = new HashMap<>(System.getenv());
854+
854855
String idfToolsPath = Platform.getPreferencesService().getString(IDFCorePlugin.PLUGIN_ID,
855856
IDFCorePreferenceConstants.IDF_TOOLS_PATH, IDFCorePreferenceConstants.IDF_TOOLS_PATH_DEFAULT, null);
856857
env.put(IDFCorePreferenceConstants.IDF_TOOLS_PATH, idfToolsPath);
858+
859+
// Merge Homebrew bin paths into PATH
860+
String existingPath = env.getOrDefault("PATH", ""); //$NON-NLS-1$ //$NON-NLS-2$
861+
StringBuilder newPath = new StringBuilder();
862+
863+
String[] brewPaths = { "/usr/local/bin", "/opt/homebrew/bin" }; //$NON-NLS-1$ //$NON-NLS-2$
864+
865+
for (String brewPath : brewPaths)
866+
{
867+
if (Files.exists(Paths.get(brewPath)) && !existingPath.contains(brewPath))
868+
{
869+
newPath.append(brewPath).append(":"); //$NON-NLS-1$
870+
}
871+
}
872+
873+
// Append the original PATH at the end
874+
newPath.append(existingPath);
875+
env.put("PATH", newPath.toString()); //$NON-NLS-1$
876+
857877
return env;
858878
}
859879

@@ -885,11 +905,14 @@ public static void closeWelcomePage(IWorkbenchWindow activeww)
885905

886906
/**
887907
* Checks if esp_detect_config.py exists in the expected OpenOCD tools directory.
908+
*
888909
* @return true if esp_detect_config.py exists, false otherwise.
889910
*/
890-
public static boolean espDetectConfigScriptExists() {
911+
public static boolean espDetectConfigScriptExists()
912+
{
891913
String openocdBinDir = getOpenOCDLocation();
892-
if (StringUtil.isEmpty(openocdBinDir)) {
914+
if (StringUtil.isEmpty(openocdBinDir))
915+
{
893916
return false;
894917
}
895918
File binDir = new File(openocdBinDir);
@@ -900,12 +923,14 @@ public static boolean espDetectConfigScriptExists() {
900923
}
901924

902925
/**
903-
* Runs the esp_detect_config.py script using the OPENOCD_SCRIPTS environment variable to locate the script and config files.
904-
* Returns the JSON output as a string, or null on error.
926+
* Runs the esp_detect_config.py script using the OPENOCD_SCRIPTS environment variable to locate the script and
927+
* config files. Returns the JSON output as a string, or null on error.
905928
*/
906-
public static String runEspDetectConfigScript() {
929+
public static String runEspDetectConfigScript()
930+
{
907931
String openocdBinDir = getOpenOCDLocation();
908-
if (StringUtil.isEmpty(openocdBinDir)) {
932+
if (StringUtil.isEmpty(openocdBinDir))
933+
{
909934
Logger.log("OpenOCD location could not be determined."); //$NON-NLS-1$
910935
return null;
911936
}
@@ -915,46 +940,55 @@ public static String runEspDetectConfigScript() {
915940
File scriptsDir = Paths.get(openocdRoot.getPath(), "share", "openocd", "scripts").toFile(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
916941
File toolsDir = Paths.get(openocdRoot.getPath(), "share", "openocd", "espressif", "tools").toFile(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
917942
File configFile = new File(scriptsDir, "esp-config.json"); //$NON-NLS-1$
918-
if (!configFile.exists()) {
943+
if (!configFile.exists())
944+
{
919945
Logger.log("esp-config.json not found at expected location: " + configFile.getAbsolutePath()); //$NON-NLS-1$
920946
return null;
921947
}
922-
if (!espDetectConfigScriptExists()) {
923-
Logger.log("esp_detect_config.py not found at expected location: " + new File(toolsDir, "esp_detect_config.py").getAbsolutePath()); //$NON-NLS-1$ //$NON-NLS-2$
948+
if (!espDetectConfigScriptExists())
949+
{
950+
Logger.log("esp_detect_config.py not found at expected location: " //$NON-NLS-1$
951+
+ new File(toolsDir, "esp_detect_config.py").getAbsolutePath()); //$NON-NLS-1$
924952
return null;
925953
}
926954
String scriptPath = new File(toolsDir, "esp_detect_config.py").getAbsolutePath(); //$NON-NLS-1$
927955
String configPath = configFile.getAbsolutePath();
928956
String openocdExecutable = Platform.getOS().equals(Platform.OS_WIN32) ? "openocd.exe" : "openocd"; //$NON-NLS-1$ //$NON-NLS-2$
929957
File openocdBin = new File(openocdBinDir, openocdExecutable);
930-
if (!openocdBin.exists()) {
958+
if (!openocdBin.exists())
959+
{
931960
Logger.log("OpenOCD binary not found at expected location."); //$NON-NLS-1$
932961
return null;
933962
}
934-
963+
935964
String idfPythonEnvPath = IDFUtil.getIDFPythonEnvPath();
936-
if (StringUtil.isEmpty(idfPythonEnvPath)) {
965+
if (StringUtil.isEmpty(idfPythonEnvPath))
966+
{
937967
Logger.log("IDF_PYTHON_ENV_PATH could not be found."); //$NON-NLS-1$
938968
return null;
939969
}
940-
970+
941971
List<String> command = new ArrayList<>();
942972
command.add(idfPythonEnvPath);
943973
command.add(scriptPath);
944974
command.add("--esp-config"); //$NON-NLS-1$
945975
command.add(configPath);
946976
command.add("--oocd");//$NON-NLS-1$
947977
command.add(openocdBin.getAbsolutePath());
948-
978+
949979
Map<String, String> env = new IDFEnvironmentVariables().getSystemEnvMap();
950-
try {
980+
try
981+
{
951982
IStatus status = new ProcessBuilderFactory().runInBackground(command, null, env);
952-
if (status == null) {
983+
if (status == null)
984+
{
953985
Logger.log("esp_detect_config.py did not return a result."); //$NON-NLS-1$
954986
return null;
955987
}
956988
return status.getMessage();
957-
} catch (Exception e) {
989+
}
990+
catch (Exception e)
991+
{
958992
Logger.log(e);
959993
return null;
960994
}

tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectFlashProcessTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
import java.io.IOException;
88

99
import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
10+
import static org.eclipse.swtbot.swt.finder.waits.Conditions.*;
1011
import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
12+
import org.eclipse.swtbot.swt.finder.widgets.SWTBotCheckBox;
13+
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
1114
import org.junit.After;
1215
import org.junit.BeforeClass;
1316
import org.junit.FixMethodOrder;
@@ -19,6 +22,8 @@
1922
import com.espressif.idf.ui.test.common.utility.TestWidgetWaitUtility;
2023
import com.espressif.idf.ui.test.operations.EnvSetupOperations;
2124
import com.espressif.idf.ui.test.operations.ProjectTestOperations;
25+
import com.espressif.idf.ui.test.operations.selectors.LaunchBarConfigSelector;
26+
import com.espressif.idf.ui.test.operations.selectors.LaunchBarTargetSelector;
2227

2328
/**
2429
* Test class to test the Flash process
@@ -58,7 +63,11 @@ public void givenNewProjectCreatedBuiltWhenSelectSerialPortWhenFlashThenCheckFla
5863
Fixture.givenNewEspressifIDFProjectIsSelected("EspressIf", "Espressif IDF Project");
5964
Fixture.givenProjectNameIs("NewProjectFlashTest");
6065
Fixture.whenNewProjectIsSelected();
66+
Fixture.whenTurnOffOpenSerialMonitorAfterFlashingInLaunchConfig();
6167
Fixture.whenProjectIsBuiltUsingContextMenu();
68+
Fixture.whenSelectLaunchTargetSerialPort();
69+
Fixture.whenFlashProject();
70+
Fixture.thenVerifyFlashDoneSuccessfully();
6271
}
6372

6473
private static class Fixture
@@ -73,6 +82,7 @@ private static void loadEnv() throws Exception
7382
bot = WorkBenchSWTBot.getBot();
7483
EnvSetupOperations.setupEspressifEnv(bot);
7584
bot.sleep(1000);
85+
ProjectTestOperations.deleteAllProjects(bot);
7686
}
7787

7888
private static void givenNewEspressifIDFProjectIsSelected(String category, String subCategory)
@@ -104,5 +114,47 @@ private static void cleanTestEnv()
104114
ProjectTestOperations.closeAllProjects(bot);
105115
ProjectTestOperations.deleteAllProjects(bot);
106116
}
117+
118+
private static void whenSelectLaunchTargetSerialPort() throws Exception
119+
{
120+
LaunchBarTargetSelector targetSelector = new LaunchBarTargetSelector(bot);
121+
targetSelector.clickEdit();
122+
TestWidgetWaitUtility.waitForDialogToAppear(bot, "New ESP Target", 20000);
123+
SWTBotShell shell = bot.shell("New ESP Target");
124+
bot.comboBoxWithLabel("Serial Port:").setSelection("/dev/ttyUSB1 Dual RS232-HS");
125+
TestWidgetWaitUtility.waitForOperationsInProgressToFinishSync(bot);
126+
shell.setFocus();
127+
bot.button("Finish").click();
128+
}
129+
130+
private static void whenTurnOffOpenSerialMonitorAfterFlashingInLaunchConfig() throws Exception
131+
{
132+
LaunchBarConfigSelector configSelector = new LaunchBarConfigSelector(bot);
133+
configSelector.clickEdit();
134+
TestWidgetWaitUtility.waitForDialogToAppear(bot, "Edit Configuration", 20000);
135+
bot.cTabItem("Main").show();
136+
bot.cTabItem("Main").setFocus();
137+
SWTBotCheckBox checkBox = bot.checkBox("Open Serial Monitor After Flashing");
138+
if (checkBox.isChecked()) {
139+
checkBox.click();
140+
}
141+
bot.button("OK").click();
142+
}
143+
144+
private static void whenFlashProject() throws IOException
145+
{
146+
ProjectTestOperations.launchCommandUsingContextMenu(projectName, bot, "Run Configurations...");
147+
TestWidgetWaitUtility.waitForDialogToAppear(bot, "Run Configurations", 10000);
148+
bot.tree().getTreeItem("ESP-IDF Application").select();
149+
bot.tree().getTreeItem("ESP-IDF Application").expand();
150+
bot.tree().getTreeItem("ESP-IDF Application").getNode(projectName).select();
151+
bot.waitUntil(widgetIsEnabled(bot.button("Run")), 5000);
152+
bot.button("Run").click();
153+
}
154+
155+
private static void thenVerifyFlashDoneSuccessfully() throws Exception
156+
{
157+
ProjectTestOperations.waitForProjectFlash(bot);
158+
}
107159
}
108160
}

tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/ProjectTestOperations.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public class ProjectTestOperations
5252
{
5353

5454
private static final String DEFAULT_PROJECT_BUILD_WAIT_PROPERTY = "default.project.build.wait";
55+
56+
private static final String DEFAULT_FLASH_WAIT_PROPERTY = "default.project.flash.wait";
5557

5658
private static final Logger logger = LoggerFactory.getLogger(ProjectTestOperations.class);
5759

@@ -90,6 +92,14 @@ public static void waitForProjectBuild(SWTWorkbenchBot bot) throws IOException
9092
DefaultPropertyFetcher.getLongPropertyValue(DEFAULT_PROJECT_BUILD_WAIT_PROPERTY, 300000));
9193
}
9294

95+
public static void waitForProjectFlash(SWTWorkbenchBot bot) throws IOException
96+
{
97+
SWTBotView view = bot.viewByPartName("Console");
98+
view.setFocus();
99+
TestWidgetWaitUtility.waitUntilViewContains(bot, "Hard resetting via RTS pin...", view,
100+
DefaultPropertyFetcher.getLongPropertyValue(DEFAULT_FLASH_WAIT_PROPERTY, 120000));
101+
}
102+
93103
public static void waitForProjectNewComponentInstalled(SWTWorkbenchBot bot) throws IOException
94104
{
95105
SWTBotView consoleView = viewConsole("ESP-IDF Console", bot);

tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/selectors/LaunchBarTargetSelector.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ public void click(int x, int y)
7070

7171
public void clickEdit()
7272
{
73-
click();
74-
bot().buttonWithId(LaunchBarWidgetIds.EDIT).click(); // $NON-NLS-1$
73+
bot().canvasWithId(LaunchBarWidgetIds.EDIT).click(); // $NON-NLS-1$
7574
}
7675

7776
private void clickOnInternalWidget(int x, int y, Widget internalWidget)

0 commit comments

Comments
 (0)