TestExecWindow
MyToolWindowControl.xaml.cs
//------------------------------------------------------------------------------
// Copyright(C) 2022 Gerald Fahrnholz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Contact: http://www.gerald-fahrnholz.eu/impressum.php
//------------------------------------------------------------------------------
using Microsoft.VisualStudio.RpcContracts.FileSystem;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls;
namespace TestExecWin_VS2022
{
class MyListItem
{
public int idx;
public string displayString;
public MyListItem(int in_idx, string in_displayString)
{
idx = in_idx;
displayString = in_displayString;
}
public override string ToString()
{
return displayString;
}
};
public partial class MyToolWindowControl : UserControl
{
private ProjectInfo m_projectInfo = new ProjectInfo();
private bool m_useDebugger = false;
enum RunMode { TEST_GROUPS, TEST_FUNCS, TEST_APPS, TEST_STARTUP_PROJECT };
private RunMode m_curRunMode = RunMode.TEST_STARTUP_PROJECT;
private int[] m_numExecutedTests = new int[] { 0, 0, 0, 0 };
private int[] m_numFailedTests = new int[] { 0, 0, 0, 0 };
private int[] m_totalNumTestsToExecute = new int[] { 0, 0, 0, 0 };
private bool m_stoppedByUser = false;
enum WaitMode { WAIT_ENDLESS, WAIT_30_SEC, WAIT_1_MIN, WAIT_2_MIN, WAIT_5_MIN, WAIT_10_MIN, WAIT_20_MIN, WAIT_30_MIN, WAIT_40_MIN, WAIT_60_MIN };
private WaitMode m_waitMode = (WaitMode)Services.GetOptions().IdxMaxWaitTime;
enum ColVisibility { BOTH, LEFT, RIGHT };
ColVisibility m_colVisibility = (ColVisibility)Services.GetOptions().IdxGroupsAndFuncs;
private int m_idxRunAllTestGroups = -1;
private int m_idxRunAllTestFuncs = -1;
private int m_idxRunAllTestApps = -1;
enum ExpImpMode { EXPORT_TO_FILE = 1, IMPPORT_FROM_FILE, IMPORT_FROM_SOLUTION, IMPORT_TEST_GROUPS_FROM_STARTUP_PROJECT, IMPORT_VISIBLE_TEST_FUNCS_FROM_STARTUP_PROJECT };
private List<string> m_currentTestApps = new List<string>();
private List<string> m_dataDescTestApps;
private int m_idxCurrentTestApps = Services.GetOptions().IdxCurrentTestApps;
private readonly System.Windows.Media.Brush m_originalBrushWindow;
private readonly System.Windows.Media.Brush m_originalBrushTextBlock;
private readonly System.Windows.Forms.Timer m_executionTimer = new System.Windows.Forms.Timer();
private readonly System.Windows.Threading.DispatcherTimer m_refreshTimer = new System.Windows.Threading.DispatcherTimer();
private bool m_refreshTimerIsActive = false;
// Is basically a copy of m_projectInfo.testGroups/testFuncs but this copy may be sorted
// according to user requests, The original collection stores the elements in the
// order as read from files.
System.Collections.Generic.List<TestGroupEntry> m_testGroups;
System.Collections.Generic.List<TestFuncEntry> m_testFuncs;
HashSet<string> m_selectedTestGroups;
enum SortOrder { AS_READ_FROM_FILE, REVERSE_READ, ALPHA, REVERSE_ALPHA };
SortOrder m_sortOrder = (SortOrder)Services.GetOptions().IdxSortOrder;
bool m_optionsVisible = Services.GetOptions().OptionsAreVisible;
bool m_logVisible = Services.GetOptions().LogIsVisible;
enum State { IDLE, RUNNING, SUCCEEDED, FAILED };
private State[] m_state = new State[] { State.IDLE, State.IDLE, State.IDLE, State.IDLE };
//----- Construction and initialization -----
public MyToolWindowControl()
{
InitializeComponent();
m_originalBrushWindow = mainGrid.Background;
m_originalBrushTextBlock = txtInfoStarArgTestGroup.Background;
m_executionTimer.Enabled = false;
m_executionTimer.Tick += new EventHandler(OnExecutionTimeout);
for (int i = 0; i < 4; ++i)
{
m_state[i] = State.IDLE;
}
MyGlobals.myToolWindowControl = this;
MyGlobals.myMainEvents.OnGuiIsStarted();
InitControls();
}
private void InitControls()
{
lstTestGroups.SelectionMode = SelectionMode.Extended;
lstTestFuncs.SelectionMode = SelectionMode.Extended;
txtInfoDefaultArgs.Background = m_originalBrushTextBlock;
txtInfoDefaultArgs.Foreground = System.Windows.Media.Brushes.Black;
// Get user options
var options = Services.GetOptions();
{
List<string> data = new List<string>();
data.Add("");
data.Add("BOOST options:");
data.Add("--detect_memory_leak=0");
data.Add("--log_level=test_suite");
data.Add("--log_sink=<PATH_TO_LOGFILE>");
data.Add("");
data.Add("TTB Runner options:");
data.Add("-- -checkForMemLeaks OFF");
data.Add("-- -help");
data.Add("");
data.Add("custom options:");
data.Add("-- -prefixEvents TTB_EXP");
cbxDefaultArgs.ItemsSource = data;
cbxDefaultArgs.SelectedIndex = 0;
cbxDefaultArgs.IsEditable = true;
cbxDefaultArgs.Text = options.StartArgs;
}
{
List<string> data = new List<string>();
data.Add("test groups and funcs");
data.Add("only test groups");
data.Add("only test funcs");
//var comboBox = sender as ComboBox;
cbxColVisibility.ItemsSource = data;
cbxColVisibility.SelectedIndex = (int)m_colVisibility;
}
{
List<string> data = new List<string>();
data.Add("sort as read");
data.Add("reverse read order");
data.Add("sort A->Z");
data.Add("sort Z->A");
cbxSortOrder.ItemsSource = data;
cbxSortOrder.SelectedIndex = (int)m_sortOrder;
}
{
List<string> data = new List<string>();
data.Add("show log");
data.Add("hide log");
cbxLogVisibility.ItemsSource = data;
cbxLogVisibility.SelectedIndex = m_logVisible ? 0 : 1;
}
{
List<string> data = new List<string>();
data.Add("regular output");
data.Add("verbous output");
data.Add("detailed output");
int outputLevel = options.IdxOutputLevel + 1;
cbxOutputLevel.ItemsSource = data;
cbxOutputLevel.SelectedIndex = outputLevel - 1;
MyGlobals.myMainEvents.OnSetOutputLevel(outputLevel);
}
{
List<string> data = new List<string>();
data.Add("leak check");
data.Add("no leak check");
cbxMemLeakCheck.ItemsSource = data;
bool leakCheck = options.CheckForMemoryLeaks;
cbxMemLeakCheck.SelectedIndex = leakCheck ? 0 : 1;
MyGlobals.myExecutor.SetMemLeakCheck(leakCheck);
}
{
List<string> data = new List<string>();
data.Add("wait for test app without time limit");
data.Add("wait for test app max 30 sec");
data.Add("wait for test app max 1 min");
data.Add("wait for test app max 2 min");
data.Add("wait for test app max 5 min");
data.Add("wait for test app max 10 min");
data.Add("wait for test app max 20 min");
data.Add("wait for test app max 30 min");
data.Add("wait for test app max 40 min");
data.Add("wait for test app max 60 min");
cbxMaxExecutionTime.ItemsSource = data;
cbxMaxExecutionTime.SelectedIndex = (int)m_waitMode;
}
{
m_dataDescTestApps = new List<string>();
m_dataDescTestApps.Add(options.GetDescTestAppsForIdx(0));
m_dataDescTestApps.Add(options.GetDescTestAppsForIdx(1));
m_dataDescTestApps.Add(options.GetDescTestAppsForIdx(2));
m_dataDescTestApps.Add(options.GetDescTestAppsForIdx(3));
m_dataDescTestApps.Add(options.GetDescTestAppsForIdx(4));
m_dataDescTestApps.Add(options.GetDescTestAppsForIdx(5));
m_dataDescTestApps.Add(options.GetDescTestAppsForIdx(6));
m_dataDescTestApps.Add(options.GetDescTestAppsForIdx(7));
cbxDescTestApps.ItemsSource = m_dataDescTestApps;
cbxDescTestApps.SelectedIndex = m_idxCurrentTestApps;
cbxDescTestApps.IsEditable = true;
}
}
//----- Called from other classes -----
public void SomeSettingsExternallyChanged()
{
// Redirect to main GUI thread
WriteLine(2, "SettingsExternallyChanged: passing to gui thread...");
Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.Run(async delegate {
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
var options = Services.GetOptions();
cbxDefaultArgs.Text = options.StartArgs;
m_optionsVisible = Services.GetOptions().OptionsAreVisible;
RefreshDisplay();
});
}
public void TriggerDelayedRefresh()
{
// Redirect to main GUI thread
WriteLine(2, "TriggerDelayedRefresh: passing to gui thread...");
Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.Run(async delegate {
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
TriggerDelayedRefreshFromGuiThread();
});
}
internal void SetTestInfo(ProjectInfo in_projectInfo)
{
m_projectInfo = in_projectInfo;
for (int i = 0; i < 4; ++i)
{
m_state[i] = State.IDLE;
m_numFailedTests[i] = 0;
m_numExecutedTests[i] = 0;
m_totalNumTestsToExecute[i] = 0;
}
if (m_projectInfo != null)
{
txtInfo.Text = m_projectInfo.project + " - " + m_projectInfo.config + " " + m_projectInfo.platform;
RefreshTestGroupList();
RefreshTestFuncList();
}
RefreshDisplay();
}
public void BuildTerminated(bool success)
{
if (m_stoppedByUser)
{
WriteLine(1, "Build terminated, success=" + success.ToString() + ", Test is aborted (stopped by user)");
TestTerminatedWithinGuiThread(false, "", "", false, new TimeSpan(0));
return;
}
if (success)
{
WriteLine(2, "Build succeeded, now starting test...");
if (m_curRunMode == RunMode.TEST_STARTUP_PROJECT)
{
StartProcess(m_projectInfo.GetExePath(), cbxDefaultArgs.Text, m_projectInfo.targetDirPath);
}
else if (m_curRunMode == RunMode.TEST_GROUPS)
{
if (m_idxRunAllTestGroups == -1)
{
StartProcess(m_projectInfo.GetExePath(), txtStartArgTestGroup.Text + " " + cbxDefaultArgs.Text, m_projectInfo.targetDirPath);
}
else // start all test groups
{
StartTestGroup(0);
}
}
else if (m_curRunMode == RunMode.TEST_FUNCS)
{
if (m_idxRunAllTestFuncs == -1)
{
StartProcess(m_projectInfo.GetExePath(), txtStartArgTestFunc.Text + " " + cbxDefaultArgs.Text, m_projectInfo.targetDirPath);
}
else // start all test funcs
{
StartTestFunc(0);
}
}
else
{
WriteLine(2, "WARNING: no longer prepared for testing, ignored Build succeeded event!");
}
}
else // build failed, do not start testing
{
if (TestIsRunning())
{
WriteLine(1, "ERROR: Build failed or could not be started, test is aborted!");
SetState(false);
}
else
{
WriteLine(2, "WARNING: no longer prepared for testing, ignored Build failed event!");
}
}
}
//----- EventHandlers for GUI controls -----
private void chkUseDebugger_CheckBoxChanged(object sender, RoutedEventArgs e)
{
try
{
m_useDebugger = (bool)chkUseDebugger.IsChecked;
RefreshState();
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
private void btnRunTestAll_Click(object sender, RoutedEventArgs e)
{
try
{
if (m_useDebugger)
{
MyGlobals.myMainEvents.OnStartDebugging(cbxDefaultArgs.Text);
}
else // regular execution
{
if (m_state[(int)RunMode.TEST_STARTUP_PROJECT] == State.RUNNING)
{
StopExecution();
}
else
{
InitForTestExecution(RunMode.TEST_STARTUP_PROJECT, 1);
RefreshState();
if (Services.GetOptions().BuildSolutionBeforeStartingTest)
{
MyGlobals.myMainEvents.OnStartBuilding();
}
else
{
StartProcess(m_projectInfo.GetExePath(), cbxDefaultArgs.Text, m_projectInfo.targetDirPath);
}
}
}
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
MyGlobals.myMainEvents.OnTestTerminated(false, m_projectInfo.GetExePath(), false, new TimeSpan(0));
}
}
private void btnOpenProtocolFile_Click(object sender, RoutedEventArgs e)
{
MyGlobals.myMainEvents.OnOpenProtocolFile();
}
private void btnRefreshAll_Click(object sender, RoutedEventArgs e)
{
MyGlobals.myMainEvents.OnRefreshNow();
}
private void btnHelp_Click(object sender, RoutedEventArgs e)
{
try
{
string assemblyPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
WriteLine(2, "Info: assemblyPath = " + assemblyPath);
string dirPath = new System.IO.FileInfo(assemblyPath).Directory.FullName;
string pathToHelpFile = dirPath + @"\Resources\index.html";
//string pathToHelpFile = System.Reflection.Assembly.GetExecutingAssembly()..Location + @".index.html";
WriteLine(1, "Trying to open help file " + pathToHelpFile);
// Open page with default web browser
System.Diagnostics.Process.Start(pathToHelpFile);
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
private void btnMoreOptions_Click(object sender, RoutedEventArgs e)
{
m_optionsVisible = !m_optionsVisible;
Services.GetOptions().OptionsAreVisible = m_optionsVisible;
Services.GetOptions().SaveSettingsFromToolWindow();
RefreshDisplay();
}
private void cbxDefaultArgs_TextChanged(object sender, EventArgs e)
{
WriteLine(3, "cbxDefaultArgs_TextChanged: Storing new args=" + cbxDefaultArgs.Text);
Services.GetOptions().StartArgs = cbxDefaultArgs.Text;
Services.GetOptions().SaveSettingsFromToolWindow();
}
private void cbxColVisibility_SelectionChanged(object sender, EventArgs e)
{
var comboBox = sender as ComboBox;
m_colVisibility = (ColVisibility)comboBox.SelectedIndex;
Services.GetOptions().IdxGroupsAndFuncs = comboBox.SelectedIndex;
Services.GetOptions().SaveSettingsFromToolWindow();
SetColVisibility();
}
private void cbxSortOrder_SelectionChanged(object sender, EventArgs e)
{
var comboBox = sender as ComboBox;
m_sortOrder = (SortOrder)comboBox.SelectedIndex;
Services.GetOptions().IdxSortOrder = comboBox.SelectedIndex;
Services.GetOptions().SaveSettingsFromToolWindow();
RefreshTestGroupList();
RefreshTestFuncList();
}
private void cbxLogVisibility_SelectionChanged(object sender, EventArgs e)
{
var comboBox = sender as ComboBox;
m_logVisible = (comboBox.SelectedIndex == 0);
Services.GetOptions().LogIsVisible = m_logVisible;
Services.GetOptions().SaveSettingsFromToolWindow();
RefreshDisplay();
}
private void cbxMaxExecutionTime_SelectionChanged(object sender, EventArgs e)
{
var comboBox = sender as ComboBox;
m_waitMode = (WaitMode)comboBox.SelectedIndex;
Services.GetOptions().IdxMaxWaitTime = comboBox.SelectedIndex;
Services.GetOptions().SaveSettingsFromToolWindow();
}
private void cbxMemLeakCheck_SelectionChanged(object sender, EventArgs e)
{
var comboBox = sender as ComboBox;
bool leakCheck = (comboBox.SelectedIndex == 0);
Services.GetOptions().CheckForMemoryLeaks = leakCheck;
Services.GetOptions().SaveSettingsFromToolWindow();
MyGlobals.myExecutor.SetMemLeakCheck(leakCheck);
}
private void cbxOutputLevel_SelectionChanged(object sender, EventArgs e)
{
var comboBox = sender as ComboBox;
Services.GetOptions().IdxOutputLevel = comboBox.SelectedIndex;
Services.GetOptions().SaveSettingsFromToolWindow();
MyGlobals.myMainEvents.OnSetOutputLevel(comboBox.SelectedIndex + 1);
}
private void lstTestGroups_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (lstTestGroups.SelectedItem == null)
return;
txtStartArgTestGroup.Text = "";
m_selectedTestGroups.Clear();
if (m_projectInfo.appType == AppType.BOOST) // --run_test=suite1 --run_test=suite2 ...
{
foreach (MyListItem listItem in lstTestGroups.SelectedItems)
{
txtStartArgTestGroup.Text += m_testGroups[listItem.idx].GetCmdString() + " ";
m_selectedTestGroups.Add(m_testGroups[listItem.idx].GetTestGroupHierarchyString());
}
}
else // assume TTB, -selectTestFile file1,file2,file3
{
txtStartArgTestGroup.Text = "-selectTestFile ";
string sep = "";
foreach (MyListItem listItem in lstTestGroups.SelectedItems)
{
txtStartArgTestGroup.Text += sep + m_testGroups[listItem.idx].GetTestGroupHierarchyString();
m_selectedTestGroups.Add(m_testGroups[listItem.idx].GetTestGroupHierarchyString());
sep = ",";
}
}
RefreshTestFuncList();
}
private void btnRunSelectedTestGroup_Click(object sender, RoutedEventArgs e)
{
try
{
if (m_useDebugger)
{
MyGlobals.myMainEvents.OnStartDebugging(txtStartArgTestGroup.Text + " " + cbxDefaultArgs.Text);
}
else // regular execution
{
if (m_state[(int)RunMode.TEST_GROUPS] == State.RUNNING)
{
StopExecution();
}
else
{
InitForTestExecution(RunMode.TEST_GROUPS, 1);
RefreshState();
if (Services.GetOptions().BuildSolutionBeforeStartingTest)
{
MyGlobals.myMainEvents.OnStartBuilding();
}
else
{
StartProcess(m_projectInfo.GetExePath(), txtStartArgTestGroup.Text + " " + cbxDefaultArgs.Text, m_projectInfo.targetDirPath);
}
}
}
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
MyGlobals.myMainEvents.OnTestTerminated(false, m_projectInfo.GetExePath(), false, new TimeSpan(0));
}
}
private void btnRunAllTestGroups_Click(object sender, RoutedEventArgs e)
{
try
{
if (m_state[(int)RunMode.TEST_GROUPS] == State.RUNNING)
{
StopExecution();
}
else
{
if (lstTestGroups.Items.Count > 0)
{
InitForTestExecution(RunMode.TEST_GROUPS, lstTestGroups.Items.Count);
m_idxRunAllTestGroups = 0;
if (Services.GetOptions().BuildSolutionBeforeStartingTest)
{
MyGlobals.myMainEvents.OnStartBuilding();
}
else
{
StartTestGroup(0);
}
}
}
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
private void btnGoToSrcTestGroup_Click(object sender, RoutedEventArgs e)
{
try
{
if (lstTestGroups.SelectedItem == null)
{
WriteLine(1, "No test group selected!");
}
else
{
WriteLine(3, "GoTo src: selIndex=" + lstTestGroups.SelectedIndex);
MyGlobals.myMainEvents.OnOpenSourceFile(m_testGroups[lstTestGroups.SelectedIndex].fileFullPath,
m_testGroups[lstTestGroups.SelectedIndex].lineNum);
}
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
private void lstTestFuncs_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (lstTestFuncs.SelectedItem == null)
return;
txtStartArgTestFunc.Text = "";
if (m_projectInfo.appType == AppType.BOOST) // --run_test=test1 --run_test=test2 ...
{
foreach (MyListItem listItem in lstTestFuncs.SelectedItems)
{
txtStartArgTestFunc.Text += m_testFuncs[listItem.idx].GetCmdString() + " ";
}
}
else // assume TTB, -selectTestFunc func1,func2,func3
{
txtStartArgTestFunc.Text = "-selectTestFunc ";
string sep = "";
foreach (MyListItem listItem in lstTestFuncs.SelectedItems)
{
txtStartArgTestFunc.Text += sep + m_testFuncs[listItem.idx].testFunc;
sep = ",";
}
}
}
private void chkTestFuncsForSelTestGroup_CheckBoxChanged(object sender, RoutedEventArgs e)
{
try
{
RefreshTestFuncList();
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
private void btnRunSelectedTestFunc_Click(object sender, RoutedEventArgs e)
{
try
{
if (m_useDebugger)
{
MyGlobals.myMainEvents.OnStartDebugging(txtStartArgTestFunc.Text + " " + cbxDefaultArgs.Text);
}
else // regular execution
{
if (m_state[(int)RunMode.TEST_FUNCS] == State.RUNNING)
{
StopExecution();
}
else
{
InitForTestExecution(RunMode.TEST_FUNCS, 1);
RefreshState();
if (Services.GetOptions().BuildSolutionBeforeStartingTest)
{
MyGlobals.myMainEvents.OnStartBuilding();
}
else
{
StartProcess(m_projectInfo.GetExePath(), txtStartArgTestFunc.Text + " " + cbxDefaultArgs.Text, m_projectInfo.targetDirPath);
}
}
}
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
MyGlobals.myMainEvents.OnTestTerminated(false, m_projectInfo.GetExePath(), false, new TimeSpan(0));
}
}
private void btnRunAllTestFuncs_Click(object sender, RoutedEventArgs e)
{
try
{
if (m_state[(int)RunMode.TEST_FUNCS] == State.RUNNING)
{
StopExecution();
}
else
{
if (lstTestFuncs.Items.Count > 0)
{
InitForTestExecution(RunMode.TEST_FUNCS, lstTestFuncs.Items.Count);
m_idxRunAllTestFuncs = 0;
if (Services.GetOptions().BuildSolutionBeforeStartingTest)
{
MyGlobals.myMainEvents.OnStartBuilding();
}
else
{
StartTestFunc(0);
}
}
}
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
private void btnGoToSrcTestFunc_Click(object sender, RoutedEventArgs e)
{
try
{
if (lstTestFuncs.SelectedItem == null)
{
WriteLine(1, "No test func selected!");
}
else
{
WriteLine(3, "GoTo src: selIndex=" + lstTestFuncs.SelectedIndex);
MyGlobals.myMainEvents.OnOpenSourceFile(m_testFuncs[lstTestFuncs.SelectedIndex].fileFullPath,
m_testFuncs[lstTestFuncs.SelectedIndex].lineNum);
}
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
private void cbxDescTestApps_SelectionChanged(object sender, EventArgs e)
{
if (cbxDescTestApps.SelectedIndex >= 0)
{
m_idxCurrentTestApps = cbxDescTestApps.SelectedIndex;
Services.GetOptions().IdxCurrentTestApps = m_idxCurrentTestApps;
Services.GetOptions().SaveSettingsFromToolWindow();
m_state[(int)RunMode.TEST_APPS] = State.IDLE;
LoadCurrentTestApps();
RefreshState();
}
}
private void btnRunAllTestApps_Click(object sender, RoutedEventArgs e)
{
WriteLine(3, "Run all test apps");
string txt = txtTestApps.Text;
string[] tmpTestApps = txt.Split(new Char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
m_currentTestApps.Clear();
foreach (var app in tmpTestApps)
{
app.Trim();
if (app.IndexOf("//") != 0) // skip comment lines
{
m_currentTestApps.Add(app);
}
}
try
{
if (m_state[(int)RunMode.TEST_APPS] == State.RUNNING)
{
StopExecution();
}
else
{
if (m_currentTestApps.Count > 0)
{
InitForTestExecution(RunMode.TEST_APPS, m_currentTestApps.Count);
m_idxRunAllTestApps = 0;
StartTestApp(0);
}
}
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
private void btnSaveTestApps_Click(object sender, RoutedEventArgs e)
{
WriteLine(3, "Save test apps");
SaveCurrentTestApps();
}
private void btnReloadTestApps_Click(object sender, RoutedEventArgs e)
{
WriteLine(3, "Reload test apps");
LoadCurrentTestApps();
}
private void btnClearTestApps_Click(object sender, RoutedEventArgs e)
{
txtTestApps.Text = "";
}
private void cbxExportImportTestApps_SelectionChangeCommitted(object sender, EventArgs e)
{
try
{
switch (cbxExportImportTestApps.SelectedIndex)
{
case (int)ExpImpMode.EXPORT_TO_FILE:
ExportTestAppsToFile();
break;
case (int)ExpImpMode.IMPPORT_FROM_FILE:
ImportTestAppsFromFile();
break;
case (int)ExpImpMode.IMPORT_FROM_SOLUTION:
ImportTestAppsFromSolution();
break;
case (int)ExpImpMode.IMPORT_TEST_GROUPS_FROM_STARTUP_PROJECT:
ImportTestAppsFromCurrentTestGroups();
break;
case (int)ExpImpMode.IMPORT_VISIBLE_TEST_FUNCS_FROM_STARTUP_PROJECT:
ImportTestAppsFromCurrentTestFuncs();
break;
default:
break;
}
cbxExportImportTestApps.SelectedIndex = 0; // reset selection to allow mulltiple triggers for same list index
// Remark: ListItem 0 is declared as invisible (="collapsed", see xaml) within list. This item is used to always show the standard text.
// The combobox is oonly used to trigger an action from the list and not to store and display a current selection!
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
private void chkShutdown_CheckBoxChanged(object sender, RoutedEventArgs e)
{
bool selectedForShutdown = (bool)chkShutdown.IsChecked;
if (selectedForShutdown)
{
WriteLine(1, "Automatic shutdown after end of test activated!");
System.Windows.Media.SolidColorBrush shutDownColor = System.Windows.Media.Brushes.Yellow;
this.Background = shutDownColor;
mainGrid.Background = shutDownColor;
tabControl.Background = shutDownColor;
}
else
{
this.Background = m_originalBrushWindow;
mainGrid.Background = m_originalBrushWindow;
tabControl.Background = m_originalBrushWindow;
}
}
private void btnClearEvents_Click(object sender, RoutedEventArgs e)
{
lstEvents.Items.Clear();
}
private void btnCopyLog_Click(object sender, RoutedEventArgs e)
{
try
{
System.Windows.Forms.Clipboard.SetText(GetExportInfo(true) + "\n" + Services.GetListBoxItemsAsText(lstEvents));
WriteLine(1, "Copied to clipboard, ready for pasting!");
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
private void btnExportLog_Click(object sender, RoutedEventArgs e)
{
try
{
System.Windows.Forms.SaveFileDialog saveFileDialog = new System.Windows.Forms.SaveFileDialog();
saveFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
saveFileDialog.FileName = GetExportInfo(false);
saveFileDialog.RestoreDirectory = true;
if (saveFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
System.IO.File.WriteAllText(saveFileDialog.FileName,
GetExportInfo(true) + "\n" + Services.GetListBoxItemsAsText(lstEvents));
}
}
catch (Exception ex)
{
WriteLine(1, "EXCEPTION: " + ex.ToString());
}
}
//----- Helper methods for Refreshing -----
private void RefreshDisplay()
{
RefreshDisplayText();
RefreshState();
SetColVisibility();
SetRowVisibility();
}
private void RefreshDisplayText()
{
switch (m_projectInfo.appType)
{
case AppType.BOOST:
txtInfoTestGroups.Text = "BOOST test suites";
txtInfoTestFuncs.Text = "BOOST test cases";
chkTestFuncsForSelTestGroup.Content = "within suite";
break;
case AppType.TTB:
txtInfoTestGroups.Text = "TTB test files";
txtInfoTestFuncs.Text = "TTB test functions";
chkTestFuncsForSelTestGroup.Content = "within file";
break;
default:
txtInfoTestGroups.Text = "--";
txtInfoTestFuncs.Text = "--";
chkTestFuncsForSelTestGroup.Content = "--";
break;
}
}
private void RefreshState(RunMode in_runMode, TextBlock tb, string info, bool setText = true)
{
switch (m_state[(int)in_runMode])
{
case State.IDLE:
tb.Background = m_originalBrushTextBlock;
tb.Foreground = System.Windows.Media.Brushes.Black;
if (setText)
{
tb.Text = info;
}
break;
case State.RUNNING:
tb.Background = System.Windows.Media.Brushes.Orange;
tb.Foreground = System.Windows.Media.Brushes.Black;
if (setText)
{
tb.Text = "Running" + GetInfoAboutCurrentProgress(in_runMode);
}
break;
case State.SUCCEEDED:
tb.Background = System.Windows.Media.Brushes.LightGreen;
tb.Foreground = System.Windows.Media.Brushes.Black;
if (setText)
{
tb.Text = "OK" + GetInfoAboutSucceededTest(in_runMode); ;
}
break;
case State.FAILED:
tb.Background = System.Windows.Media.Brushes.Red;
tb.Foreground = System.Windows.Media.Brushes.White;
if (setText)
{
tb.Text = "FAILED" + GetInfoAboutFailedTest(in_runMode);
}
break;
}
}
private void RefreshState()
{
RefreshState(RunMode.TEST_GROUPS, txtInfoStarArgTestGroup, GetInfoStartArgTestGroup());
RefreshState(RunMode.TEST_FUNCS, txtInfoStarArgTestFunc, GetInfoStartArgTestFunc());
RefreshState(RunMode.TEST_STARTUP_PROJECT, txtInfo, "", false);
RefreshState(RunMode.TEST_APPS, txtInfoTestApps, "");
RefreshButtons();
return;
}
private void RefreshButtons()
{
if (m_useDebugger)
{
btnRunTestAll.IsEnabled = true;
btnRunSelectedTestGroup.IsEnabled = true;
btnRunSelectedTestFunc.IsEnabled = true;
btnRunAllTestGroups.IsEnabled = false;
btnRunAllTestFuncs.IsEnabled = false;
btnRunAllTestApps.IsEnabled = false;
btnRunTestAll.Content = "Debug";
btnRunSelectedTestGroup.Content = "Debug";
btnRunSelectedTestFunc.Content = "Debug";
btnRunAllTestGroups.Content = "Run each";
btnRunAllTestFuncs.Content = "Run each";
return;
}
bool running = (m_state[(int)RunMode.TEST_STARTUP_PROJECT] == State.RUNNING)
|| (m_state[(int)RunMode.TEST_GROUPS] == State.RUNNING)
|| (m_state[(int)RunMode.TEST_FUNCS] == State.RUNNING)
|| (m_state[(int)RunMode.TEST_APPS] == State.RUNNING);
chkUseDebugger.IsEnabled = !running;
btnRunTestAll.IsEnabled = !running || (m_state[(int)RunMode.TEST_STARTUP_PROJECT] == State.RUNNING);
btnRunSelectedTestGroup.IsEnabled = !running || ((m_state[(int)RunMode.TEST_GROUPS] == State.RUNNING) && (m_idxRunAllTestGroups == -1));
btnRunAllTestGroups.IsEnabled = !running || ((m_state[(int)RunMode.TEST_GROUPS] == State.RUNNING) && (m_idxRunAllTestGroups >= 0));
btnRunSelectedTestFunc.IsEnabled = !running || ((m_state[(int)RunMode.TEST_FUNCS] == State.RUNNING) && (m_idxRunAllTestFuncs == -1));
btnRunAllTestFuncs.IsEnabled = !running || ((m_state[(int)RunMode.TEST_FUNCS] == State.RUNNING) && (m_idxRunAllTestFuncs >= 0));
btnOpenProtocolFile.IsEnabled = !running;
btnRefreshAll.IsEnabled = !running;
btnRunTestAll.Content = ((btnRunTestAll.IsEnabled && running) ? "Stop" : Services.GetOptions().RunUntilFailure ? "Run until failure" : "Run");
btnRunSelectedTestGroup.Content = ((btnRunSelectedTestGroup.IsEnabled && running) ? "Stop test" : "Run selected");
btnRunAllTestGroups.Content = ((btnRunAllTestGroups.IsEnabled && running) ? "Stop test" : "Run each");
btnRunSelectedTestFunc.Content = ((btnRunSelectedTestFunc.IsEnabled && running) ? "Stop test" : "Run selected");
btnRunAllTestFuncs.Content = ((btnRunAllTestFuncs.IsEnabled && running) ? "Stop test" : "Run each");
btnRunAllTestApps.IsEnabled = !running || (m_state[(int)RunMode.TEST_APPS] == State.RUNNING);
btnRunAllTestApps.Content = ((btnRunAllTestApps.IsEnabled && running) ? "Stop" : "Run all");
btnMoreOptions.Content = (m_optionsVisible ? "Hide" : "...");
}
private void RefreshTestFuncList()
{
lstTestFuncs.Items.Clear();
bool showOnlyFuncsWithinGroup = (bool)chkTestFuncsForSelTestGroup.IsChecked;
if (showOnlyFuncsWithinGroup)
{
if (lstTestGroups.SelectedItem == null)
{
if (lstTestGroups.Items.Count == 0)
{
// no test groups available
return;
}
if (lstTestGroups.Items.Count > 0)
{
lstTestGroups.SelectedIndex = 0;
if (lstTestGroups.SelectedItem == null)
{
// nothing selected
return;
}
}
}
}
// Create local collection of test funcs which may be sorted
m_testFuncs = new System.Collections.Generic.List<TestFuncEntry>();
foreach (var testFuncEntry in m_projectInfo.testFuncs)
{
if (showOnlyFuncsWithinGroup)
{
if (m_selectedTestGroups.Contains(testFuncEntry.GetTestGroupHierarchyString()))
{
m_testFuncs.Add(testFuncEntry);
}
}
else // show all test funcs
{
m_testFuncs.Add(testFuncEntry);
}
}
switch (m_sortOrder)
{
case SortOrder.AS_READ_FROM_FILE:
// do not change sort order
break;
case SortOrder.REVERSE_READ:
{
m_testFuncs.Reverse();
}
break;
case SortOrder.ALPHA:
{
m_testFuncs.Sort((x, y) => x.GetDisplayString().CompareTo(y.GetDisplayString()));
}
break;
case SortOrder.REVERSE_ALPHA:
{
m_testFuncs.Sort((x, y) => y.GetDisplayString().CompareTo(x.GetDisplayString()));
}
break;
}
int idx = 0;
foreach (var testFuncEntry in m_testFuncs)
{
MyListItem entry = new MyListItem(idx, testFuncEntry.GetDisplayString());
lstTestFuncs.Items.Add(entry);
++idx;
}
}
private void RefreshTestGroupList()
{
int lastSelectedIndex = lstTestGroups.SelectedIndex;
lstTestGroups.Items.Clear();
// Copy test groups to local collection which may be sorted
m_testGroups = new System.Collections.Generic.List<TestGroupEntry>(m_projectInfo.testGroups);
m_selectedTestGroups = new HashSet<string>();
switch (m_sortOrder)
{
case SortOrder.AS_READ_FROM_FILE:
// do not change sort order
break;
case SortOrder.REVERSE_READ:
{
m_testGroups.Reverse();
}
break;
case SortOrder.ALPHA:
{
m_testGroups.Sort((x, y) => x.GetDisplayString().CompareTo(y.GetDisplayString()));
}
break;
case SortOrder.REVERSE_ALPHA:
{
m_testGroups.Sort((x, y) => y.GetDisplayString().CompareTo(x.GetDisplayString()));
}
break;
}
// Copy sorted entries to listbox
int idx = 0;
foreach (var testGroupEntry in m_testGroups)
{
MyListItem entry = new MyListItem(idx, testGroupEntry.GetDisplayString());
lstTestGroups.Items.Add(entry);
++idx;
}
if ((lstTestGroups.Items.Count > 0) && (lastSelectedIndex >= 0))
{
int selIndex = (lastSelectedIndex < lstTestGroups.Items.Count) ? lastSelectedIndex : lstTestGroups.Items.Count - 1;
{
lstTestGroups.SelectedIndex = selIndex;
m_selectedTestGroups.Clear();
if (selIndex >= 0)
{
m_selectedTestGroups.Add(m_testGroups[selIndex].GetTestGroupHierarchyString());
}
}
}
}
private void SetRowVisibility()
{
if (m_optionsVisible)
{
mainRowOptions.Height = new GridLength(56);
mainRowDefaultArgs.Height = new GridLength(30);
}
else
{
mainRowOptions.Height = new GridLength(0);
mainRowDefaultArgs.Height = new GridLength(0);
}
if (m_logVisible)
{
mainRowLog.Height = new GridLength(5, GridUnitType.Star);
mainRowLogButton.Height = new GridLength(30);
}
else
{
mainRowLog.Height = new GridLength(0);
mainRowLogButton.Height = new GridLength(0);
}
}
private void SetColVisibility()
{
switch (m_colVisibility)
{
case ColVisibility.BOTH:
mainColGroups.Width = new GridLength(1, GridUnitType.Star);
mainColFuncs.Width = new GridLength(1, GridUnitType.Star);
break;
case ColVisibility.LEFT:
mainColGroups.Width = new GridLength(1, GridUnitType.Star);
mainColFuncs.Width = new GridLength(0);
break;
case ColVisibility.RIGHT:
mainColGroups.Width = new GridLength(0);
mainColFuncs.Width = new GridLength(1, GridUnitType.Star);
break;
}
}
private void TriggerDelayedRefreshFromGuiThread()
{
if (m_refreshTimerIsActive)
{
WriteLine(2, "TriggerDelayedRefreshFromGuiThread: timer already active,call is ignored");
return;
}
m_refreshTimerIsActive = true;
m_refreshTimer.Tick += new EventHandler(RefreshTimer_Elapsed);
m_refreshTimer.Interval = new TimeSpan(0, 0, 1);
m_refreshTimer.Start();
WriteLine(2, "TriggerDelayedRefreshFromGuiThread: new timer started");
}
private void RefreshTimer_Elapsed(object sender, EventArgs e)
{
if (!m_refreshTimerIsActive)
{
WriteLine(2, "RefreshTimer_Elapsed: timer already stopped, ignore timer event!");
return;
}
WriteLine(2, "RefreshTimer_Elapsed: timer will be stopped, refresh is executed");
m_refreshTimerIsActive = false;
m_refreshTimer.Stop();
if (MyGlobals.myMainEvents != null)
MyGlobals.myMainEvents.OnRefreshNow();
}
//----- Helper methods to get data for display -----
private string GetInfoStartArgTestGroup()
{
switch (m_projectInfo.appType)
{
case AppType.BOOST:
return "Select test suite / edit cmd";
case AppType.TTB:
return "Select test file / edit cmd";
default:
return "--";
}
}
private string GetInfoStartArgTestFunc()
{
switch (m_projectInfo.appType)
{
case AppType.BOOST:
return "Select single test case / edit cmd";
case AppType.TTB:
return "Select single test func / edit cmd";
default:
return "--";
}
}
private string GetInfoAboutCurrentProgress(RunMode in_runMode)
{
int idx = (int)in_runMode;
if (m_state[idx] == State.RUNNING)
{
if ((in_runMode == RunMode.TEST_APPS) && (m_idxRunAllTestApps >= 0))
{
return " " + System.IO.Path.GetFileNameWithoutExtension(m_currentTestApps[m_idxRunAllTestApps])
+ " (" + (m_numExecutedTests[idx] + 1) + " of " + m_totalNumTestsToExecute[idx] + ")";
}
else
{
return " (" + (m_numExecutedTests[idx] + 1) + " of " + m_totalNumTestsToExecute[idx] + ")";
}
}
return "";
}
private string GetInfoAboutSucceededTest(RunMode in_runMode)
{
int idx = (int)in_runMode;
if (m_totalNumTestsToExecute[idx] > 1)
{
return " (" + (m_numExecutedTests[idx]) + " of " + m_totalNumTestsToExecute[idx] + ")";
}
return "";
}
private string GetInfoAboutFailedTest(RunMode in_runMode)
{
int idx = (int)in_runMode;
if (m_totalNumTestsToExecute[idx] > 1)
{
return " (" + (m_numFailedTests[idx]) + " of " + m_numExecutedTests[idx] + ")";
}
return "";
}
private string GetInfoAboutCurrentTest()
{
if ((m_curRunMode == RunMode.TEST_APPS) && (m_idxRunAllTestApps >= 0))
{
return System.IO.Path.GetFileNameWithoutExtension(m_currentTestApps[m_idxRunAllTestApps]);
}
return "";
}
private string GetExportInfo(bool in_withTimeStamp)
{
string info = "Exported from TestExecWin - " + txtInfo.Text;
if (in_withTimeStamp)
{
var now = DateTime.Now;
info += " - " + now.ToShortDateString() + " " + now.ToLongTimeString();
info = "// " + info + "\n// Source path: " + m_projectInfo.sourceDirPath + "\n";
}
return info;
}
//----- Helper methods to perform some action -----
private void InitForTestExecution(RunMode in_runMode, int in_numTestsToExecute)
{
m_stoppedByUser = false;
m_idxRunAllTestGroups = -1;
m_idxRunAllTestFuncs = -1;
m_idxRunAllTestApps = -1;
m_curRunMode = in_runMode;
int idx = (int)m_curRunMode;
m_numExecutedTests[idx] = 0;
m_numFailedTests[idx] = 0;
m_totalNumTestsToExecute[idx] = in_numTestsToExecute;
m_state[idx] = State.RUNNING;
}
private void StartProcess(string exePath, string args, string workDir)
{
int waitTimeMs = GetMaxWaitTimeInMs();
if (waitTimeMs > 0)
{
m_executionTimer.Interval = waitTimeMs;
m_executionTimer.Start();
}
MyGlobals.myMainEvents.OnStartTest(exePath, args, workDir);
}
private void StopExecution()
{
WriteLine(2, "Stopping execution...");
m_stoppedByUser = true;
MyGlobals.myMainEvents.OnStopAll();
}
private void StartTestGroup(int in_idx)
{
if (m_testGroups[in_idx].GetDisplayString() == "<default>")
{
// Simulate successful execution
TestTerminatedWithinGuiThread(true, "", "<execution skipped>", false, new TimeSpan(0));
return;
}
m_state[(int)m_curRunMode] = State.RUNNING;
RefreshState();
StartProcess(m_projectInfo.GetExePath(), m_testGroups[in_idx].GetCmdString() + " " + cbxDefaultArgs.Text, m_projectInfo.targetDirPath);
}
private void StartTestFunc(int in_idx)
{
m_state[(int)m_curRunMode] = State.RUNNING;
RefreshState();
StartProcess(m_projectInfo.GetExePath(), m_testFuncs[in_idx].GetCmdString() + " " + cbxDefaultArgs.Text, m_projectInfo.targetDirPath);
}
private void StartTestApp(int in_idx)
{
string exePathWithOptionalArgs = m_currentTestApps[in_idx];
string exeToStart = exePathWithOptionalArgs;
string args = cbxDefaultArgs.Text;
// Check for optional cmd args after executable
string tmpExeToStart = exeToStart.ToLower();
int posStartExtension = tmpExeToStart.LastIndexOf(".exe");
if (posStartExtension >= 0)
{
int posStartArgs = posStartExtension + 5;
if (posStartArgs < exeToStart.Length)
{
string specificArgs = exePathWithOptionalArgs.Substring(posStartArgs);
if (specificArgs.Length > 0)
{
args = specificArgs + " " + args;
exeToStart = exePathWithOptionalArgs.Substring(0, posStartArgs - 1);
}
}
}
m_state[(int)m_curRunMode] = State.RUNNING;
RefreshState();
StartProcess(exeToStart, args, System.IO.Path.GetDirectoryName(exeToStart));
}
private void ExportTestAppsToFile()
{
System.Windows.Forms.SaveFileDialog saveFileDialog = new System.Windows.Forms.SaveFileDialog();
saveFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
saveFileDialog.FileName = cbxDescTestApps.Text;
saveFileDialog.RestoreDirectory = true;
if (saveFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
System.IO.File.WriteAllText(saveFileDialog.FileName, txtTestApps.Text);
}
}
private void ImportTestAppsFromFile()
{
System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();
openFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string readText = System.IO.File.ReadAllText(openFileDialog.FileName);
txtTestApps.Text += "\n// Imported from file " + openFileDialog.FileName + "\n";
txtTestApps.Text += readText;
}
}
private void ImportTestAppsFromSolution()
{
txtTestApps.Text += "\n// Imported executables from current solution " + System.IO.Path.GetFileName(m_projectInfo.solutionFullPath) + "\n";
string foundExePaths = MyGlobals.myMainEvents.OnGetExecutablesFromCurrentSolution();
txtTestApps.Text += foundExePaths;
}
private void ImportTestAppsFromCurrentTestGroups()
{
string executablesWithStartArgs = "\n// Imported test suites from " + m_projectInfo.project + "\n";
for (int i = 0; i < m_testGroups.Count; ++i)
{
executablesWithStartArgs += m_projectInfo.GetExePath() + " " + m_testGroups[i].GetCmdString() + "\n";
}
txtTestApps.Text += executablesWithStartArgs;
}
private void ImportTestAppsFromCurrentTestFuncs()
{
string executablesWithStartArgs = "\n// Imported visible test cases from " + m_projectInfo.project + "\n";
for (int i = 0; i < m_testFuncs.Count; ++i)
{
executablesWithStartArgs += m_projectInfo.GetExePath() + " " + m_testFuncs[i].GetCmdString() + "\n";
}
txtTestApps.Text += executablesWithStartArgs;
}
private void LoadCurrentTestApps()
{
txtTestApps.Text = Services.GetOptions().GetTestAppsForIdx(m_idxCurrentTestApps);
}
private void SaveCurrentTestApps()
{
Services.GetOptions().SaveTestAppsForIdx(m_idxCurrentTestApps, cbxDescTestApps.Text, txtTestApps.Text);
m_dataDescTestApps[m_idxCurrentTestApps] = cbxDescTestApps.Text;
cbxDescTestApps.ItemsSource = null;
cbxDescTestApps.ItemsSource = m_dataDescTestApps;
cbxDescTestApps.SelectedIndex = m_idxCurrentTestApps;
}
private void SaveLog(RunMode in_runMode)
{
try
{
string fileName = "TextExecWin.";
if (in_runMode == RunMode.TEST_APPS)
{
fileName += "RunTestApps." + cbxDescTestApps.Text;
}
else if (in_runMode == RunMode.TEST_GROUPS)
{
fileName += "RunAllTestGroups." + txtInfo.Text;
}
else if (in_runMode == RunMode.TEST_FUNCS)
{
fileName += "RunAllTestFuncs." + txtInfo.Text;
}
else if (in_runMode == RunMode.TEST_STARTUP_PROJECT)
{
fileName += "SingleRun." + txtInfo.Text;
}
var now = DateTime.Now;
string timeStamp = now.ToString("yyyy.MM.dd_HH.mm.ss");
fileName += "." + timeStamp + ".Log.txt";
WriteLine(2, "SaveLog-fileName=" + fileName);
string fileDir = m_projectInfo.targetDirPath;
if (fileDir == "<not set>")
{
// Get the first path found within environment variables TMP, TEMP or USERPROFILE
fileDir = System.IO.Path.GetTempPath();
}
string fullFilePath = fileDir + "\\" + fileName;
WriteLine(2, "SaveLog-fullFilePath=" + fullFilePath);
string fileHeader = "// Exported from TestExecWin - " + now.ToShortDateString() + " " + now.ToLongTimeString();
fileHeader += "\n// Test project : " + txtInfo.Text;
fileHeader += "\n// Source path : " + m_projectInfo.sourceDirPath;
fileHeader += "\n// RunMode : " + in_runMode + "\n\n";
WriteLine(3, "SaveLog-fileHeader=\n" + fileHeader);
// Write list contents to file
System.IO.File.WriteAllText(fullFilePath, fileHeader + Services.GetListBoxItemsAsText(lstEvents));
}
catch (Exception ex)
{
WriteLine(1, "SaveLog-EXCEPTION: " + ex.ToString());
}
}
public void TestTerminatedWithinGuiThread(bool in_success, string infoAboutTest, string in_args, bool in_memLeaksDetected, TimeSpan in_executionTime)
{
m_executionTimer.Stop();
// Display execution status
string info = in_args;
if (info == "")
{
info = "<no args set>";
}
string durationStr;
if (in_executionTime.TotalSeconds < 1.0)
{
durationStr = "<1s ";
}
else
{
double totalNumMinutes = in_executionTime.TotalSeconds / 60.0;
durationStr = totalNumMinutes.ToString("F1") + "m ";
}
//int totalNumSeconds = Convert.ToInt32(Math.Round(in_executionTime.TotalSeconds));
//int totalNumMinutes = totalNumSeconds / 60;
//int numSeconds = totalNumSeconds % 60;
//int numSecondsAsDecimalMinute = numSeconds / 6;
//string durationStr = totalNumMinutes + "," + numSecondsAsDecimalMinute + "m ";
WriteLine(1, (!in_success ? "FAILED: " : (in_memLeaksDetected ? "FAILED (MEM_LEAKS): " : "OK: "))
+ durationStr + GetInfoAboutCurrentTest() + " " + info);
bool failure = !in_success || in_memLeaksDetected;
int idx = (int)m_curRunMode;
++m_numExecutedTests[idx];
if (failure)
{
++m_numFailedTests[idx];
}
bool testSucceededUpToNow = (m_numFailedTests[idx] == 0);
// Safe update of state variables and refresh
// of GUI controls within GUI thread
SetState(testSucceededUpToNow);
/// ...
/// [dispatch test terminate msg]
if (!m_stoppedByUser)
{
if (m_idxRunAllTestGroups >= 0)
{
++m_idxRunAllTestGroups;
if (m_idxRunAllTestGroups >= lstTestGroups.Items.Count)
{
m_idxRunAllTestGroups = -1;
CheckForFinalAction(RunMode.TEST_GROUPS);
}
else // start next test
{
StartTestGroup(m_idxRunAllTestGroups);
}
}
else if (m_idxRunAllTestFuncs >= 0)
{
++m_idxRunAllTestFuncs;
if (m_idxRunAllTestFuncs >= lstTestFuncs.Items.Count)
{
m_idxRunAllTestFuncs = -1;
CheckForFinalAction(RunMode.TEST_FUNCS);
}
else // start next test
{
StartTestFunc(m_idxRunAllTestFuncs);
}
}
else if (m_idxRunAllTestApps >= 0)
{
++m_idxRunAllTestApps;
if (m_idxRunAllTestApps >= m_currentTestApps.Count)
{
// last test app has terminated
m_idxRunAllTestApps = -1;
CheckForFinalAction(RunMode.TEST_APPS);
}
else // start next test
{
StartTestApp(m_idxRunAllTestApps);
}
}
else
{
if (Services.GetOptions().RunUntilFailure && m_curRunMode == RunMode.TEST_STARTUP_PROJECT)
{
if (in_success)
{
WriteLine(1, "Execution " + m_numExecutedTests[idx].ToString() + " succeeded. Continue run cycle...");
m_state[idx] = State.RUNNING;
RefreshState();
StartProcess(m_projectInfo.GetExePath(), cbxDefaultArgs.Text, m_projectInfo.targetDirPath);
}
else
{
WriteLine(1, "Execution " + m_numExecutedTests[idx].ToString() + " failed. Exiting run cycle.");
CheckForFinalAction(RunMode.TEST_STARTUP_PROJECT);
}
}
else
{
CheckForFinalAction(RunMode.TEST_STARTUP_PROJECT);
}
}
}
}
private void OnExecutionTimeout(Object myObject, EventArgs myEventArgs)
{
m_executionTimer.Stop();
WriteLine(1, "TIMEOUT of " + GetMaxWaitTimeInMs() / 1000 + " sec has expired!");
MyGlobals.myExecutor.KillRunningProcess();
}
private void CheckForFinalAction(RunMode in_runMode)
{
try
{
bool shutdown = (bool)chkShutdown.IsChecked;
if (shutdown)
{
SaveLog(in_runMode);
bool reallyShutdown = true; // deactivate for testing
if (reallyShutdown)
{
// Possible extension: First check for existence of predefined batch file to perform specific shutdown actions
//string nameBatchFile="TestExecWin.Shutdown.cmd";
//string foundBatchFilePath = "";
//System.Collections.Generic.List<string> possibleFilePaths = new System.Collections.Generic.List<string>();
//if (m_projectInfo.targetDirPath != "<not set>")
//{
// possibleFilePaths.Add(m_projectInfo.targetDirPath);
//}
//possibleFilePaths.Add(System.IO.Path.GetTempPath());
//foreach (string fileDir in possibleFilePaths)
//{
// string tmpPath = fileDir + nameBatchFile;
// if (System.IO.File.Exists(tmpPath))
// {
// foundBatchFilePath = tmpPath;
// break;
// }
// WriteLine(1, "Batch not found: " + tmpPath);
//}
//if (foundBatchFilePath.Length>0)
//{
// WriteLine(1, "Trying to shutdown with " + foundBatchFilePath + "...");
// Process.Start(foundBatchFilePath);
//}
//else
{
// WriteLine(1, "No predefined batch file found, now trying to shutdown with simple shutdown command...");
WriteLine(1, "Now trying to shutdown with simple command shutdown /s /f ...");
Process.Start("shutdown", "/s /f /t 0");
}
}
else
{
WriteLine(1, "Shutdown is skipped");
}
}
}
catch (Exception ex)
{
WriteLine(1, "CheckForFinalAction-EXCEPTION: " + ex.ToString());
}
}
//----- General helper methods -----
private void SetState(bool in_success)
{
if (m_state[(int)m_curRunMode] == State.RUNNING)
{
m_state[(int)m_curRunMode] = (in_success ? State.SUCCEEDED : State.FAILED);
}
RefreshState();
}
public bool TestIsRunning()
{
for (int i = 0; i < 4; ++i)
{
if (m_state[i] == State.RUNNING)
return true;
}
return false;
}
private int GetMaxWaitTimeInMs()
{
switch (m_waitMode)
{
case WaitMode.WAIT_ENDLESS:
return 0;
case WaitMode.WAIT_30_SEC:
return 30 * 1000;
case WaitMode.WAIT_1_MIN:
return 60 * 1000;
case WaitMode.WAIT_2_MIN:
return 120 * 1000;
case WaitMode.WAIT_5_MIN:
return 300 * 1000;
case WaitMode.WAIT_10_MIN:
return 600 * 1000;
case WaitMode.WAIT_20_MIN:
return 1200 * 1000;
case WaitMode.WAIT_30_MIN:
return 1800 * 1000;
case WaitMode.WAIT_40_MIN:
return 2400 * 1000;
case WaitMode.WAIT_60_MIN:
return 3600 * 1000;
default:
return 3600 * 1000;
}
}
private void WriteLine(int in_outputLevel, String in_info)
{
if (MyGlobals.myEventReceiver != null)
{
MyGlobals.myEventReceiver.WriteLine(in_outputLevel, in_info);
}
}
/// [threading sync gui thread]
public void AddInfoToEventList(string info)
{
// Redirect to main GUI thread
Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.Run(async delegate {
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
AddInfoToEventListFromGuiThread(info);
});
}
private void AddInfoToEventListFromGuiThread(string info)
{
// here we are sure to be within GUI thread and we can
// safely access the list box
lstEvents.Items.Add(info);
/// ...
/// [threading sync gui thread]
// Ensure last added item is visible
ListBoxAutomationPeer svAutomation = (ListBoxAutomationPeer)ScrollViewerAutomationPeer.CreatePeerForElement(lstEvents);
IScrollProvider scrollInterface = (IScrollProvider)svAutomation.GetPattern(PatternInterface.Scroll);
System.Windows.Automation.ScrollAmount scrollVertical = System.Windows.Automation.ScrollAmount.LargeIncrement;
System.Windows.Automation.ScrollAmount scrollHorizontal = System.Windows.Automation.ScrollAmount.NoAmount;
//If the vertical scroller is not available, the operation cannot be performed, which will raise an exception.
if (scrollInterface == null)
{
return;
}
if (scrollInterface.VerticallyScrollable)
scrollInterface.Scroll(scrollHorizontal, scrollVertical);
}
}
}