From 731c2c262ebc08d95f917a60520f2936e1bed003 Mon Sep 17 00:00:00 2001 From: Jerome St-Louis Date: Tue, 17 May 2011 01:00:49 -0400 Subject: [PATCH] Initial Git commit (A bit rusty... please fix, test runs fail right now) --- res/check.png | Bin 0 -> 2913 bytes res/x.png | Bin 0 -> 2940 bytes testSuite.ec | 983 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ testSuite.epj | 63 ++++ 4 files changed, 1046 insertions(+) create mode 100644 res/check.png create mode 100644 res/x.png create mode 100644 testSuite.ec create mode 100644 testSuite.epj diff --git a/res/check.png b/res/check.png new file mode 100644 index 0000000000000000000000000000000000000000..efde21585ae75b104f039412ee11a81bfc8ddbc8 GIT binary patch literal 2913 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 LNkvXXu0mjfK;C3Y literal 0 HcmV?d00001 diff --git a/res/x.png b/res/x.png new file mode 100644 index 0000000000000000000000000000000000000000..9438c2b91ecda735a41a1bd818f2084b127c6a04 GIT binary patch literal 2940 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 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 ::allTestRuns(Test t) + { + Array 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 ::allOutputFiles(TestRun t) + { + Array 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 files; + Array 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 outputOrig, Array 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 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 outputsLatest = AccessMacros::allOutputFiles(run); + Array 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 { }; diff --git a/testSuite.epj b/testSuite.epj new file mode 100644 index 0000000..1b9e69d --- /dev/null +++ b/testSuite.epj @@ -0,0 +1,63 @@ +{ + "Version" : 0.2, + "ModuleName" : "testSuite", + "Options" : { + "Warnings" : "All", + "PreprocessorDefinitions" : [ + "MAKEFILE_GENERATOR", + "TEST_SUITE" + ], + "TargetType" : "Executable", + "TargetFileName" : "testSuite", + "Libraries" : [ + "ecere" + ], + "Console" : true + }, + "Configurations" : [ + { + "Name" : "Debug", + "Options" : { + "Debug" : true, + "Optimization" : "None", + "PreprocessorDefinitions" : [ + "_DEBUG" + ] + } + }, + { + "Name" : "Release", + "Options" : { + "Debug" : false, + "Optimization" : "Speed" + } + } + ], + "Files" : [ + { + "Folder" : "extern", + "Files" : [ + { + "Folder" : "project", + "Files" : [ + "/sdk/ide/src/project/Project.ec", + "/sdk/ide/src/project/ProjectConfig.ec", + "/sdk/ide/src/project/ProjectNode.ec" + ] + }, + "/sdk/extras/md5.ec", + "../sdk/ide/src/IDESettings.ec", + "../sdk/extras/gui/controls/PathBox.ec", + "../sdk/extras/gui/controls/StringsBox.ec", + "../sdk/ide/src/OldIDESettings.ec" + ] + }, + "testSuite.ec", + "TODO.txt" + ], + "ResourcesPath" : "", + "Resources" : [ + "res/check.png", + "res/x.png" + ] +} \ No newline at end of file -- 1.8.3.1