FunctionRecord_Impl::FunctionRecord_Impl(const analysis::Function& function, const FunctionRecordType& functionRecordType, ProblemRecord& problemRecord, const FunctionType& functionType, int functionVectorIndex) : ObjectRecord_Impl(problemRecord.projectDatabase(), function.uuid(), function.name(), function.displayName(), function.description(), function.versionUUID()), m_problemRecordId(problemRecord.id()), m_functionType(functionType), m_functionVectorIndex(functionVectorIndex), m_functionRecordType(functionRecordType) {}
WorkflowRecord_Impl::WorkflowRecord_Impl(const runmanager::Workflow& workflow, ProblemRecord& problemRecord, int workflowIndex) : ObjectRecord_Impl(problemRecord.projectDatabase(), workflow.uuid(), "", "", "", createUUID()), m_problemRecordId(problemRecord.id()), m_workflowIndex(workflowIndex) { openstudio::runmanager::RunManager runManager = problemRecord.projectDatabase().runManager(); try { m_runManagerWorkflowKey = runManager.persistWorkflow(workflow); } catch (const std::exception& e) { LOG(Error,"Could not persist workflow, because '" << e.what() << "'."); } }
WorkflowRecord::WorkflowRecord(const runmanager::Workflow& workflow, ProblemRecord& problemRecord, int workflowIndex) : ObjectRecord(std::shared_ptr<detail::WorkflowRecord_Impl>( new detail::WorkflowRecord_Impl(workflow, problemRecord, workflowIndex)), problemRecord.projectDatabase()) { OS_ASSERT(getImpl<detail::WorkflowRecord_Impl>()); }
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()); }
VariableRecord_Impl::VariableRecord_Impl(const analysis::Variable& variable, const VariableRecordType& variableRecordType, ProblemRecord& problemRecord, int workflowIndex) : ObjectRecord_Impl(problemRecord.projectDatabase(), variable.uuid(), variable.name(), variable.displayName(), variable.description(), variable.versionUUID()), m_variableVectorIndex(workflowIndex), m_variableRecordType(variableRecordType) {}
MeasureGroupRecord::MeasureGroupRecord(const analysis::MeasureGroup& measureGroup, ProblemRecord& problemRecord, int variableVectorIndex) : DiscreteVariableRecord(std::shared_ptr<detail::MeasureGroupRecord_Impl>( new detail::MeasureGroupRecord_Impl(measureGroup, problemRecord, variableVectorIndex)), problemRecord.projectDatabase(), measureGroup) { OS_ASSERT(getImpl<detail::MeasureGroupRecord_Impl>()); constructMeasureRecords(measureGroup); }
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()); }
InputVariableRecord_Impl::InputVariableRecord_Impl(const analysis::InputVariable& inputVariable, const InputVariableRecordType& inputVariableRecordType, ProblemRecord& problemRecord, int workflowIndex) : VariableRecord_Impl(inputVariable, VariableRecordType::InputVariableRecord, problemRecord, workflowIndex), m_problemRecordId(problemRecord.id()), m_inputVariableRecordType(inputVariableRecordType) { if (analysis::OptionalUncertaintyDescription oUDesc = inputVariable.uncertaintyDescription()) { m_uncertaintyDescriptionType = oUDesc->type(); } }
RubyContinuousVariableRecord::RubyContinuousVariableRecord( const analysis::RubyContinuousVariable& rubyContinuousVariable, ProblemRecord& problemRecord, int variableVectorIndex) : ContinuousVariableRecord(boost::shared_ptr<detail::RubyContinuousVariableRecord_Impl>( new detail::RubyContinuousVariableRecord_Impl(rubyContinuousVariable, problemRecord, variableVectorIndex)), problemRecord.projectDatabase(), rubyContinuousVariable) { OS_ASSERT(getImpl<detail::RubyContinuousVariableRecord_Impl>()); constructRelatedRecords(rubyContinuousVariable); }
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, ProblemRecord) { //Logger::instance().logLevel(Debug); openstudio::path rubyLibDirPath = openstudio::toPath(rubyLibDir()); openstudio::path perturbScript = rubyLibDirPath/openstudio::toPath("openstudio/runmanager/rubyscripts/PerturbObject.rb"); // Workflow Workflow workflow; // Variables VariableVector variables; // Measures MeasureVector perturbations1; MeasureVector perturbations2; // Discrete Variable Records InputVariableRecordVector measureGroupRecords; { // Problem Problem problem("0 Variables",variables,workflow); // Project Database ProjectDatabase database = getCleanDatabase("ProblemRecord"); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problem,database); InputVariableRecordVector measureGroupRecords = problemRecord.inputVariableRecords(); EXPECT_EQ(0u,measureGroupRecords.size()); } { perturbations1.push_back(NullMeasure()); variables.push_back(analysis::MeasureGroup("",perturbations1)); // Problem Problem problem("perturbations1",variables,workflow); // Project Database ProjectDatabase database = getCleanDatabase("ProblemRecord"); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problem,database); measureGroupRecords = problemRecord.inputVariableRecords(); EXPECT_EQ(1u,measureGroupRecords.size()); // Discrete Variable Record MeasureGroupRecord measureGroupRecord = measureGroupRecords.at(0).cast<MeasureGroupRecord>(); EXPECT_EQ(1u,measureGroupRecord.measureRecordIds(true).size()); EXPECT_EQ(1u,measureGroupRecord.measureRecords(true).size()); } { variables.push_back(MeasureGroup("Wall Construction",perturbations1)); // Problem Problem problem("perturbations1",variables,workflow); // Project Database ProjectDatabase database = getCleanDatabase("ProblemRecord"); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problem,database); measureGroupRecords = problemRecord.inputVariableRecords(); EXPECT_EQ(2u,measureGroupRecords.size()); // Discrete Variable Record MeasureGroupRecord variable1 = measureGroupRecords.at(0).cast<MeasureGroupRecord>(); EXPECT_EQ(static_cast<unsigned>(1), variable1.measureRecords(true).size()); EXPECT_EQ(static_cast<unsigned>(1), variable1.measureRecords(false).size()); EXPECT_EQ(static_cast<unsigned>(2), problemRecord.inputVariableRecords().size()); } { perturbations2.push_back(NullMeasure()); variables.push_back(MeasureGroup("Roof Construction",perturbations2)); // Problem Problem problem("perturbations2",variables,workflow); // Project Database ProjectDatabase database = getCleanDatabase("ProblemRecord"); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problem,database); measureGroupRecords = problemRecord.inputVariableRecords(); EXPECT_EQ(3u,measureGroupRecords.size()); // Discrete Variable Record MeasureGroupRecord variable1 = measureGroupRecords.at(0).cast<MeasureGroupRecord>(); MeasureGroupRecord variable2 = measureGroupRecords.at(0).cast<MeasureGroupRecord>(); MeasureGroupRecord variable3 = measureGroupRecords.at(0).cast<MeasureGroupRecord>(); EXPECT_EQ(static_cast<size_t>(1), variable1.measureRecords(true).size()); EXPECT_EQ(static_cast<size_t>(1), variable1.measureRecords(false).size()); EXPECT_EQ(static_cast<size_t>(3), problemRecord.inputVariableRecords().size()); UUID uuid1; UUID versionUUID1; NullMeasure nullMeasure1(uuid1,versionUUID1,"","","",true); NullMeasureRecord nullMeasureRecord1(nullMeasure1,variable1,0); EXPECT_EQ(static_cast<unsigned>(2), variable1.measureRecords(true).size()); EXPECT_EQ(static_cast<unsigned>(2), variable1.measureRecords(false).size()); EXPECT_EQ(static_cast<unsigned>(2), variable2.measureRecords(true).size()); EXPECT_EQ(static_cast<unsigned>(2), variable2.measureRecords(false).size()); UUID uuid2; UUID versionUUID2; NullMeasure nullMeasure2(uuid2,versionUUID2,"","","",true); NullMeasureRecord nullMeasureRecord2(nullMeasure2,variable1,0); EXPECT_EQ(static_cast<unsigned>(2), variable1.measureRecords(true).size()); EXPECT_EQ(static_cast<unsigned>(2), variable1.measureRecords(false).size()); EXPECT_EQ(static_cast<unsigned>(2), variable2.measureRecords(true).size()); EXPECT_EQ(static_cast<unsigned>(2), variable2.measureRecords(false).size()); MeasureVector perturbations; MeasureGroup measureGroup("Wall Construction",perturbations); MeasureGroupRecord measureGroupRecord(measureGroup, problemRecord,0); openstudio::path rubyPath = resourcesPath() / openstudio::toPath("project/rubyscripts/*.rb"); openstudio::path perturbScript = rubyPath/openstudio::toPath("openstudio/runmanager/rubyscripts/PerturbObject.rb"); RubyMeasure rubyMeasure(perturbScript,FileReferenceType::OSM,FileReferenceType::OSM); RubyMeasureRecord rubyMeasureRecord1(rubyMeasure,measureGroupRecord,0); EXPECT_EQ(static_cast<unsigned>(1), measureGroupRecord.numMeasures(true)); EXPECT_EQ(static_cast<unsigned>(1), measureGroupRecord.measureRecordIds(true).size()); EXPECT_EQ(static_cast<unsigned>(1), measureGroupRecord.measureRecords(true).size()); RubyMeasureRecord rubyMeasureRecord(rubyMeasure,measureGroupRecord,0); EXPECT_EQ(static_cast<unsigned>(1), measureGroupRecord.numMeasures(true)); EXPECT_EQ(static_cast<unsigned>(1), measureGroupRecord.measureRecordIds(true).size()); EXPECT_EQ(rubyMeasureRecord.id(), measureGroupRecord.measureRecordIds(true)[0]); EXPECT_EQ(static_cast<unsigned>(1), measureGroupRecord.measureRecords(true).size()); EXPECT_EQ(rubyMeasureRecord.handle(), measureGroupRecord.measureRecords(true)[0].handle()); } }
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()); }