TEST_F(ProjectFixture, AttributeRecord_ManyAnnualEndUses) { ProjectDatabase database = getCleanDatabase("AttributeRecord_ManyAnnualEndUses"); for (unsigned i = 0; i < 10; ++i){ EndUses endUses; endUses.addEndUse(25.0, EndUseFuelType::Gas, EndUseCategoryType::Heating); endUses.addEndUse(2.0, EndUseFuelType::Electricity, EndUseCategoryType::Cooling); endUses.addEndUse(1.0, EndUseFuelType::Electricity, EndUseCategoryType::InteriorLights); endUses.addEndUse(10.0, EndUseFuelType::Electricity, EndUseCategoryType::Fans, "Fan Energy"); endUses.addEndUse(10.0, EndUseFuelType::Water, EndUseCategoryType::Humidifier); std::stringstream ss; ss << "model " << i; FileReferenceRecord model(FileReference(toPath("./in.osm")),database); AttributeRecord attributeRecord(endUses.attribute(), model); ASSERT_TRUE(model.getAttributeRecord(EndUses::attributeName())); EXPECT_TRUE(endUses.attribute() == model.getAttributeRecord(EndUses::attributeName()).get().attribute()); } database.save(); }
// Test not yet to scale re: data points. TEST_F(ProjectFixture,Profile_SaveAnalysis) { Analysis analysis = getAnalysisToRun(100,500); // time the process of saving to database ptime start = microsec_clock::local_time(); ProjectDatabase db = getCleanDatabase(toPath("./SaveAnalysis")); ASSERT_TRUE(db.startTransaction()); AnalysisRecord record(analysis,db); db.save(); ASSERT_TRUE(db.commitTransaction()); time_duration saveTime = microsec_clock::local_time() - start; std::cout << "Time: " << to_simple_string(saveTime) << std::endl; }
TEST_F(ProjectFixture, AttributeRecord_AttributeTypes) { ProjectDatabase database = getCleanDatabase("AttributeRecord_AttributeTypes"); FileReferenceRecord model(FileReference(toPath("./in.osm")),database); EXPECT_EQ(static_cast<unsigned>(0), AttributeRecord::getAttributeRecords(database).size()); EXPECT_EQ(static_cast<unsigned>(0), model.attributeRecords().size()); // make attributes Attribute boolAttribute("bool", true); Attribute unsignedAttribute("unsigned", 2u); Attribute intAttribute("int", -1); Attribute doubleAttribute("double", 1.23, std::string("m")); Attribute stringAttribute("string", "hello"); // because of tracking by UUID, have to make separate child attributes AttributeVector childAttributes; childAttributes.push_back(Attribute("bool", true)); childAttributes.push_back(Attribute("bool", true)); Attribute vectorAttribute("vector", childAttributes); // create AttributeRecords AttributeRecord boolAttributeRecord(boolAttribute, model); AttributeRecord unsignedAttributeRecord(unsignedAttribute, model); AttributeRecord intAttributeRecord(intAttribute, model); AttributeRecord doubleAttributeRecord(doubleAttribute, model); AttributeRecord stringAttributeRecord(stringAttribute, model); AttributeRecord vectorAttributeRecord(vectorAttribute, model); ASSERT_TRUE(model.getAttributeRecord("bool")); EXPECT_TRUE(boolAttribute == model.getAttributeRecord("bool").get().attribute()); ASSERT_TRUE(model.getAttributeRecord("unsigned")); EXPECT_TRUE(unsignedAttribute == model.getAttributeRecord("unsigned").get().attribute()); ASSERT_TRUE(model.getAttributeRecord("int")); EXPECT_TRUE(intAttribute == model.getAttributeRecord("int").get().attribute()); ASSERT_TRUE(model.getAttributeRecord("double")); EXPECT_TRUE(doubleAttribute == model.getAttributeRecord("double").get().attribute()); ASSERT_TRUE(model.getAttributeRecord("string")); EXPECT_TRUE(stringAttribute == model.getAttributeRecord("string").get().attribute()); ASSERT_TRUE(model.getAttributeRecord("vector")); EXPECT_TRUE(vectorAttribute == model.getAttributeRecord("vector").get().attribute()); EXPECT_EQ(static_cast<unsigned>(6), AttributeRecord::getAttributeRecords(database).size()); EXPECT_EQ(static_cast<unsigned>(6), model.attributeRecords().size()); database.save(); }
TEST_F(ProjectFixture, ProblemRecord_RubyContinuousVariables) { // Create a database containing a ProblemRecord with a chain of // RubyContinuousVariables that reference the same RubyMeasure analysis::Problem problem("Contains Linked RubyContinuousVariables"); // Measure with two RubyContinuousVariables analysis::RubyMeasure wwrScript(openstudio::toPath(rubyLibDir()) / openstudio::toPath("openstudio/sketchup_plugin/user_scripts/Alter or Add Model Elements/Set_Window_to_Wall_Ratio.rb"), FileReferenceType::OSM, FileReferenceType::OSM, true); ruleset::OSArgument arg = ruleset::OSArgument::makeDoubleArgument("wwr"); analysis::RubyContinuousVariable wwr("Window to Wall Ratio",arg,wwrScript); wwr.setMinimum(0.15); wwr.setMaximum(0.60); problem.push(wwr); arg = ruleset::OSArgument::makeDoubleArgument("offset"); analysis::RubyContinuousVariable offset("Window Offset from Floor",arg,wwrScript); offset.setMinimum(0.5); offset.setMaximum(2.0); problem.push(offset); EXPECT_EQ(wwr.measure(), offset.measure()); // Project Database ProjectDatabase database = getCleanDatabase("ProblemRecord_RubyContinuousVariables"); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problem,database); database.save(); // Deserialize the problem and verify that the deserialized RubyMeasures are // all equal. problemRecord = ProblemRecord::getProblemRecords(database)[0]; problem = problemRecord.problem(); ASSERT_EQ(2u,problem.variables().size()); ASSERT_TRUE(problem.variables()[0].optionalCast<RubyContinuousVariable>()); ASSERT_TRUE(problem.variables()[1].optionalCast<RubyContinuousVariable>()); EXPECT_EQ(problem.variables()[0].cast<RubyContinuousVariable>().measure(), problem.variables()[1].cast<RubyContinuousVariable>().measure()); }
TEST_F(ProjectFixture,CloudSessionRecord_VagrantPopulated) { std::string id; UUID uuid, versionUUID; { ProjectDatabase database = getCleanDatabase("CloudSessionRecord_VagrantPopulated"); VagrantSession session(toString(createUUID()), Url("http://localhost:8080"), UrlVector(1u,Url("http://localhost:8081"))); id = session.sessionId(); uuid = session.uuid(); versionUUID = session.versionUUID(); CloudSessionRecord record = CloudSessionRecord::factoryFromCloudSession(session,database); database.save(); EXPECT_EQ(1u,CloudSessionRecord::getCloudSessionRecords(database).size()); } { ProjectDatabase database = getExistingDatabase("CloudSessionRecord_VagrantPopulated"); EXPECT_EQ(1u,CloudSessionRecord::getCloudSessionRecords(database).size()); ASSERT_FALSE(CloudSessionRecord::getCloudSessionRecords(database).empty()); CloudSessionRecord record = CloudSessionRecord::getCloudSessionRecords(database)[0]; CloudSession session = record.cloudSession(); ASSERT_TRUE(session.optionalCast<VagrantSession>()); VagrantSession vagrantSession = session.cast<VagrantSession>(); EXPECT_EQ(uuid,vagrantSession.uuid()); EXPECT_EQ(versionUUID,vagrantSession.versionUUID()); EXPECT_EQ("VagrantProvider",vagrantSession.cloudProviderType()); EXPECT_EQ(id,vagrantSession.sessionId()); ASSERT_TRUE(vagrantSession.serverUrl()); EXPECT_EQ(Url("http://localhost:8080"),vagrantSession.serverUrl().get()); ASSERT_EQ(1u,vagrantSession.workerUrls().size()); EXPECT_EQ(Url("http://localhost:8081"),vagrantSession.workerUrls()[0]); } }
TEST_F(ProjectFixture, RubyContinuousVariableRecord_SaveAndRetrieve) { openstudio::path perturbScript = openstudio::toPath(rubyLibDir()) / openstudio::toPath("openstudio/runmanager/rubyscripts/PerturbObject.rb"); RubyMeasure rubyMeasure(perturbScript,FileReferenceType::OSM,FileReferenceType::OSM); rubyMeasure.addArgument("objectType","OS:Material"); rubyMeasure.addArgument("nameRegex","Insulation"); rubyMeasure.addArgument("field","2"); ruleset::OSArgument thickness = ruleset::OSArgument::makeDoubleArgument("Thickness"); RubyContinuousVariable insulationThickness("Insulation Thickness",thickness,rubyMeasure); Problem problem("Trivial Problem",VariableVector(1u,insulationThickness),runmanager::Workflow()); int id(0); { ProjectDatabase database = getCleanDatabase("RubyContinuousVariableRecord_SaveAndRetrieve"); ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problem,database); id = problemRecord.id(); database.save(); } { ProjectDatabase database = getExistingDatabase("RubyContinuousVariableRecord_SaveAndRetrieve"); OptionalProblemRecord oProblemRecord = ProblemRecord::getProblemRecord(id,database); ASSERT_TRUE(oProblemRecord); problem = oProblemRecord->problem(); } EXPECT_EQ(1,problem.numVariables()); ASSERT_TRUE(problem.variables()[0].optionalCast<RubyContinuousVariable>()); insulationThickness = problem.variables()[0].cast<RubyContinuousVariable>(); EXPECT_EQ("Thickness",insulationThickness.argument().name()); EXPECT_EQ(3u,insulationThickness.perturbation().arguments().size()); }
TEST_F(ProjectFixture,CloudSessionRecord_AWSDefault) { { ProjectDatabase database = getCleanDatabase("CloudSessionRecord_AWSDefault"); AWSProvider provider; CloudSession session = provider.session(); CloudSessionRecord record = CloudSessionRecord::factoryFromCloudSession(session,database); database.save(); EXPECT_EQ(1u,CloudSessionRecord::getCloudSessionRecords(database).size()); } { ProjectDatabase database = getExistingDatabase("CloudSessionRecord_AWSDefault"); EXPECT_EQ(1u,CloudSessionRecord::getCloudSessionRecords(database).size()); ASSERT_FALSE(CloudSessionRecord::getCloudSessionRecords(database).empty()); CloudSessionRecord record = CloudSessionRecord::getCloudSessionRecords(database)[0]; CloudSession session = record.cloudSession(); EXPECT_TRUE(session.optionalCast<AWSSession>()); } }
TEST_F(ProjectFixture, WorkflowRecord_Base) { ProjectDatabase database = getCleanDatabase("WorkflowRecord_Base"); EXPECT_EQ(database.timestampCreate(), database.timestampLast()); EXPECT_EQ(database.handle(), database.uuidLast()); openstudio::System::msleep(1000); EXPECT_EQ(static_cast<unsigned>(0), WorkflowRecord::getWorkflowRecords(database).size()); openstudio::runmanager::Workflow rmWorkflow; rmWorkflow.addJob(openstudio::runmanager::JobType::Null, ""); // Fake ProblemRecord so can test WorkflowRecord Problem problem("Dummy",WorkflowStepVector()); ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problem,database); WorkflowRecord workflowRecord(rmWorkflow, problemRecord, 0); EXPECT_EQ("", workflowRecord.name()); EXPECT_EQ("", workflowRecord.displayName()); EXPECT_EQ("", workflowRecord.description()); EXPECT_TRUE(workflowRecord.timestampCreate() > database.timestampCreate()); EXPECT_EQ(workflowRecord.timestampCreate(), workflowRecord.timestampLast()); EXPECT_EQ(workflowRecord.handle(), rmWorkflow.uuid()); EXPECT_EQ(database.timestampLast(), database.timestampCreate()); EXPECT_EQ(database.handle(), database.uuidLast()); openstudio::System::msleep(1000); database.save(); EXPECT_TRUE(database.timestampLast() > database.timestampCreate()); EXPECT_NE(database.handle(), database.uuidLast()); DateTime databaseTimestampLast = database.timestampLast(); UUID databaseUUIDLast = database.uuidLast(); openstudio::System::msleep(1000); database.save(); EXPECT_EQ(database.timestampLast(), databaseTimestampLast); EXPECT_EQ(database.uuidLast(), databaseUUIDLast); EXPECT_EQ(static_cast<unsigned>(1), WorkflowRecord::getWorkflowRecords(database).size()); EXPECT_EQ(database.timestampLast(), databaseTimestampLast); EXPECT_EQ(database.uuidLast(), databaseUUIDLast); EXPECT_EQ(workflowRecord.timestampCreate(), workflowRecord.timestampLast()); EXPECT_EQ(workflowRecord.handle(), rmWorkflow.uuid()); EXPECT_TRUE(workflowRecord.setDescription("A simple workflowRecord")); EXPECT_EQ(database.timestampLast(), databaseTimestampLast); EXPECT_EQ(database.uuidLast(), databaseUUIDLast); EXPECT_TRUE(workflowRecord.timestampCreate() < workflowRecord.timestampLast()); EXPECT_NE(workflowRecord.handle(), workflowRecord.uuidLast()); openstudio::System::msleep(1000); database.save(); EXPECT_TRUE(databaseTimestampLast < database.timestampLast()); EXPECT_NE(database.uuidLast(), databaseUUIDLast); EXPECT_TRUE(workflowRecord.timestampCreate() < workflowRecord.timestampLast()); EXPECT_NE(workflowRecord.handle(), workflowRecord.uuidLast()); databaseTimestampLast = database.timestampLast(); databaseUUIDLast = database.uuidLast(); DateTime workflowTimestampLast = workflowRecord.timestampLast(); UUID workflowUUIDLast = workflowRecord.uuidLast(); EXPECT_EQ(static_cast<unsigned>(1), WorkflowRecord::getWorkflowRecords(database).size()); EXPECT_EQ(database.timestampLast(), databaseTimestampLast); EXPECT_EQ(database.uuidLast(), databaseUUIDLast); EXPECT_EQ(workflowRecord.timestampLast(), workflowTimestampLast); EXPECT_EQ(workflowRecord.uuidLast(), workflowUUIDLast); EXPECT_TRUE(database.removeRecord(workflowRecord)); EXPECT_EQ(static_cast<unsigned>(0), WorkflowRecord::getWorkflowRecords(database).size()); EXPECT_EQ(database.timestampLast(), databaseTimestampLast); EXPECT_EQ(database.uuidLast(), databaseUUIDLast); EXPECT_EQ(workflowTimestampLast, workflowRecord.timestampLast()); EXPECT_EQ(workflowUUIDLast, workflowRecord.uuidLast()); openstudio::System::msleep(1000); database.save(); EXPECT_TRUE(databaseTimestampLast < database.timestampLast()); EXPECT_NE(database.uuidLast(), databaseUUIDLast); EXPECT_EQ(workflowTimestampLast, workflowRecord.timestampLast()); EXPECT_EQ(workflowUUIDLast, workflowRecord.uuidLast()); }
// Test not yet to scale re: total data points. TEST_F(ProjectFixture,Profile_UpdateAnalysis) { Analysis analysis = getAnalysisToRun(100,500); // save to database ProjectDatabase db = getCleanDatabase(toPath("./UpdateAnalysis")); ASSERT_TRUE(db.startTransaction()); AnalysisRecord record(analysis,db); db.save(); ASSERT_TRUE(db.commitTransaction()); // add output data to 1 data point DataPointVector dataPoints = analysis.dataPoints(); boost::mt19937 mt; typedef boost::uniform_real<> uniform_dist_type; typedef boost::variate_generator<boost::mt19937&, uniform_dist_type> uniform_gen_type; uniform_gen_type responseGenerator(mt,uniform_dist_type(50.0,500.0)); for (int i = 0; i < 1; ++i) { std::stringstream ss; ss << "dataPoint" << i + 1; DoubleVector responseValues; for (int j = 0, n = analysis.problem().responses().size(); j < n; ++j) { responseValues.push_back(responseGenerator()); } openstudio::path runDir = toPath(ss.str()); dataPoints[i] = DataPoint(dataPoints[i].uuid(), createUUID(), dataPoints[i].name(), dataPoints[i].displayName(), dataPoints[i].description(), analysis.problem(), true, false, true, DataPointRunType::Local, dataPoints[i].variableValues(), responseValues, runDir, FileReference(runDir / toPath("ModelToIdf/in.osm")), FileReference(runDir / toPath("ModelToIdf/out.idf")), FileReference(runDir / toPath("EnergyPlus/eplusout.sql")), FileReferenceVector(1u,FileReference(runDir / toPath("Ruby/report.xml"))), boost::optional<runmanager::Job>(), std::vector<openstudio::path>(), TagVector(), AttributeVector()); dataPoints[i].setName(dataPoints[i].name()); // set dirty } analysis = Analysis(analysis.uuid(), analysis.versionUUID(), analysis.name(), analysis.displayName(), analysis.description(), analysis.problem(), analysis.algorithm(), analysis.seed(), analysis.weatherFile(), dataPoints, false, false); analysis.setName(analysis.name()); // set dirty // time the process of updating the database ptime start = microsec_clock::local_time(); db.unloadUnusedCleanRecords(); ASSERT_TRUE(db.startTransaction()); record = AnalysisRecord(analysis,db); db.save(); ASSERT_TRUE(db.commitTransaction()); time_duration updateTime = microsec_clock::local_time() - start; std::cout << "Time: " << to_simple_string(updateTime) << std::endl; }
TEST_F(ProjectFixture, RubyMeasureRecord_RubyScript) { // Measures MeasureVector measures; // Null Measure measures.push_back(NullMeasure()); openstudio::path rubyLibDirPath = openstudio::toPath(rubyLibDir()); openstudio::path perturbScript = rubyLibDirPath/openstudio::toPath("openstudio/runmanager/rubyscripts/PerturbObject.rb"); RubyMeasure rubyMeasure(perturbScript, FileReferenceType::OSM, FileReferenceType::OSM); rubyMeasure.addArgument("inputPath", "in.osm"); rubyMeasure.addArgument("outputPath", "out.osm"); rubyMeasure.addArgument("objectType", "OS:Material"); rubyMeasure.addArgument("nameRegex", "I02 50mm insulation board"); rubyMeasure.addArgument("field", "3"); rubyMeasure.addArgument("value", "0.10"); // RubyMeasure measures.push_back(rubyMeasure); // Variables VariableVector variables; variables.push_back(MeasureGroup("Wall Construction",measures)); // Workflow openstudio::runmanager::Workflow workflow; // Problem Problem problem("Variable",variables,workflow); // Save to database { ProjectDatabase database = getCleanDatabase("RubyMeasureRecord_RubyScript"); bool didStartTransaction = database.startTransaction(); EXPECT_TRUE(didStartTransaction); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problem,database); database.save(); if (didStartTransaction) { EXPECT_TRUE(database.commitTransaction()); } // Variable Records InputVariableRecordVector measureGroupRecords = problemRecord.inputVariableRecords(); EXPECT_EQ(1u,measureGroupRecords.size()); // Discrete Variable Record MeasureGroupRecord measureGroupRecord = measureGroupRecords.at(0).cast<MeasureGroupRecord>(); EXPECT_EQ(2u,measureGroupRecord.measureRecordIds(true).size()); EXPECT_EQ(2u,measureGroupRecord.measureRecords(true).size()); RubyMeasureRecord rubyMeasureRecord(rubyMeasure,measureGroupRecord,0); EXPECT_EQ("MeasureRecords",rubyMeasureRecord.databaseTableName()); ObjectRecordVector objectRecordVector = rubyMeasureRecord.children(); EXPECT_EQ(6u,objectRecordVector.size()); // arguments objectRecordVector = rubyMeasureRecord.resources(); EXPECT_EQ(1u,objectRecordVector.size()); // script FileReferenceRecord scriptRecord = rubyMeasureRecord.fileReferenceRecord(); EXPECT_EQ("FileReferenceRecords",scriptRecord.databaseTableName()); Measure measure = rubyMeasureRecord.measure(); EXPECT_EQ(true,measure.isSelected()); ASSERT_TRUE(measure.optionalCast<RubyMeasure>()); RubyMeasure rubyMeasureCopy = measure.cast<RubyMeasure>(); EXPECT_FALSE(rubyMeasureCopy.usesBCLMeasure()); EXPECT_FALSE(rubyMeasureCopy.isUserScript()); EXPECT_EQ(6u,rubyMeasureCopy.arguments().size()); MeasureGroupRecord measureGroupRecordFromRuby = rubyMeasureRecord.measureGroupRecord().get(); EXPECT_EQ(measureGroupRecord.databaseTableName(),measureGroupRecordFromRuby.databaseTableName()); EXPECT_EQ(measureGroupRecord.id(),measureGroupRecordFromRuby.id()); } // Reopen database { ProjectDatabase database = getExistingDatabase("RubyMeasureRecord_RubyScript"); ProblemRecordVector problemRecords = ProblemRecord::getProblemRecords(database); ASSERT_FALSE(problemRecords.empty()); EXPECT_EQ(1u,problemRecords.size()); ProblemRecord problemRecord = problemRecords[0]; // COPY-PASTED FROM ABOVE // Variable Records InputVariableRecordVector measureGroupRecords = problemRecord.inputVariableRecords(); EXPECT_EQ(1u,measureGroupRecords.size()); // Discrete Variable Record MeasureGroupRecord measureGroupRecord = measureGroupRecords.at(0).cast<MeasureGroupRecord>(); EXPECT_EQ(2u,measureGroupRecord.measureRecordIds(true).size()); EXPECT_EQ(2u,measureGroupRecord.measureRecords(true).size()); RubyMeasureRecord rubyMeasureRecord(rubyMeasure,measureGroupRecord,0); EXPECT_EQ("MeasureRecords",rubyMeasureRecord.databaseTableName()); ObjectRecordVector objectRecordVector = rubyMeasureRecord.children(); EXPECT_EQ(6u,objectRecordVector.size()); // arguments objectRecordVector = rubyMeasureRecord.resources(); EXPECT_EQ(1u,objectRecordVector.size()); // script FileReferenceRecord scriptRecord = rubyMeasureRecord.fileReferenceRecord(); EXPECT_EQ("FileReferenceRecords",scriptRecord.databaseTableName()); Measure measure = rubyMeasureRecord.measure(); EXPECT_EQ(true,measure.isSelected()); ASSERT_TRUE(measure.optionalCast<RubyMeasure>()); RubyMeasure rubyMeasureCopy = measure.cast<RubyMeasure>(); EXPECT_FALSE(rubyMeasureCopy.usesBCLMeasure()); EXPECT_FALSE(rubyMeasureCopy.isUserScript()); EXPECT_EQ(6u,rubyMeasureCopy.arguments().size()); MeasureGroupRecord measureGroupRecordFromRuby = rubyMeasureRecord.measureGroupRecord().get(); EXPECT_EQ(measureGroupRecord.databaseTableName(),measureGroupRecordFromRuby.databaseTableName()); EXPECT_EQ(measureGroupRecord.id(),measureGroupRecordFromRuby.id()); } }
TEST_F(ProjectFixture, RubyMeasureRecord_BCLMeasure) { // Construct problem with RubyMeasure that points to BCLMeasure Problem problem("Problem",VariableVector(),runmanager::Workflow()); MeasureGroup dvar("Variable",MeasureVector()); problem.push(dvar); openstudio::path measuresPath = resourcesPath() / toPath("/utilities/BCL/Measures"); openstudio::path dir = measuresPath / toPath("SetWindowToWallRatioByFacade"); BCLMeasure measure = BCLMeasure::load(dir).get(); RubyMeasure rpert(measure); dvar.push(rpert); OSArgument arg = OSArgument::makeDoubleArgument("wwr"); arg.setValue(0.4); rpert.setArgument(arg); arg = OSArgument::makeIntegerArgument("typo_arg"); arg.setDefaultValue(1); rpert.setArgument(arg); // Serialize to database { ProjectDatabase database = getCleanDatabase("RubyMeasureRecord_BCLMeasure"); bool didStartTransaction = database.startTransaction(); EXPECT_TRUE(didStartTransaction); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problem,database); database.save(); if (didStartTransaction) { EXPECT_TRUE(database.commitTransaction()); } } // Re-open database, de-serialize, verify that RubyMeasure is intact. openstudio::path tempDir1 = measuresPath / toPath(toString(createUUID())); { ProjectDatabase database = getExistingDatabase("RubyMeasureRecord_BCLMeasure"); ASSERT_EQ(1u,ProblemRecord::getProblemRecords(database).size()); ASSERT_EQ(1u,MeasureGroupRecord::getMeasureGroupRecords(database).size()); EXPECT_EQ(1u,RubyMeasureRecord::getRubyMeasureRecords(database).size()); MeasureRecordVector dprs = MeasureGroupRecord::getMeasureGroupRecords(database)[0].measureRecords(false); ASSERT_EQ(1u,dprs.size()); ASSERT_TRUE(dprs[0].optionalCast<RubyMeasureRecord>()); RubyMeasureRecord rpr = dprs[0].cast<RubyMeasureRecord>(); RubyMeasure rp = rpr.rubyMeasure(); EXPECT_TRUE(rp.usesBCLMeasure()); EXPECT_TRUE(rp.measure()); EXPECT_EQ(dir,rp.measureDirectory()); EXPECT_EQ(measure.uuid(),rp.measureUUID()); EXPECT_EQ(measure.versionUUID(),rp.measureVersionUUID()); EXPECT_ANY_THROW(rp.perturbationScript()); EXPECT_EQ(2u,rp.arguments().size()); EXPECT_FALSE(rp.hasIncompleteArguments()); // Update measure and save BCLMeasure newVersion = measure.clone(tempDir1).get(); newVersion.setDescription("Window to wall ratio with sill height configurable."); newVersion.save(); EXPECT_NE(measure.versionUUID(),newVersion.versionUUID()); OSArgumentVector args; args.push_back(OSArgument::makeDoubleArgument("wwr")); args.push_back(OSArgument::makeDoubleArgument("sillHeight")); Problem problemCopy = ProblemRecord::getProblemRecords(database)[0].problem(); problemCopy.updateMeasure(newVersion,args,false); bool didStartTransaction = database.startTransaction(); EXPECT_TRUE(didStartTransaction); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problemCopy,database); database.save(); if (didStartTransaction) { EXPECT_TRUE(database.commitTransaction()); } } // Re-open database, check that old argument records are gone, check that de-serialized object ok openstudio::path tempDir2 = measuresPath / toPath(toString(createUUID())); { ProjectDatabase database = getExistingDatabase("RubyMeasureRecord_BCLMeasure"); ASSERT_EQ(1u,ProblemRecord::getProblemRecords(database).size()); EXPECT_EQ(1u,MeasureGroupRecord::getMeasureGroupRecords(database).size()); EXPECT_EQ(1u,RubyMeasureRecord::getRubyMeasureRecords(database).size()); EXPECT_EQ(1u,FileReferenceRecord::getFileReferenceRecords(database).size()); EXPECT_EQ(2u,OSArgumentRecord::getOSArgumentRecords(database).size()); Problem problemCopy = ProblemRecord::getProblemRecords(database)[0].problem(); InputVariableVector vars = problemCopy.variables(); ASSERT_FALSE(vars.empty()); ASSERT_TRUE(vars[0].optionalCast<MeasureGroup>()); MeasureVector dps = vars[0].cast<MeasureGroup>().measures(false); ASSERT_FALSE(dps.empty()); ASSERT_TRUE(dps[0].optionalCast<RubyMeasure>()); RubyMeasure rp = dps[0].cast<RubyMeasure>(); EXPECT_TRUE(rp.usesBCLMeasure()); EXPECT_TRUE(rp.measure()); EXPECT_EQ(tempDir1,rp.measureDirectory()); EXPECT_EQ(measure.uuid(),rp.measureUUID()); EXPECT_NE(measure.versionUUID(),rp.measureVersionUUID()); EXPECT_ANY_THROW(rp.perturbationScript()); ASSERT_EQ(2u,rp.arguments().size()); EXPECT_TRUE(rp.hasIncompleteArguments()); EXPECT_EQ("wwr",rp.arguments()[0].name()); ASSERT_EQ(1u,rp.incompleteArguments().size()); EXPECT_EQ("sillHeight",rp.incompleteArguments()[0].name()); // Set to different measure BCLMeasure measure2 = measure.clone(tempDir2).get(); measure2.changeUID(); measure2.incrementVersionId(); measure2.save(); measure2 = BCLMeasure::load(tempDir2).get(); EXPECT_NE(measure.uuid(),measure2.uuid()); EXPECT_NE(measure.versionUUID(),measure2.versionUUID()); rp.setMeasure(measure2); EXPECT_TRUE(rp.isDirty()); EXPECT_TRUE(problemCopy.isDirty()); bool didStartTransaction = database.startTransaction(); EXPECT_TRUE(didStartTransaction); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problemCopy,database); database.save(); if (didStartTransaction) { EXPECT_TRUE(database.commitTransaction()); } } // Re-open database, check that old measure and all argument records are gone { ProjectDatabase database = getExistingDatabase("RubyMeasureRecord_BCLMeasure"); ASSERT_EQ(1u,ProblemRecord::getProblemRecords(database).size()); EXPECT_EQ(1u,MeasureGroupRecord::getMeasureGroupRecords(database).size()); EXPECT_EQ(1u,RubyMeasureRecord::getRubyMeasureRecords(database).size()); EXPECT_EQ(1u,FileReferenceRecord::getFileReferenceRecords(database).size()); EXPECT_EQ(0u,OSArgumentRecord::getOSArgumentRecords(database).size()); Problem problemCopy = ProblemRecord::getProblemRecords(database)[0].problem(); InputVariableVector vars = problemCopy.variables(); ASSERT_FALSE(vars.empty()); ASSERT_TRUE(vars[0].optionalCast<MeasureGroup>()); MeasureVector dps = vars[0].cast<MeasureGroup>().measures(false); ASSERT_FALSE(dps.empty()); ASSERT_TRUE(dps[0].optionalCast<RubyMeasure>()); RubyMeasure rp = dps[0].cast<RubyMeasure>(); EXPECT_TRUE(rp.usesBCLMeasure()); EXPECT_TRUE(rp.measure()); EXPECT_EQ(tempDir2,rp.measureDirectory()); EXPECT_NE(measure.uuid(),rp.measureUUID()); EXPECT_NE(measure.versionUUID(),rp.measureVersionUUID()); EXPECT_ANY_THROW(rp.perturbationScript()); ASSERT_EQ(0u,rp.arguments().size()); EXPECT_FALSE(rp.hasIncompleteArguments()); } boost::filesystem::remove_all(tempDir1); boost::filesystem::remove_all(tempDir2); }
TEST_F(ProjectFixture, DataPointTagRecords) { // create Analysis with one DataPoint with one Tag ("test tag") analysis::Problem problem("problem",analysis::VariableVector(),runmanager::Workflow()); FileReference seed(toPath("in.osm")); analysis::Analysis analysis("analysis",problem,seed); analysis::DataPoint dataPoint = problem.createDataPoint(std::vector<QVariant>()).get(); dataPoint.addTag("test tag"); analysis.addDataPoint(dataPoint); // make sure tag records follow data points around. // trying to replicate issue where data point tag records get repointed to // file reference record with id 0. { // save analysis to a new database ProjectDatabase database = getCleanDatabase("DataPointTagRecords"); AnalysisRecord analysisRecord(analysis,database); database.save(); ASSERT_EQ(1u,analysisRecord.dataPointRecords().size()); DataPointRecord dataPointRecord = analysisRecord.dataPointRecords()[0]; ASSERT_EQ(1u,dataPointRecord.tagRecords().size()); TagRecord tagRecord = dataPointRecord.tagRecords()[0]; EXPECT_EQ("test tag",tagRecord.name()); analysis::DataPoint dataPoint = dataPointRecord.dataPoint(); ASSERT_EQ(1u,dataPoint.tags().size()); EXPECT_EQ("test tag",dataPoint.tags()[0].name()); analysis::Analysis analysis = analysisRecord.analysis(); ASSERT_EQ(1u,analysis.dataPoints().size()); dataPoint = analysis.dataPoints()[0]; ASSERT_EQ(1u,dataPoint.tags().size()); EXPECT_EQ("test tag",dataPoint.tags()[0].name()); } NameFinder<TagRecord> testRecordFinder("test tag"); NameFinder<TagRecord> anotherTestRecordFinder("another test"); NameFinder<Tag> testTagFinder("test tag"); NameFinder<Tag> anotherTestTagFinder("another test"); { ProjectDatabase database = getExistingDatabase("DataPointTagRecords"); ASSERT_EQ(1u,AnalysisRecord::getAnalysisRecords(database).size()); AnalysisRecord analysisRecord = AnalysisRecord::getAnalysisRecords(database)[0]; ASSERT_EQ(1u,analysisRecord.dataPointRecords().size()); DataPointRecord dataPointRecord = analysisRecord.dataPointRecords()[0]; ASSERT_EQ(1u,dataPointRecord.tagRecords().size()); TagRecord tagRecord = dataPointRecord.tagRecords()[0]; EXPECT_EQ("test tag",tagRecord.name()); analysis::DataPoint dataPoint = dataPointRecord.dataPoint(); ASSERT_EQ(1u,dataPoint.tags().size()); EXPECT_EQ("test tag",dataPoint.tags()[0].name()); analysis::Analysis analysis = analysisRecord.analysis(); ASSERT_EQ(1u,analysis.dataPoints().size()); dataPoint = analysis.dataPoints()[0]; ASSERT_EQ(1u,dataPoint.tags().size()); EXPECT_EQ("test tag",dataPoint.tags()[0].name()); // adding a second tag and resaving the analysis dataPoint.addTag("another test"); analysisRecord = AnalysisRecord(analysis,database); bool test = database.save(); EXPECT_TRUE(test); ASSERT_EQ(1u,analysisRecord.dataPointRecords().size()); dataPointRecord = analysisRecord.dataPointRecords()[0]; TagRecordVector tagRecords = dataPointRecord.tagRecords(); EXPECT_EQ(2u,tagRecords.size()); EXPECT_FALSE(std::find_if(tagRecords.begin(),tagRecords.end(),testRecordFinder) == tagRecords.end()); EXPECT_FALSE(std::find_if(tagRecords.begin(),tagRecords.end(),anotherTestRecordFinder) == tagRecords.end()); dataPoint = dataPointRecord.dataPoint(); TagVector tags = dataPoint.tags(); EXPECT_EQ(2u,tags.size()); EXPECT_FALSE(std::find_if(tags.begin(),tags.end(),testTagFinder) == tags.end()); EXPECT_FALSE(std::find_if(tags.begin(),tags.end(),anotherTestTagFinder) == tags.end()); analysis = analysisRecord.analysis(); ASSERT_EQ(1u,analysis.dataPoints().size()); dataPoint = analysis.dataPoints()[0]; tags = dataPoint.tags(); EXPECT_EQ(2u,tags.size()); EXPECT_FALSE(std::find_if(tags.begin(),tags.end(),testTagFinder) == tags.end()); EXPECT_FALSE(std::find_if(tags.begin(),tags.end(),anotherTestTagFinder) == tags.end()); tagRecords = TagRecord::getTagRecords(database); EXPECT_EQ(2u,tagRecords.size()); EXPECT_FALSE(std::find_if(tagRecords.begin(),tagRecords.end(),testRecordFinder) == tagRecords.end()); EXPECT_FALSE(std::find_if(tagRecords.begin(),tagRecords.end(),anotherTestRecordFinder) == tagRecords.end()); } { ProjectDatabase database = getExistingDatabase("DataPointTagRecords"); ASSERT_EQ(1u,AnalysisRecord::getAnalysisRecords(database).size()); AnalysisRecord analysisRecord = AnalysisRecord::getAnalysisRecords(database)[0]; ASSERT_EQ(1u,analysisRecord.dataPointRecords().size()); DataPointRecord dataPointRecord = analysisRecord.dataPointRecords()[0]; TagRecordVector tagRecords = dataPointRecord.tagRecords(); EXPECT_EQ(2u,tagRecords.size()); EXPECT_FALSE(std::find_if(tagRecords.begin(),tagRecords.end(),testRecordFinder) == tagRecords.end()); EXPECT_FALSE(std::find_if(tagRecords.begin(),tagRecords.end(),anotherTestRecordFinder) == tagRecords.end()); dataPoint = dataPointRecord.dataPoint(); TagVector tags = dataPoint.tags(); EXPECT_FALSE(std::find_if(tags.begin(),tags.end(),testTagFinder) == tags.end()); EXPECT_FALSE(std::find_if(tags.begin(),tags.end(),anotherTestTagFinder) == tags.end()); analysis = analysisRecord.analysis(); ASSERT_EQ(1u,analysis.dataPoints().size()); dataPoint = analysis.dataPoints()[0]; tags = dataPoint.tags(); EXPECT_FALSE(std::find_if(tags.begin(),tags.end(),testTagFinder) == tags.end()); EXPECT_FALSE(std::find_if(tags.begin(),tags.end(),anotherTestTagFinder) == tags.end()); } }
TEST_F(ProjectFixture,DataPoint_DataPointRecord_Synchronization) { // create analysis with one data point ProjectDatabase database = getCleanDatabase("DataPoint_DataPointRecord_Synchronization"); analysis::Analysis analysis( "Test Analysis", analysis::Problem("Test Problem",analysis::VariableVector(),runmanager::Workflow()), analysis::DesignOfExperiments(analysis::DesignOfExperimentsOptions( analysis::DesignOfExperimentsType::FullFactorial)), FileReference(toPath("in.osm"))); std::vector<QVariant> variableValues; analysis::DataPoint original = analysis.problem().createDataPoint(variableValues).get(); analysis.addDataPoint(original); // save analysis to database { bool didStartTransaction = database.startTransaction(); AnalysisRecord analysisRecord(analysis,database); DataPointRecordVector dataPointRecords = DataPointRecord::getDataPointRecords(database); ASSERT_EQ(1u,dataPointRecords.size()); DataPointRecord dataPointRecord = dataPointRecords[0]; EXPECT_FALSE(dataPointRecord.isComplete()); database.save(); if (didStartTransaction) { database.commitTransaction(); } } // reload analysis, change data point, save back to database // verify that change shows up in database OptionalAnalysis loadedAnalysis; { AnalysisRecordVector loadedAnalysisRecords = AnalysisRecord::getAnalysisRecords(database); ASSERT_EQ(1u,loadedAnalysisRecords.size()); loadedAnalysis = loadedAnalysisRecords[0].analysis(); analysis::DataPointVector loadedDataPoints = loadedAnalysis->dataPoints(); ASSERT_EQ(1u,loadedDataPoints.size()); loadedDataPoints[0].getImpl<analysis::detail::DataPoint_Impl>()->markComplete(); EXPECT_TRUE(loadedDataPoints[0].isComplete()); } ASSERT_TRUE(loadedAnalysis); { bool didStartTransaction = database.startTransaction(); database.unloadUnusedCleanRecords(); AnalysisRecord analysisRecord(*loadedAnalysis,database); database.save(); if (didStartTransaction) { database.commitTransaction(); } EXPECT_EQ(1u,AnalysisRecord::getAnalysisRecords(database).size()); DataPointRecordVector dataPointRecords = DataPointRecord::getDataPointRecords(database); ASSERT_EQ(1u,dataPointRecords.size()); DataPointRecord dataPointRecord = dataPointRecords[0]; EXPECT_TRUE(dataPointRecord.isComplete()); } }
// this is a monster test that is more for testing the database than attributes TEST_F(ProjectFixture, AttributeRecord_LoadSave) { int id; UUID handle; Attribute attribute("name", 1.0, std::string("m")); { ProjectDatabase database = getCleanDatabase("AttributeRecord_LoadSave"); EXPECT_EQ(static_cast<unsigned>(0), AttributeRecord::getAttributeRecords(database).size()); FileReferenceRecord model(FileReference(toPath("./in.osm")),database); AttributeRecord attributeRecord(attribute,model); id = attributeRecord.id(); handle = attributeRecord.handle(); EXPECT_EQ("name", attributeRecord.name()); EXPECT_EQ("name", attributeRecord.displayName()); EXPECT_EQ("", attributeRecord.description()); EXPECT_EQ(AttributeValueType::Double, attributeRecord.attributeValueType().value()); EXPECT_EQ(1.0, attributeRecord.attributeValueAsDouble()); ASSERT_TRUE(attributeRecord.attributeUnits()); EXPECT_EQ("m", attributeRecord.attributeUnits().get()); EXPECT_TRUE(database.includesRecord(attributeRecord)); EXPECT_TRUE(database.isNewRecord(attributeRecord)); EXPECT_FALSE(database.isDirtyRecord(attributeRecord)); EXPECT_FALSE(database.isCleanRecord(attributeRecord)); EXPECT_FALSE(database.isRemovedRecord(attributeRecord)); EXPECT_EQ(static_cast<unsigned>(2), attributeRecord.useCount()); } { // open existing database ProjectDatabase database = getExistingDatabase("AttributeRecord_LoadSave"); // new objects were removed EXPECT_EQ(static_cast<unsigned>(0), AnalysisRecord::getAnalysisRecords(database).size()); EXPECT_EQ(static_cast<unsigned>(0), FileReferenceRecord::getFileReferenceRecords(database).size()); EXPECT_EQ(static_cast<unsigned>(0), AttributeRecord::getAttributeRecords(database).size()); FileReferenceRecord model(FileReference(toPath("./in.osm")),database); // create AttributeRecord AttributeRecord attributeRecord(attribute, model); id = attributeRecord.id(); handle = attributeRecord.handle(); EXPECT_EQ("name", attributeRecord.name()); EXPECT_EQ("name", attributeRecord.displayName()); EXPECT_EQ("", attributeRecord.description()); EXPECT_EQ(AttributeValueType::Double, attributeRecord.attributeValueType().value()); EXPECT_EQ(1.0, attributeRecord.attributeValueAsDouble()); ASSERT_TRUE(attributeRecord.attributeUnits()); EXPECT_EQ("m", attributeRecord.attributeUnits().get()); EXPECT_TRUE(database.includesRecord(attributeRecord)); EXPECT_TRUE(database.isNewRecord(attributeRecord)); EXPECT_FALSE(database.isDirtyRecord(attributeRecord)); EXPECT_FALSE(database.isCleanRecord(attributeRecord)); EXPECT_FALSE(database.isRemovedRecord(attributeRecord)); EXPECT_EQ(static_cast<unsigned>(2), attributeRecord.useCount()); // save to database EXPECT_TRUE(database.save()); EXPECT_TRUE(database.includesRecord(attributeRecord)); EXPECT_FALSE(database.isNewRecord(attributeRecord)); EXPECT_FALSE(database.isDirtyRecord(attributeRecord)); EXPECT_TRUE(database.isCleanRecord(attributeRecord)); EXPECT_FALSE(database.isRemovedRecord(attributeRecord)); EXPECT_EQ(static_cast<unsigned>(2), attributeRecord.useCount()); } { // open existing database ProjectDatabase database = getExistingDatabase("AttributeRecord_LoadSave"); // saved objects were not removed ASSERT_EQ(static_cast<unsigned>(1), FileReferenceRecord::getFileReferenceRecords(database).size()); ASSERT_EQ(static_cast<unsigned>(1), AttributeRecord::getAttributeRecords(database).size()); std::vector<FileReferenceRecord> fileReferenceRecords = FileReferenceRecord::getFileReferenceRecords(database); FileReferenceRecord model = fileReferenceRecords.at(0); EXPECT_EQ(static_cast<unsigned>(1), model.attributeRecords().size()); AttributeRecord attributeRecord = model.attributeRecords()[0]; EXPECT_EQ(id, attributeRecord.id()); EXPECT_EQ(handle, attributeRecord.handle()); EXPECT_EQ("name", attributeRecord.name()); EXPECT_EQ("name", attributeRecord.displayName()); EXPECT_EQ("", attributeRecord.description()); EXPECT_EQ(AttributeValueType::Double, attributeRecord.attributeValueType().value()); EXPECT_EQ(1.0, attributeRecord.attributeValueAsDouble()); ASSERT_TRUE(attributeRecord.attributeUnits()); EXPECT_EQ("m", attributeRecord.attributeUnits().get()); EXPECT_TRUE(database.includesRecord(attributeRecord)); EXPECT_FALSE(database.isNewRecord(attributeRecord)); EXPECT_FALSE(database.isDirtyRecord(attributeRecord)); EXPECT_TRUE(database.isCleanRecord(attributeRecord)); EXPECT_FALSE(database.isRemovedRecord(attributeRecord)); EXPECT_EQ(static_cast<unsigned>(2), attributeRecord.useCount()); // remove record but don't save EXPECT_TRUE(database.removeRecord(attributeRecord)); EXPECT_EQ(static_cast<unsigned>(1), FileReferenceRecord::getFileReferenceRecords(database).size()); EXPECT_EQ(static_cast<unsigned>(0), AttributeRecord::getAttributeRecords(database).size()); EXPECT_TRUE(database.includesRecord(attributeRecord)); EXPECT_FALSE(database.isNewRecord(attributeRecord)); EXPECT_FALSE(database.isDirtyRecord(attributeRecord)); EXPECT_FALSE(database.isCleanRecord(attributeRecord)); EXPECT_TRUE(database.isRemovedRecord(attributeRecord)); EXPECT_EQ(static_cast<unsigned>(2), attributeRecord.useCount()); } { // open existing database ProjectDatabase database = getExistingDatabase("AttributeRecord_LoadSave"); // saved objects were not removed ASSERT_EQ(static_cast<unsigned>(1), FileReferenceRecord::getFileReferenceRecords(database).size()); ASSERT_EQ(static_cast<unsigned>(1), AttributeRecord::getAttributeRecords(database).size()); std::vector<FileReferenceRecord> fileReferenceRecords = FileReferenceRecord::getFileReferenceRecords(database); FileReferenceRecord model = fileReferenceRecords.at(0); EXPECT_EQ(static_cast<unsigned>(1), model.attributeRecords().size()); AttributeRecord attributeRecord = model.attributeRecords()[0]; EXPECT_EQ(id, attributeRecord.id()); EXPECT_EQ(handle, attributeRecord.handle()); EXPECT_EQ("name", attributeRecord.name()); EXPECT_EQ("name", attributeRecord.displayName()); EXPECT_EQ("", attributeRecord.description()); EXPECT_EQ(AttributeValueType::Double, attributeRecord.attributeValueType().value()); EXPECT_EQ(1.0, attributeRecord.attributeValueAsDouble()); ASSERT_TRUE(attributeRecord.attributeUnits()); EXPECT_EQ("m", attributeRecord.attributeUnits().get()); EXPECT_TRUE(database.includesRecord(attributeRecord)); EXPECT_FALSE(database.isNewRecord(attributeRecord)); EXPECT_FALSE(database.isDirtyRecord(attributeRecord)); EXPECT_TRUE(database.isCleanRecord(attributeRecord)); EXPECT_FALSE(database.isRemovedRecord(attributeRecord)); EXPECT_EQ(static_cast<unsigned>(2), attributeRecord.useCount()); // remove record then save save EXPECT_TRUE(database.removeRecord(attributeRecord)); EXPECT_EQ(static_cast<unsigned>(1), FileReferenceRecord::getFileReferenceRecords(database).size()); EXPECT_EQ(static_cast<unsigned>(0), AttributeRecord::getAttributeRecords(database).size()); EXPECT_TRUE(database.includesRecord(attributeRecord)); EXPECT_FALSE(database.isNewRecord(attributeRecord)); EXPECT_FALSE(database.isDirtyRecord(attributeRecord)); EXPECT_FALSE(database.isCleanRecord(attributeRecord)); EXPECT_TRUE(database.isRemovedRecord(attributeRecord)); EXPECT_EQ(static_cast<unsigned>(2), attributeRecord.useCount()); EXPECT_TRUE(database.save()); EXPECT_EQ(static_cast<unsigned>(1), FileReferenceRecord::getFileReferenceRecords(database).size()); EXPECT_EQ(static_cast<unsigned>(0), AttributeRecord::getAttributeRecords(database).size()); EXPECT_FALSE(database.includesRecord(attributeRecord)); EXPECT_FALSE(database.isNewRecord(attributeRecord)); EXPECT_FALSE(database.isDirtyRecord(attributeRecord)); EXPECT_FALSE(database.isCleanRecord(attributeRecord)); EXPECT_FALSE(database.isRemovedRecord(attributeRecord)); EXPECT_EQ(static_cast<unsigned>(1), attributeRecord.useCount()); } { // open existing database ProjectDatabase database = getExistingDatabase("AttributeRecord_LoadSave"); // objects were removed EXPECT_EQ(static_cast<unsigned>(1), FileReferenceRecord::getFileReferenceRecords(database).size()); EXPECT_EQ(static_cast<unsigned>(0), AttributeRecord::getAttributeRecords(database).size()); } }
TEST_F(ProjectFixture,AnalysisRecord_AddAndRemoveDataPoints) { // create an analysis with data points, no results Analysis analysis("My Analysis", Problem("My Problem",VariableVector(),runmanager::Workflow()), FileReferenceType::OSM); Problem problem = analysis.problem(); DiscretePerturbationVector perturbations; int pi = 1; std::stringstream ss; for (int i = 0; i < 3; ++i) { perturbations.push_back(NullPerturbation()); for (int j = 0; j < 4; ++j) { ss << "measure" << pi << ".rb"; perturbations.push_back(RubyPerturbation(toPath(ss.str()), FileReferenceType::OSM, FileReferenceType::OSM,true)); ss.str(""); ++pi; } ss << "Variable " << i+1; problem.push(DiscreteVariable(ss.str(),perturbations)); perturbations.clear(); ss.str(""); } EXPECT_EQ(3u,analysis.problem().variables().size()); ASSERT_FALSE(problem.variables().empty()); EXPECT_EQ(5u,problem.variables()[0].cast<DiscreteVariable>().numPerturbations(true)); problem.pushResponse( LinearFunction("Energy Use", VariableVector(1u,OutputAttributeVariable("Energy Use","Total.Energy.Use")))); EXPECT_EQ(1u,problem.responses().size()); std::vector<QVariant> values(3u,0); OptionalDataPoint dataPoint = problem.createDataPoint(values); ASSERT_TRUE(dataPoint); bool test = analysis.addDataPoint(*dataPoint); EXPECT_TRUE(test); values[1] = 3; dataPoint = problem.createDataPoint(values); ASSERT_TRUE(dataPoint); test = analysis.addDataPoint(*dataPoint); EXPECT_TRUE(test); values[0] = 1; values[1] = 2; values[2] = 4; dataPoint = problem.createDataPoint(values); ASSERT_TRUE(dataPoint); test = analysis.addDataPoint(*dataPoint); EXPECT_TRUE(test); EXPECT_TRUE(analysis.isDirty()); EXPECT_TRUE(problem.isDirty()); BOOST_FOREACH(const Variable& variable, problem.variables()) { EXPECT_TRUE(variable.isDirty()); ASSERT_TRUE(variable.optionalCast<DiscreteVariable>()); BOOST_FOREACH(const DiscretePerturbation& perturbation,variable.cast<DiscreteVariable>().perturbations(false)) { EXPECT_TRUE(perturbation.isDirty()); } } BOOST_FOREACH(const Function& response, problem.responses()) { EXPECT_TRUE(response.isDirty()); } BOOST_FOREACH(const DataPoint& dataPoint, analysis.dataPoints()) { EXPECT_TRUE(dataPoint.isDirty()); } // save to database, make sure everything is there, make sure clean signal filters down ProjectDatabase database = getCleanDatabase("AnalysisRecord_AddAndRemoveDataPoints"); { bool transactionStarted = database.startTransaction(); EXPECT_TRUE(transactionStarted); AnalysisRecord analysisRecord(analysis,database); database.save(); test = database.commitTransaction(); EXPECT_TRUE(test); EXPECT_EQ(analysis.uuid(),analysisRecord.handle()); EXPECT_EQ(analysis.versionUUID(),analysisRecord.uuidLast()); ASSERT_NO_THROW(analysisRecord.problemRecord()); ProblemRecord problemRecord = analysisRecord.problemRecord(); InputVariableRecordVector variableRecords = problemRecord.inputVariableRecords(); EXPECT_EQ(3u,variableRecords.size()); ASSERT_FALSE(variableRecords.empty()); ASSERT_TRUE(variableRecords[0].optionalCast<DiscreteVariableRecord>()); DiscretePerturbationRecordVector perturbationRecords = variableRecords[0].cast<DiscreteVariableRecord>().discretePerturbationRecords(false); EXPECT_EQ(5u,perturbationRecords.size()); ASSERT_TRUE(perturbationRecords.size() > 1); EXPECT_TRUE(perturbationRecords[0].optionalCast<NullPerturbationRecord>()); EXPECT_TRUE(perturbationRecords[1].optionalCast<RubyPerturbationRecord>()); EXPECT_EQ(3u,analysisRecord.dataPointRecords().size()); EXPECT_TRUE(analysisRecord.completeDataPointRecords().empty()); } analysis.clearDirtyFlag(); EXPECT_FALSE(analysis.isDirty()); EXPECT_FALSE(problem.isDirty()); BOOST_FOREACH(const Variable& variable, problem.variables()) { EXPECT_FALSE(variable.isDirty()); ASSERT_TRUE(variable.optionalCast<DiscreteVariable>()); BOOST_FOREACH(const DiscretePerturbation& perturbation,variable.cast<DiscreteVariable>().perturbations(false)) { EXPECT_FALSE(perturbation.isDirty()); } } BOOST_FOREACH(const Function& response, problem.responses()) { EXPECT_FALSE(response.isDirty()); } BOOST_FOREACH(const DataPoint& dataPoint, analysis.dataPoints()) { EXPECT_FALSE(dataPoint.isDirty()); } // make some more data points and make sure dirty flag bubbles up values[0] = 3; values[1] = 2; values[2] = 2; dataPoint = problem.createDataPoint(values); ASSERT_TRUE(dataPoint); test = analysis.addDataPoint(*dataPoint); EXPECT_TRUE(test); values[0] = 0; values[1] = 4; values[2] = 0; dataPoint = problem.createDataPoint(values); ASSERT_TRUE(dataPoint); test = analysis.addDataPoint(*dataPoint); EXPECT_TRUE(test); EXPECT_EQ(5u,analysis.dataPoints().size()); EXPECT_TRUE(analysis.isDirty()); EXPECT_FALSE(problem.isDirty()); BOOST_FOREACH(const Variable& variable, problem.variables()) { EXPECT_FALSE(variable.isDirty()); ASSERT_TRUE(variable.optionalCast<DiscreteVariable>()); BOOST_FOREACH(const DiscretePerturbation& perturbation,variable.cast<DiscreteVariable>().perturbations(false)) { EXPECT_FALSE(perturbation.isDirty()); } } BOOST_FOREACH(const Function& response, problem.responses()) { EXPECT_FALSE(response.isDirty()); } int i = 0; BOOST_FOREACH(const DataPoint& dataPoint, analysis.dataPoints()) { if (i < 3) { EXPECT_FALSE(dataPoint.isDirty()); } else { EXPECT_TRUE(dataPoint.isDirty()); } ++i; } // save to database, make sure changes made it in { bool transactionStarted = database.startTransaction(); EXPECT_TRUE(transactionStarted); database.unloadUnusedCleanRecords(); // ETH@20130201 - Having to call this is awkward. // Where is the best place? AnalysisRecord analysisRecord(analysis,database); database.save(); test = database.commitTransaction(); EXPECT_TRUE(test); EXPECT_EQ(analysis.uuid(),analysisRecord.handle()); EXPECT_EQ(analysis.versionUUID(),analysisRecord.uuidLast()); ASSERT_NO_THROW(analysisRecord.problemRecord()); ProblemRecord problemRecord = analysisRecord.problemRecord(); EXPECT_EQ(problemRecord.handle(),analysisRecord.problemRecord().handle()); EXPECT_EQ(problemRecord.uuidLast(),analysisRecord.problemRecord().uuidLast()); InputVariableRecordVector variableRecords = problemRecord.inputVariableRecords(); EXPECT_EQ(3u,variableRecords.size()); ASSERT_FALSE(variableRecords.empty()); ASSERT_TRUE(variableRecords[0].optionalCast<DiscreteVariableRecord>()); DiscretePerturbationRecordVector perturbationRecords = variableRecords[0].cast<DiscreteVariableRecord>().discretePerturbationRecords(false); EXPECT_EQ(5u,perturbationRecords.size()); ASSERT_TRUE(perturbationRecords.size() > 1); EXPECT_TRUE(perturbationRecords[0].optionalCast<NullPerturbationRecord>()); EXPECT_TRUE(perturbationRecords[1].optionalCast<RubyPerturbationRecord>()); EXPECT_EQ(5u,analysisRecord.dataPointRecords().size()); EXPECT_TRUE(analysisRecord.completeDataPointRecords().empty()); } analysis.clearDirtyFlag(); EXPECT_FALSE(analysis.isDirty()); EXPECT_FALSE(problem.isDirty()); BOOST_FOREACH(const Variable& variable, problem.variables()) { EXPECT_FALSE(variable.isDirty()); ASSERT_TRUE(variable.optionalCast<DiscreteVariable>()); BOOST_FOREACH(const DiscretePerturbation& perturbation,variable.cast<DiscreteVariable>().perturbations(false)) { EXPECT_FALSE(perturbation.isDirty()); } } BOOST_FOREACH(const Function& response, problem.responses()) { EXPECT_FALSE(response.isDirty()); } BOOST_FOREACH(const DataPoint& dataPoint, analysis.dataPoints()) { EXPECT_FALSE(dataPoint.isDirty()); } // remove a data point and save database. make sure point actually disappears DataPoint toRemove = analysis.dataPoints()[3]; test = analysis.removeDataPoint(toRemove); EXPECT_TRUE(test); EXPECT_TRUE(analysis.isDirty()); { bool transactionStarted = database.startTransaction(); EXPECT_TRUE(transactionStarted); database.unloadUnusedCleanRecords(); // ETH@20130201 - Having to call this is awkward. // Where is the best place? AnalysisRecord analysisRecord(analysis,database); database.save(); test = database.commitTransaction(); EXPECT_TRUE(test); EXPECT_EQ(analysis.uuid(),analysisRecord.handle()); EXPECT_EQ(analysis.versionUUID(),analysisRecord.uuidLast()); ASSERT_NO_THROW(analysisRecord.problemRecord()); ProblemRecord problemRecord = analysisRecord.problemRecord(); EXPECT_EQ(problemRecord.handle(),analysisRecord.problemRecord().handle()); EXPECT_EQ(problemRecord.uuidLast(),analysisRecord.problemRecord().uuidLast()); InputVariableRecordVector variableRecords = problemRecord.inputVariableRecords(); EXPECT_EQ(3u,variableRecords.size()); ASSERT_FALSE(variableRecords.empty()); ASSERT_TRUE(variableRecords[0].optionalCast<DiscreteVariableRecord>()); DiscretePerturbationRecordVector perturbationRecords = variableRecords[0].cast<DiscreteVariableRecord>().discretePerturbationRecords(false); EXPECT_EQ(5u,perturbationRecords.size()); ASSERT_TRUE(perturbationRecords.size() > 1); EXPECT_TRUE(perturbationRecords[0].optionalCast<NullPerturbationRecord>()); EXPECT_TRUE(perturbationRecords[1].optionalCast<RubyPerturbationRecord>()); EXPECT_EQ(4u,analysisRecord.dataPointRecords().size()); OptionalDataPointRecord searchResult = database.getObjectRecordByHandle<DataPointRecord>(toRemove.uuid()); EXPECT_FALSE(searchResult); EXPECT_EQ(4u,DataPointRecord::getDataPointRecords(database).size()); } EXPECT_EQ(4u,analysis.dataPoints().size()); test = analysis.clearDirtyFlag(); EXPECT_TRUE(test); }
TEST_F(ProjectFixture,AnalysisRecord_SetProblem) { // create an analysis with data points Problem problem1("Minimal Problem",VariableVector(),runmanager::Workflow()); Analysis analysis("Analysis", problem1, FileReferenceType::OSM); OptionalDataPoint dataPoint = problem1.createDataPoint(std::vector<QVariant>()); ASSERT_TRUE(dataPoint); bool test = analysis.addDataPoint(*dataPoint); EXPECT_TRUE(test); // save to database, make sure everything is there, make sure clean signal filters down ProjectDatabase database = getCleanDatabase("AnalysisRecord_SetProblem"); { bool transactionStarted = database.startTransaction(); EXPECT_TRUE(transactionStarted); AnalysisRecord analysisRecord(analysis,database); database.save(); test = database.commitTransaction(); EXPECT_TRUE(test); ASSERT_NO_THROW(analysisRecord.problemRecord()); ProblemRecord problemRecord = analysisRecord.problemRecord(); EXPECT_EQ(problem1.uuid(),problemRecord.handle()); EXPECT_EQ(problem1.versionUUID(),problemRecord.uuidLast()); EXPECT_EQ(1u,analysisRecord.dataPointRecords().size()); } analysis.clearDirtyFlag(); EXPECT_FALSE(analysis.isDirty()); EXPECT_FALSE(problem1.isDirty()); BOOST_FOREACH(const DataPoint& dataPoint, analysis.dataPoints()) { EXPECT_FALSE(dataPoint.isDirty()); } EXPECT_FALSE(analysis.dataPointsAreInvalid()); // set analysis to have new problem // make sure dirty flag bubbles up, data points marked invalid Problem problem2 = problem1.clone().cast<Problem>(); problem2.setName("Real Problem"); EXPECT_NE(problem1.uuid(),problem2.uuid()); analysis.setProblem(problem2); EXPECT_TRUE(analysis.isDirty()); EXPECT_FALSE(problem1.isDirty()); EXPECT_TRUE(problem2.isDirty()); EXPECT_TRUE(analysis.dataPointsAreInvalid()); RubyPerturbation userScript(toPath("measure.rb"), FileReferenceType::IDF, FileReferenceType::IDF, true); RubyContinuousVariable cvar("Script Argument Variable", ruleset::OSArgument::makeDoubleArgument("COP"), userScript); test = problem2.push(cvar); EXPECT_FALSE(test); // IDF not compatible with seed EXPECT_TRUE(problem2.variables().empty()); test = userScript.setPerturbationScript(toPath("measure.rb"), FileReferenceType::OSM, FileReferenceType::OSM, true); EXPECT_TRUE(test); test = problem2.push(cvar); EXPECT_TRUE(test); EXPECT_EQ(1u,analysis.problem().variables().size()); EXPECT_EQ(1u,analysis.dataPoints().size()); dataPoint = problem2.createDataPoint(std::vector<QVariant>(1u,3.5)); ASSERT_TRUE(dataPoint); test = analysis.addDataPoint(*dataPoint); EXPECT_FALSE(test); // save to database, make sure dataPointsAreInvalid flag was saved, old problem // should still be there, new problem there, and clean signal won't go through Analysis analysisCopy = analysis; // will replace with deserialized version momentarily { bool transactionStarted = database.startTransaction(); EXPECT_TRUE(transactionStarted); database.unloadUnusedCleanRecords(); // ETH@20130201 - Having to call this is awkward. // (As are the brackets) Where is the best place? AnalysisRecord analysisRecord(analysis,database); database.save(); test = database.commitTransaction(); EXPECT_TRUE(test); ASSERT_NO_THROW(analysisRecord.problemRecord()); ProblemRecord problemRecord = analysisRecord.problemRecord(); EXPECT_EQ(problem2.uuid(),problemRecord.handle()); EXPECT_EQ(problem2.versionUUID(),problemRecord.uuidLast()); EXPECT_EQ(2u,ProblemRecord::getProblemRecords(database).size()); // old one still around EXPECT_EQ(1u,analysisRecord.dataPointRecords().size()); test = analysis.clearDirtyFlag(); EXPECT_FALSE(test); Analysis analysisCopy = analysisRecord.analysis(); // should work b/c both problems around } EXPECT_EQ(analysis.uuid(),analysisCopy.uuid()); EXPECT_EQ(analysis.versionUUID(),analysisCopy.versionUUID()); EXPECT_TRUE(analysisCopy.isDirty()); EXPECT_TRUE(analysisCopy.dataPointsAreInvalid()); ASSERT_FALSE(analysisCopy.dataPoints().empty()); EXPECT_NE(analysisCopy.problem().uuid(),analysisCopy.dataPoints()[0].problem().uuid()); test = analysisCopy.clearDirtyFlag(); EXPECT_FALSE(test); // remove data points, save again, make sure dataPointsAreInvalid flag a-okay, new problem // still there and ok, old problem is going to hang around because didn't get rid of it when // analysisRecord still pointing to it, clean signal filters all the way down analysisCopy.removeAllDataPoints(); { bool transactionStarted = database.startTransaction(); EXPECT_TRUE(transactionStarted); database.unloadUnusedCleanRecords(); // ETH@20130201 - Having to call this is awkward. // Where is the best place? AnalysisRecord analysisRecord(analysisCopy,database); database.save(); test = database.commitTransaction(); EXPECT_TRUE(test); ASSERT_NO_THROW(analysisRecord.problemRecord()); ProblemRecord problemRecord = analysisRecord.problemRecord(); EXPECT_EQ(problem2.uuid(),problemRecord.handle()); EXPECT_EQ(problem2.versionUUID(),problemRecord.uuidLast()); // old problem record still hanging around. // TODO: Have use count as child, resource, and be able to (selectively) purge. EXPECT_EQ(2u,ProblemRecord::getProblemRecords(database).size()); EXPECT_TRUE(analysisRecord.dataPointRecords().empty()); analysis = analysisRecord.analysis(); } test = analysis.clearDirtyFlag(); EXPECT_TRUE(test); EXPECT_FALSE(analysis.isDirty()); EXPECT_FALSE(analysis.dataPointsAreInvalid()); EXPECT_FALSE(analysis.resultsAreInvalid()); EXPECT_TRUE(analysis.dataPoints().empty()); }