--- /dev/null
+import "ecere"
+import "EDA"
+import "md5"
+import "Project"
+import "PathBox"
+
+Test dummy; // FIXME ugly hack
+
+GlobalSettings globalSettings { };
+
+struct MD5Digest
+{
+ byte digest [16];
+
+ void OnDisplay(Surface surface,
+ int x, int y, int width,
+ void * fieldData,
+ Alignment alignment,
+ DataDisplayFlags flags)
+ {
+ ColorKey keys[] = {{Color {digest[0] , digest[1] , digest[2] }, 0.0f},
+ {Color {digest[3] , digest[4] , digest[5] }, 0.2f},
+ {Color {digest[6] , digest[7] , digest[8] }, 0.4f},
+ {Color {digest[9] , digest[10], digest[11]}, 0.6f},
+ {Color {digest[12], digest[13], digest[14]}, 0.8f},
+ {Color {digest[15], digest[0] , digest[1] }, 1.0f}};
+
+ surface.Gradient(keys, 6, 0, horizontal, x+1, y+1, x+34, y+14);
+ surface.Rectangle(x+1,y+1,x+34,y+14);
+ }
+
+ void OnSerialize(IOChannel channel)
+ {
+ channel.WriteData(digest,16);
+ }
+ void OnUnserialize(IOChannel channel)
+ {
+ channel.ReadData(digest,16);
+ }
+ property TestRun
+ {
+ set {
+ TempFile hashTemp { };
+
+ Array<OutputFile> files = AccessMacros::allOutputFiles(value);
+ for(of : files)
+ {
+ File f = of.outputFile;
+ if(f)
+ {
+ while(!f.Eof())
+ {
+ byte buffer[1024];
+ uint count = f.Read(buffer,1,sizeof(buffer));
+ hashTemp.Write(buffer, 1, count);
+ }
+ delete f;
+ }
+ }
+ {
+ uint size;
+ MD5_CTX ctx;
+ MD5Init(&ctx);
+ size = hashTemp.GetSize();
+ MD5Update(&ctx, hashTemp.buffer, size);
+ MD5Final(digest, &ctx);
+ }
+ delete hashTemp;
+ files.Free();
+ delete files;
+ }
+ // TOFIX: When this is commented out, no warning at conversion but conversion not acting as such!!
+ get { }
+ }
+};
+
+CompilerConfig defaultCompiler;
+
+void CreateMakefile(String epjPath, String makePath)
+{
+ Project project;
+ bool valid = true;
+ char* configName = null;//"release";
+
+ defaultCompiler = MakeDefaultCompiler("Default", true);
+ defaultCompiler.eccCommand = "ecc -nolinenumbers";
+
+ if(FileExists(epjPath).isFile)
+ {
+ char extension[MAX_EXTENSION] = "";
+ GetExtension(epjPath, extension);
+ strlwr(extension);
+ if(!strcmp(extension, ProjectExtension))
+ {
+ project = LoadProject(epjPath);
+ if(project)
+ {
+ ProjectConfig defaultConfig = null;
+ if(configName)
+ {
+ valid = false;
+ for(config : project.configurations)
+ {
+ if(!strcmpi(configName, config.name))
+ {
+ project.config = config;
+ valid = true;
+ break;
+ }
+ }
+ if(!valid)
+ printf("Error: Project configuration (%s) was not found.\n", configName);
+ }
+ else
+ {
+ ProjectConfig releaseConfig;
+ for(config : project.configurations)
+ {
+ if(!strcmpi(config.name, "Release"))
+ {
+ project.config = config;
+ releaseConfig = config;
+ break;
+ }
+ }
+ if(!releaseConfig && project.configurations.count)
+ {
+ project.config = project.configurations.firstIterator.data;
+ /*
+ releaseConfig = project.configs.first;
+ releaseConfig.objDir.dir = "release";
+ releaseConfig.targetDir.dir = "release";
+ releaseConfig.optimize = forSpeed;
+ releaseConfig.debug = false;
+ releaseConfig.name = "Release";
+ */
+ }
+
+ if(!releaseConfig)
+ {
+ printf("Error: There are no Project configurations.\n", configName);
+ valid = false;
+ // we don't need to create a config to compile a config-less project, do we?
+ /*
+ char targetName[MAX_FILENAME];
+ GetLastDirectory(epjPath, targetName);
+ StripExtension(targetName);
+ defaultConfig = ProjectConfig
+ {
+ name = "Release";
+ targetType = executable;
+ targetName = targetName;
+ defaultNameSpace = "";
+ objDir.dir = "release";
+ targetDir.dir = "release";
+ optimize = forSpeed;
+ debug = false;
+ allWarnings = true;
+ makingModified = true;
+ compilingModified = true;
+ linkingModified = true;
+ };
+ project.config = defaultConfig;
+ */
+ }
+ }
+ if(valid)
+ project.GenerateMakefile(makePath, false, "");
+
+ delete defaultConfig;
+ delete project;
+ }
+ }
+ }
+}
+
+
+dbtable "Tests" Test
+{
+ Test id "id";
+ String name "name";
+ String filePath "filePath";
+ TestRun reference "reference";
+ bool active "active";
+}
+
+enum OutputFileType
+{
+ sym, imp, c, ec
+};
+
+dbtable "OutputFiles" OutputFile
+{
+ OutputFile id "id";
+ File outputFile "outputFile";
+ String filePath "filePath";
+ Test test "test";
+ TestRun run "run";
+ OutputFileType type "type";
+ DateTime created "created";
+ dbindex run;
+}
+
+dbtable "Runs" TestRun
+{
+ TestRun id "id";
+ File makeOutput "makeOutput";
+ bool makeReturnValue "makeReturnValue";
+ Test test "test";
+ TimeStamp time "time";
+ bool save "save";
+ MD5Digest digest "digest";
+ dbindex test, time testAndTime;
+}
+
+Database db;
+
+class AccessMacros
+{
+ TestRun ::lastTestRun(Test t)
+ {
+ TestRun tr = 0;
+ Row tRow { tbl = dbindex("Runs", testAndTime) };
+ if(tRow.Find(dbfield("Runs",test),middle,nil,t)) {
+ tr = tRow.sysID;
+ }
+ delete tRow;
+ return tr;
+ }
+ Array<TestRun> ::allTestRuns(Test t)
+ {
+ Array<TestRun> runs { };
+ Row tRow { tbl = dbindex("Runs",testAndTime) };
+ for(tRow.Find(dbfield("Runs",test),middle,nil,t); !tRow.nil; tRow.Next())
+ runs.Add(tRow.sysID);
+ delete tRow;
+ return runs;
+ }
+ Array<OutputFile> ::allOutputFiles(TestRun t)
+ {
+ Array<OutputFile> files { };
+ RowOutputFiles tRow { tbl = dbindex("OutputFiles",run) };
+ for(tRow.Find(dbfield("OutputFiles",run),middle,nil,t); !tRow.nil; tRow.Next())
+ {
+ if(t != tRow.run)
+ break;
+ files.Add(tRow.sysID);
+ }
+ delete tRow;
+ return files;
+ }
+}
+
+class TestSuiteApp : GuiApplication
+{
+ DataSource ds { driver = /*"SQLite"*/"EDB" };
+ TestSuiteApp()
+ {
+ db = database_open(ds, "TestSuite");
+ }
+ ~TestSuiteApp()
+ {
+ Array<OutputFile> files;
+ Array<TestRun> runs;
+ RowTests tests { };
+ RowRuns rRuns { };
+ RowOutputFiles rFiles { };
+ while(tests.Next())
+ {
+ Test t = (Test)tests.id;
+ runs = AccessMacros::allTestRuns(t);
+ for(run : runs)
+ {
+ if(!run.save)
+ {
+ if(t.reference == run)
+ {
+ t.reference = null;
+ }
+ files = AccessMacros::allOutputFiles(run);
+ for(file : files)
+ {
+ rFiles.sysID=file;
+ rFiles.Delete();
+ }
+ rRuns.sysID=run;
+ rRuns.Delete();
+ }
+ }
+ }
+ delete tests;
+ delete rRuns;
+ delete rFiles;
+ delete db;
+ delete ds;
+ }
+}
+
+class TestSuiteGlobalSettings : GlobalAppSettings
+{
+ settingsName = "testSuite";
+ char * diffTool;
+ char * testDB_file;
+ ~TestSuiteGlobalSettings()
+ {
+ delete diffTool;
+ delete testDB_file;
+ }
+ void OnAskReloadSettings()
+ {
+ Load();
+ }
+ void Load()
+ {
+ if(GlobalAppSettings::Load())
+ {
+ delete diffTool;
+ delete testDB_file;
+ GetGlobalValue("Tools","diff", singleString, &diffTool);
+ GetGlobalValue("Tests","list", singleString, $testDB_file);
+ CloseAndMonitor();
+ }
+ }
+ void Save()
+ {
+ if(GlobalAppSettings::Save())
+ {
+ PutGlobalValue("Tools","diff", singleString, diffTool);
+ PutGlobalValue("Tests","list", singleString, testDB_file);
+ CloseAndMonitor();
+ }
+ }
+}
+
+class DiffThread : Thread
+{
+ char origDir[MAX_LOCATION];
+ char newDir[MAX_LOCATION];
+
+ uint Main()
+ {
+ DualPipe diff;
+ FileListing flOrig { origDir, 0 };
+ FileListing flNew { newDir, 0 };
+ diff = DualPipeOpenf({ true }, "%s \"%s\" \"%s\"", theGlobalSettings.diffTool, origDir, newDir);
+ if(diff)
+ {
+ diff.Wait();
+ }
+ while(flOrig.Find())
+ {
+ DeleteFile(flOrig.path);
+ }
+ rmdir(origDir);
+ while(flNew.Find())
+ {
+ DeleteFile(flNew.path);
+ }
+ rmdir(newDir);
+ delete diff;
+ return 0;
+ }
+ void DiffDir(Array<OutputFile> outputOrig, Array<OutputFile> outputNew)
+ {
+ //char origDir[MAX_LOCATION];
+ //char newDir[MAX_LOCATION];
+ char tmpname[MAX_LOCATION];
+
+ CreateTemporaryDir(origDir, "TestSuiteOrigDir");
+ CreateTemporaryDir(newDir,"TestSuiteNewDir");
+
+ for(d : [ outputOrig, outputNew ])
+ {
+ for(of : d)
+ {
+ char tmpname[MAX_LOCATION];
+ char dummybuffer[MAX_LOCATION];
+ File outputFile = of.outputFile;
+ if(outputFile)
+ {
+ File tmp;
+ GetLastDirectory(of.filePath, dummybuffer);
+ strcpy(tmpname, (d == outputOrig) ? origDir : newDir);
+ PathCat(tmpname, dummybuffer);
+ tmp = FileOpen(tmpname, write);
+ if(tmp)
+ {
+ CopyFile(outputFile, tmp);
+ delete tmp;
+ }
+ }
+ delete outputFile;
+ }
+ }
+
+ Create();
+ }
+}
+
+class BuildTool
+{
+ int GenerateMakefile(Test t)
+ {
+ DualPipe epj2makePipe;
+ char testFolder[MAX_LOCATION];
+ char makefileOut[MAX_LOCATION];
+ char epjName[MAX_LOCATION];
+ char * filePath = t.filePath;
+
+ StripLastDirectory(filePath, testFolder);
+ PathCat(testFolder, "release");
+ MakeDir(testFolder);
+
+ StripLastDirectory(filePath, testFolder);
+ GetLastDirectory(filePath, epjName);
+ strcpy(makefileOut, testFolder);
+ PathCat(makefileOut, "makefile.test");
+
+ // epj2makePipe = DualPipeOpenf({ output = true },"epj2make -l /usr/ecere/lib -o %s %s > /dev/null", makefileOut, t.filePath);
+ //epj2makePipe = DualPipeOpenf({ output = true },"epj2make -cpp cpp -l /usr/ecere/lib -o %s %s", makefileOut, filePath);
+ //epj2makePipe.Wait();
+ CreateMakefile(filePath, makefileOut);
+
+ delete filePath;
+ //return epj2makePipe.GetExitCode();
+ return 0;
+ }
+
+ char* Copy2Temp(File f, String tmpPath)
+ {
+ File tmp;
+ char tmpFilename[MAX_LOCATION];
+ tmp = CreateTemporaryFile(tmpFilename, tmpPath);
+ CopyFile(f, tmp);
+ tmp.Flush();
+ return tmpFilename;
+ }
+
+ int BuildTest(TestRun run)
+ {
+ DualPipe makePipe;
+ int makeSuccess;
+ char makefileOut[MAX_LOCATION];
+ char * filePath = run.test.filePath;
+ char oldDir[MAX_LOCATION];
+ StripLastDirectory(filePath, makefileOut);
+
+ GetWorkingDir(oldDir, sizeof(oldDir));
+ ChangeWorkingDir(makefileOut);
+ PathCat(makefileOut, "makefile.test");
+
+ //Execute("make -f %s clean", makefileOut);
+
+ makePipe = DualPipeOpenf({ output = true },"make -f %s clean", makefileOut);
+ {
+ TempFile f { };
+ char makeBuffer[1024];
+ int size=1024;
+ uint count;
+ while(!makePipe.Eof())
+ {
+ count = makePipe.Read(makeBuffer,1,sizeof(makeBuffer));
+ f.Write(makeBuffer, 1, count);
+ }
+ run.makeOutput = f;
+ }
+ delete makePipe;
+
+ makePipe = DualPipeOpenf({ output = true },"make -f %s", makefileOut);
+ {
+ TempFile f { };
+ char makeBuffer[1024];
+ int size=1024;
+ uint count;
+ while(!makePipe.Eof())
+ {
+ count = makePipe.Read(makeBuffer,1,sizeof(makeBuffer));
+ f.Write(makeBuffer, 1, count);
+ }
+ run.makeOutput = f;
+ }
+ //makePipe.Wait();
+ ChangeWorkingDir(oldDir);
+ makeSuccess = makePipe.GetExitCode();
+ run.makeReturnValue = makeSuccess;
+ return makeSuccess;
+ }
+ void AddOutputFiles(TestRun run)
+ {
+ char testFolder[MAX_LOCATION];
+ FileListing fl;
+ char * filePath = run.test.filePath;
+ StripLastDirectory(filePath, testFolder);
+ PathCat(testFolder, "release");
+
+ fl = { testFolder, extensions = "c, ec, sym, imp" }; // ["c", "ec", "sym", "imp"] perhaps?
+ while(fl.Find())
+ {
+ File f;
+ RowOutputFiles of { };
+ char extension[MAX_LOCATION];
+ DateTime rightNow { };
+ f = FileOpen(fl.path, read);
+
+ of.Add();
+ of.id = of.sysID;
+ of.outputFile = f;
+ of.filePath = fl.path;
+ of.test = run.test;
+ of.run = run;
+ GetExtension(fl.path, extension);
+ if(!strcmp(extension,"c"))
+ {
+ of.type = c;
+ }
+ else if(!strcmp(extension,"ec"))
+ {
+ of.type = ec;
+ }
+ else if(!strcmp(extension,"sym"))
+ {
+ of.type = sym;
+ }
+ else if(!strcmp(extension,"imp"))
+ {
+ of.type = imp;
+ }
+ rightNow.GetLocalTime();
+ of.created = (TimeStamp)rightNow;
+ delete f;
+ }
+ delete filePath;
+ }
+}
+
+void CopyFile(File input, File output)
+{
+ byte buffer[65536];
+ input.Seek(0, start);
+ for(;!input.Eof();)
+ {
+ uint count = input.Read(buffer, 1, sizeof(buffer));
+ if(count)
+ {
+ int yo = output.Write(buffer, 1, count);
+ }
+ }
+}
+
+class RelativeTimeStamp : TimeStamp
+{
+ char * OnGetString(char * tempString, void * fieldData, bool * needClass)
+ {
+ int64 count;
+ int days;
+ String units;
+ DateTime dt { };
+ TimeStamp rightNow;
+ dt.GetLocalTime();
+ rightNow = (TimeStamp)dt;
+ count = (int64)(rightNow - (TimeStamp)this);
+ if(count >= 60)
+ {
+ count /= 60;
+ if(count >= 60)
+ {
+ count /= 60;
+ if(count >= 24)
+ {
+ count /= 24;
+ if(count >= 7)
+ {
+ days = (int)count;
+ count /= 7;
+ if(days >= 30)
+ {
+ count = days / 30;
+ if(days >= 365)
+ {
+ count = days / 365;
+ units = "year";
+ }
+ else
+ {
+ units = "month";
+ }
+ }
+ else
+ {
+ units = "week";
+ }
+ }
+ else
+ {
+ units = "day";
+ }
+ }
+ else
+ {
+ units = "hour";
+ }
+ }
+ else
+ {
+ units = "minute";
+ }
+ }
+ else
+ {
+ count = 0;
+ }
+ if(count == 0)
+ {
+ PrintBuf(tempString, 1024, "<1 minute ago");
+ }
+ else
+ {
+ PrintBuf(tempString, 1024, count, " ", units, (count > 1)? "s" : "", " ago");
+ }
+ return tempString;
+ }
+}
+
+enum BuildStatus
+{
+ success, failure;
+ void OnDisplay(Surface surface,
+ int x, int y, int width,
+ TrumpDialog trumpDialog,
+ Alignment alignment,
+ DataDisplayFlags flags)
+ {
+ Bitmap b;
+ if(this==success)
+ {
+ b = theTestSuiteWindow.makeSuccess.bitmap;
+ }
+ else
+ {
+ b = theTestSuiteWindow.makeFailure.bitmap;
+ }
+ surface.Blit(b, x, y, 0, 0, b.width, b.height);
+ }
+};
+
+class TestSuiteWindow : Window
+{
+ text = "Ecere Compiler Tests";
+ background = activeBorder;
+ borderStyle = sizable;
+ hasMaximize = true;
+ hasMinimize = true;
+ hasClose = true;
+ size = { 520, 600 };
+ anchor = { horz = -3, vert = 80 };
+
+ BitmapResource makeSuccess { ":check.png" , window = this };
+ BitmapResource makeFailure { ":x.png", window = this };
+
+ TestSuiteWindow()
+ {
+ testListBox.AddField(fieldName);
+ testListBox.AddField(fieldActive);
+
+ runsListBox.AddField(fieldBuildStatus);
+ runsListBox.AddField(fieldAuraColor);
+ runsListBox.AddField(fieldRun);
+ runsListBox.AddField(fieldSaved);
+ // LoadTests(); FIXME this causes a segfault (but not OnCreate)
+ Print("starting up...\n");
+ }
+
+ PaneSplitter windowPanes
+ {
+ this, leftPane = testListBox, rightPane = runSection, split = 200;
+ };
+ Window runSection
+ {
+ this, anchor = { top = 0, bottom = 30, left = 0, right = 0 };
+ };
+ PaneSplitter runPanes
+ {
+ runSection, leftPane = dataBox, rightPane = runsListBox, split = 100, orientation = horizontal;
+ };
+
+ Timer timer
+ {
+ this,
+ delay = 30,
+ started = true;
+
+ bool DelayExpired()
+ {
+ runsListBox.Update(null);
+ return true;
+ }
+ };
+
+ void NewTest(RowTests tRow, char* testName, char* testFilePath)
+ {
+ tRow.Add();
+ tRow.id = tRow.sysID;
+ tRow.active=true;
+ tRow.name=testName;
+ tRow.filePath = testFilePath;
+ }
+
+ DataRow AddTest(RowTests tRow)
+ {
+ DataRow row;
+ String s;
+ row = testListBox.AddRow();
+ row.tag = tRow.id;
+ s = tRow.name; row.SetData(fieldName, s); delete s;
+ row.SetData(fieldActive, tRow.active);
+ return row;
+ }
+
+ void DeleteTest(ListBox testListBox, DataRow row)
+ {
+ // do we also delete all runs and files associated with this test?
+ RowTests tRow { };
+ tRow.sysID=row.tag;
+ tRow.Delete();
+ delete tRow; // won't be needed in the (distant?) future :-)
+ testListBox.DeleteRow(row);
+ }
+
+ void LoadTests()
+ {
+ RowTests tRow { };
+ while(tRow.Next())
+ {
+ theTestSuiteWindow.AddTest(tRow);
+ }
+ delete tRow;
+ }
+
+ DataField fieldName { width = 140, header = "Name" , dataType = class(char*), editable = true };
+ DataField fieldActive { width = 40, header = "Active", dataType = class(bool) };
+
+ ListBox testListBox
+ {
+ this,
+ anchor = { top = 2, bottom = 30, left = 2, right = 2 },
+ hasHeader = true;
+
+ bool NotifyChanged(ListBox testListBox, DataRow row)
+ {
+ RowTests tRow { };
+ tRow.sysID=row.tag;
+ tRow.name = row.GetData(fieldName);
+ tRow.active = row.GetData(fieldActive);
+ delete tRow;
+ return true;
+ }
+
+ bool NotifyKeyDown(ListBox testListBox, DataRow row, Key key, unichar ch)
+ {
+ if(key == del)
+ {
+ DeleteTest(testListBox, row);
+ // bRemove.NotifyClicked(this, bRemove,0,0,0);
+ }
+ else if(key == space)
+ {
+ //bool newActiveStatus = !(*(bool*)row.GetData(fieldActive)); // FIXME is needed?
+ row.SetData(fieldActive, !row.GetData(fieldActive));
+ testListBox.NotifyChanged(this, testListBox, row);
+ return false;
+ }
+ return true;
+ }
+
+ bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
+ {
+ dataBox.Clear();
+ if(row)
+ {
+ { // print to data box
+ Test t;
+ char* tname;
+ char* tpath;
+ bool tactive;
+ t = (Test)row.tag;
+ tname = t.name;
+ tpath = t.filePath;
+ tactive = t.active;
+ dataBox.Printf("Name: %s\n", tname);
+ dataBox.Printf("Location: %s\n", tpath);
+ dataBox.Printf("Active: %d\n", tactive);
+ delete tname; delete tpath;
+ }
+ { // show test runs
+ Test t;
+ Array<TestRun> runs;
+ AccessMacros amacs{ };
+ t = (Test)row.tag;
+ runs = amacs.allTestRuns(t);
+ runsListBox.Clear();
+ for(tr : runs)
+ {
+ DataRow row;
+ BuildStatus buildStatus;
+ TimeStamp time = tr.time;
+ MD5Digest aura = tr.digest;
+ buildStatus = tr.makeReturnValue ? failure : success;
+ row = runsListBox.AddRow();
+ row.tag = tr;
+ row.SetData(fieldBuildStatus, buildStatus);
+ row.SetData(fieldAuraColor, aura);
+ row.SetData(fieldRun, time);
+ row.SetData(fieldSaved, tr.save);
+ }
+ }
+ }
+ return true;
+ }
+ };
+
+ DataField fieldBuildStatus { width = 40, dataType = class(BuildStatus), header = "Make" };
+ DataField fieldAuraColor { width = 40, dataType = class(MD5Digest), header = "Aura" };
+ DataField fieldRun { width = 120, dataType = class(RelativeTimeStamp), header = "Run" };
+ DataField fieldSaved { width = 80, dataType = class(bool), header = "Save", editable = true };
+
+ ListBox runsListBox
+ {
+ parent = runSection,
+ master=this,
+ anchor = { top = 0, bottom = 0, left = 0, right = 0 },
+ hasHeader = true;
+
+ bool NotifyChanged(ListBox listBox, DataRow row)
+ {
+ TestRun tr = (TestRun)row.tag;
+ tr.save = row.GetData(fieldSaved);
+ return true;
+ }
+ };
+ EditBox dataBox
+ {
+ parent = runSection,
+ master=this,
+ opacity = 0,
+ inactive = true,
+ anchor = { top = 0, bottom = 0, left = 0, right = 0 },
+ hasHorzScroll = true,
+ readOnly = true,
+ multiLine = true,
+ noCaret = true
+ };
+ Button addTest
+ {
+ parent=this,
+ text = "Add",
+ hotKey=altA,
+ anchor = { bottom = 2, left = 2 };
+
+ bool NotifyClicked(Button button, int x, int y, Modifiers mods)
+ {
+ FileFilter projectFilters[] =
+ {
+ { "eC project and source files (.ec, .epj)", "ec, epj" }
+ };
+ FileDialog f { filters = projectFilters, sizeFilters = sizeof(projectFilters), type = multiOpen };
+ incref f;
+ if(f.Modal()== ok)
+ {
+ int i;
+ RowTests tRow { };
+ for(i=0; i<f.numSelections; ++i)
+ {
+ char testName[MAX_LOCATION];
+ DataRow row;
+ GetLastDirectory(f.multiFilePaths[i], testName);
+ NewTest(tRow, testName, f.multiFilePaths[i]);
+ row = AddTest(tRow);
+ if(i+1 == f.numSelections)
+ {
+ testListBox.SelectRow(row);
+ }
+ }
+ }
+ delete f;
+ //Refocus();
+ return true;
+ }
+ };
+ Button runTests
+ {
+ parent = this,
+ text = "Run",
+ hotKey = altR,
+ anchor = { bottom = 2, right = 2 };
+
+ bool NotifyClicked(Button button, int x, int y, Modifiers mods)
+ {
+ DataRow row;
+ for(row=testListBox.firstRow; row; row=row.next)
+ {
+ Test t = (Test)row.tag;
+ if(!t.active)
+ {
+ continue;
+ }
+ else
+ {
+ BuildTool bt { };
+ DiffThread dt { };
+ DateTime rightNow { };
+ RowRuns runs { };
+ TestRun run;
+ runs.Add();
+ runs.id = runs.sysID;
+ rightNow.GetLocalTime();
+ runs.time = (TimeStamp)rightNow;
+ runs.test = t;
+ run = runs.id;
+ bt.GenerateMakefile(t);
+ bt.BuildTest(run);
+ bt.AddOutputFiles(run);
+ runs.digest = run;
+ if(!t.reference)
+ {
+ t.reference = run;
+ }
+ else
+ {
+ DiffThread dt { };
+ Array<OutputFile> outputsLatest = AccessMacros::allOutputFiles(run);
+ Array<OutputFile> outputsReference = AccessMacros::allOutputFiles(t.reference);
+ dt.DiffDir(outputsReference, outputsLatest);
+ }
+ }
+ testListBox.NotifySelect(this, testListBox, testListBox.currentRow, mods);
+ }
+ return true;
+ }
+ };
+ Button acceptTest
+ {
+ parent=this,
+ text = "Accept Run (x)",
+ hotKey=altX,
+ anchor={ bottom = 2, right = 52 };
+
+ bool NotifyClicked(Button button, int x, int y, Modifiers mods)
+ {
+ DataRow row;
+ MessageBox confirmation
+ {
+ type = yesNo,
+ text = "Accept Test",
+ contents = "Accept the selected test?"
+ };
+ if(confirmation.Modal() == yes)
+ {
+ TestRun tr;
+ row = runsListBox.currentRow;
+ if(row)
+ {
+ tr = (TestRun)row.tag;
+ tr.save = true;
+ tr.test.reference = tr;
+ }
+ }
+ return true;
+ }
+ }
+ bool OnCreate()
+ {
+ globalSettings.Load();
+
+ LoadTests();
+ delete theGlobalSettings.diffTool;
+ theGlobalSettings.diffTool = CopyString("meld");
+ // theGlobalSettings.diffTool = CopyString("C:/Program Files/Araxis/Araxis Merge v6.5/compare.exe /wait");
+ return true;
+ }
+}
+
+TestSuiteWindow theTestSuiteWindow { };
+TestSuiteGlobalSettings theGlobalSettings { };