-
Notifications
You must be signed in to change notification settings - Fork 460
Fix #11054 - Crash with schedule with missing day types #11085
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
``` [ RUN ] EnergyPlusFixture.ScheduleCompact_MissingDayTypes Process 1427200 stopped * thread #1, name = 'energyplus_test', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0x70) frame #0: 0x0000555556a3e650 energyplus_tests`std::__cxx1998::vector<double, std::allocator<double>>::size(this=0x0000000000000068 size=0) const at stl_vector.h:993:40 990 _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR 991 size_type 992 size() const _GLIBCXX_NOEXCEPT -> 993 { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); } 994 995 /** Returns the size() of the largest possible %vector. */ 996 _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR (lldb) bt * thread #1, name = 'energyplus_test', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0x70) * frame #0: 0x0000555556a3e650 energyplus_tests`std::__cxx1998::vector<double, std::allocator<double>>::size(this=0x0000000000000068 size=0) const at stl_vector.h:993:40 frame #1: 0x0000555557784d86 energyplus_tests`std::__debug::vector<double, std::allocator<double>>::operator[](this=0x0000000000000050 size=0, __n=27) const at vector:450:2 frame #2: 0x0000555559615269 energyplus_tests`EnergyPlus::Sched::ScheduleDetailed::getHrTsVal(this=0x000055555ed4b0c0, state=0x000055555e7b8190, hr=7, ts=4) const at ScheduleManager.cc:2520:82 ```
| TEST_F(EnergyPlusFixture, ScheduleCompact_MissingDayTypes) | ||
| { | ||
| // Test for #11054 | ||
| std::string const idf_objects = delimited_string({ | ||
| "ScheduleTypeLimits,", | ||
| " Any Number; !- Name", | ||
|
|
||
| "Schedule:Compact,", | ||
| " WindowVentSched, !- Name", | ||
| " Any Number, !- Schedule Type Limits Name", | ||
| " Through: 12/31, !- Field 1", | ||
| " For: Monday Tuesday Wednesday Thursday Friday Saturday, !- Field 2", | ||
| " Until: 24:00,1; !- Field 3", | ||
| }); | ||
|
|
||
| ASSERT_TRUE(process_idf(idf_objects)); | ||
|
|
||
| auto &s_glob = state->dataGlobal; | ||
|
|
||
| s_glob->TimeStepsInHour = 4; // must initialize this to get schedules initialized | ||
| s_glob->MinutesInTimeStep = 15; // must initialize this to get schedules initialized | ||
| s_glob->TimeStepZone = 0.25; | ||
| s_glob->TimeStepZoneSec = s_glob->TimeStepZone * Constant::rSecsInHour; | ||
| state->dataEnvrn->CurrentYearIsLeapYear = false; | ||
|
|
||
| state->init_state(*state); // read schedules (this calls ProcessScheduleInput via ScheduleManagerData::init_state) | ||
|
|
||
| const std::string expected_error = delimited_string({ | ||
| " ** Warning ** ProcessScheduleInput: Schedule:Compact = WINDOWVENTSCHED", | ||
| " ** ~~~ ** has missing day types in Through=12/31", | ||
| " ** ~~~ ** Last \"For\" field=FOR: MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY", | ||
| R"( ** ~~~ ** Missing day types= "Sunday", "Holiday", "SummerDesignDay", "WinterDesignDay", "CustomDay1", "CustomDay2")", | ||
| " ** ~~~ ** Missing day types will have 0.0 as Schedule Values", | ||
| }); | ||
|
|
||
| compare_err_stream(expected_error); | ||
|
|
||
| auto const *sch = dynamic_cast<Sched::ScheduleDetailed const *>(Sched::GetSchedule(*state, "WINDOWVENTSCHED")); | ||
| EXPECT_NE(sch, nullptr); | ||
| EXPECT_EQ(367, sch->weekScheds.size()); | ||
| EXPECT_EQ(sch->weekScheds.front(), nullptr); | ||
| const auto &weekSched = sch->weekScheds[1]; | ||
| EXPECT_EQ("WINDOWVENTSCHED_wk_1", weekSched->Name); | ||
| for (size_t i = 2; i < 367; ++i) { | ||
| EXPECT_EQ(weekSched, sch->weekScheds[i]); | ||
| } | ||
| EXPECT_EQ((int)Sched::DayType::Num, weekSched->dayScheds.size()); | ||
|
|
||
| EXPECT_EQ(nullptr, weekSched->dayScheds[(int)Sched::DayType::Unused]); | ||
| EXPECT_EQ(nullptr, weekSched->dayScheds[(int)Sched::DayType::Sunday]); | ||
|
|
||
| ASSERT_NE(nullptr, weekSched->dayScheds[(int)Sched::DayType::Monday]); | ||
| ASSERT_NE(nullptr, weekSched->dayScheds[(int)Sched::DayType::Tuesday]); | ||
| ASSERT_NE(nullptr, weekSched->dayScheds[(int)Sched::DayType::Wednesday]); | ||
| ASSERT_NE(nullptr, weekSched->dayScheds[(int)Sched::DayType::Thursday]); | ||
| ASSERT_NE(nullptr, weekSched->dayScheds[(int)Sched::DayType::Friday]); | ||
| ASSERT_NE(nullptr, weekSched->dayScheds[(int)Sched::DayType::Saturday]); | ||
| auto const &daySched = weekSched->dayScheds[(int)Sched::DayType::Monday]; | ||
| for (int i = (int)Sched::DayType::Monday; i <= (int)Sched::DayType::Saturday; ++i) { | ||
| EXPECT_EQ(daySched, weekSched->dayScheds[i]); | ||
| } | ||
|
|
||
| EXPECT_EQ(nullptr, weekSched->dayScheds[(int)Sched::DayType::Holiday]); | ||
| EXPECT_EQ(nullptr, weekSched->dayScheds[(int)Sched::DayType::SummerDesignDay]); | ||
| EXPECT_EQ(nullptr, weekSched->dayScheds[(int)Sched::DayType::WinterDesignDay]); | ||
| EXPECT_EQ(nullptr, weekSched->dayScheds[(int)Sched::DayType::CustomDay1]); | ||
| EXPECT_EQ(nullptr, weekSched->dayScheds[(int)Sched::DayType::CustomDay2]); | ||
|
|
||
| state->dataEnvrn->Month = 1; | ||
| state->dataEnvrn->DayOfMonth = 1; | ||
| state->dataEnvrn->DayOfYear_Schedule = General::OrdinalDay(state->dataEnvrn->Month, state->dataEnvrn->DayOfMonth, 1); | ||
| s_glob->HourOfDay = 1; | ||
| s_glob->TimeStep = 1; | ||
| state->dataEnvrn->DSTIndicator = 0; | ||
| state->dataEnvrn->HolidayIndex = 0; | ||
|
|
||
| // Monday is defined, so we should get 1.0 | ||
| state->dataEnvrn->DayOfWeek = 2; | ||
| EXPECT_NEAR(1.0, sch->getHrTsVal(*state, 7, 4), 0.000001); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New test, until here, everything is good including on develop.
| // Now test a day that is not defined, like Sunday | ||
| // We shouldn't segfault, and it should default to returning 0.0 | ||
| state->dataEnvrn->DayOfWeek = 1; | ||
| ASSERT_NO_THROW(sch->getHrTsVal(*state, 7, 4)); | ||
| EXPECT_NEAR(0.0, sch->getHrTsVal(*state, 7, 4), 0.000001); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This segfaults on develop. With the fix, it correctly returns 0.0 as we explicitly say in the warning
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great!
| "Schedule:Compact,", | ||
| " WindowVentSched, !- Name", | ||
| " Any Number, !- Schedule Type Limits Name", | ||
| " Through: 12/31, !- Field 1", | ||
| " For: Monday Tuesday Wednesday Thursday Friday Saturday, !- Field 2", | ||
| " Until: 24:00,1; !- Field 3", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a Sunday, I get 0 because it's missing, not 1.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But today is Tuesday.
| if (daySched == nullptr) { | ||
| // We already warned in ProcessScheduleInput that there were missing days: Missing day types will have 0.0 as Schedule Values | ||
| return 0.0; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simple fix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine. In a turn of events, my personal preference is if (!daySched) here, but I'm 100% fine with comparing to nullptr.
|
Myoldmopar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great little fix here with tests, thanks @jmarrec
| if (daySched == nullptr) { | ||
| // We already warned in ProcessScheduleInput that there were missing days: Missing day types will have 0.0 as Schedule Values | ||
| return 0.0; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine. In a turn of events, my personal preference is if (!daySched) here, but I'm 100% fine with comparing to nullptr.
| "Schedule:Compact,", | ||
| " WindowVentSched, !- Name", | ||
| " Any Number, !- Schedule Type Limits Name", | ||
| " Through: 12/31, !- Field 1", | ||
| " For: Monday Tuesday Wednesday Thursday Friday Saturday, !- Field 2", | ||
| " Until: 24:00,1; !- Field 3", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But today is Tuesday.
| // Now test a day that is not defined, like Sunday | ||
| // We shouldn't segfault, and it should default to returning 0.0 | ||
| state->dataEnvrn->DayOfWeek = 1; | ||
| ASSERT_NO_THROW(sch->getHrTsVal(*state, 7, 4)); | ||
| EXPECT_NEAR(0.0, sch->getHrTsVal(*state, 7, 4), 0.000001); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great!
|
And it's passing happily locally. Thanks @jmarrec, merging. |
Pull request overview
Description of the purpose of this PR
Confirmed that the defect file segfaults before, and works with this PR, and the eplusout.err has the expected warning
Pull Request Author
Reviewer