// checkCheckPoint tests that a checkpoint happened at the requested delay // in seconds (+/- margin) func checkCheckPoint(testDir string, c *tomlParser.TestCase) error { path := file.GetOutputDir(testDir) stamp := filepath.Join(path, c.BaseName+".stamp") stampi, err := os.Stat(stamp) if err != nil { return fmt.Errorf("Failed to stat file %s", stamp) } stampTime := stampi.ModTime() checkpt := filepath.Join(path, c.BaseName+".cp") checkpti, err := os.Stat(checkpt) if err != nil { return fmt.Errorf("Failed to stat file %s", checkpt) } checkTime := checkpti.ModTime() if checkTime.Sub(stampTime).Seconds() < c.Delay-c.Margin { return fmt.Errorf("Realtime checkpoint scheduled for %f seconds but "+ "time between timestamp and checkpoint is less than %f seconds", c.Delay, c.Delay-c.Margin) } if checkTime.Sub(stampTime).Seconds() > c.Delay+c.Margin { return fmt.Errorf("Realtime checkpoint scheduled for %f seconds but "+ "time between timestamp and checkpoint exceeds %f seconds", c.Delay, c.Delay+c.Margin) } return nil }
// createSimJobs is responsible for filling a worker queue with // jobs to be run via the simulation tool. It parses the test // description, assembles a TestDescription struct and adds it // to the simulation job queue. func createSimJobs(includePath string, testPaths []string, simJobs chan *tester.TestData, testResults chan *tester.TestResult) { runID := 0 for _, testDir := range testPaths { testFile := filepath.Join(testDir, "test_description.json") testDescription, err := jsonParser.Parse(testFile, includePath) if err != nil { msg := fmt.Sprintf("Error parsing test description in %s: %v", testDir, err) testResults <- &tester.TestResult{Path: testFile, Success: false, TestName: "parse description", ErrorMessage: msg} continue } // create output directory outputDir := file.GetOutputDir(testDir) if err := os.Mkdir(outputDir, 0744); err != nil { msg := fmt.Sprint(err) testResults <- &tester.TestResult{Path: testFile, Success: false, TestName: "create test output directory", ErrorMessage: msg} continue } // set path and pick a Seed value for run testDescription.Path = testDir testDescription.Run.RunID = runID // schedule requested number of Seeds; if there is just a single // Seed requested we pick one randomly switch testDescription.Run.NumSeeds { case 0: // user didn't set number of Seeds -- assume single Seed testDescription.Run.NumSeeds = 1 testDescription.Run.Seed = rng.Intn(10000) case 1: testDescription.Run.Seed = rng.Intn(10000) default: for i := 1; i < testDescription.Run.NumSeeds; i++ { newTest := testDescription.Copy() newTest.Run.Seed = i testDescription.Run.Seed = i + 1 simJobs <- &tester.TestData{newTest, nil} } } simJobs <- &tester.TestData{testDescription, nil} runID++ } close(simJobs) }
// simRunner runs mcell on the mdl file passed in as an // absolute path. The working directory is set to the base path // of the mdl file. func simRunner(mcellPath string, test *tester.TestData, output chan *tester.TestData) { outputDir := file.GetOutputDir(test.Path) for i, runFile := range test.Run.MdlFiles { // create run command mdlPath := filepath.Join(test.Path, runFile) runLog := fmt.Sprintf("run_%d.%d.log", test.Run.Seed, i) errLog := fmt.Sprintf("err_%d.%d.log", test.Run.Seed, i) argList := append(test.Run.CommandlineOpts, "-seed", strconv.Itoa(test.Run.Seed), "-logfile", runLog, "-errfile", errLog, mdlPath) cmd := exec.Command(mcellPath, argList...) cmd.Dir = outputDir if err := misc.WriteCmdLine(mcellPath, outputDir, argList); err != nil { test.SimStatus = append(test.SimStatus, tester.RunStatus{Success: false, ExitMessage: fmt.Sprint(err), StdErrContent: "", ExitCode: -1}) output <- test return } // connect stdout and stderr stdOutPath := fmt.Sprintf("stdout_%d.%d.log", test.Run.Seed, i) stdOut, err := os.Create(filepath.Join(outputDir, stdOutPath)) if err != nil { test.SimStatus = append(test.SimStatus, tester.RunStatus{Success: false, ExitMessage: fmt.Sprint(err), StdErrContent: "", ExitCode: -1}) output <- test return } defer stdOut.Close() cmd.Stdout = stdOut stdErrPath := fmt.Sprintf("stderr_%d.%d.log", test.Run.Seed, i) stdErr, err := os.Create(filepath.Join(outputDir, stdErrPath)) if err != nil { test.SimStatus = append(test.SimStatus, tester.RunStatus{Success: false, ExitMessage: fmt.Sprint(err), StdErrContent: "", ExitCode: -1}) output <- test return } defer stdErr.Close() cmd.Stderr = stdErr err = cmd.Run() if err != nil { stdErr, _ := ioutil.ReadFile(filepath.Join(outputDir, errLog)) exitCode, err := misc.DetermineExitCode(err) if err != nil { exitCode = -1 } test.SimStatus = append(test.SimStatus, tester.RunStatus{Success: false, ExitMessage: fmt.Sprint(err), StdErrContent: string(stdErr), ExitCode: exitCode}) } else { test.SimStatus = append(test.SimStatus, tester.RunStatus{Success: true, ExitMessage: "", StdErrContent: "", ExitCode: 0}) } } output <- test }