Skip to content

Commit 56a7b71

Browse files
authored
Fix data race in pipeline reload (#410)
Root cause was not blocking new requests from creation. There was no transient state that would block requests so when pipeline reload happened it checked once if there is no ongoing request but after that new request could still be created. JIRA:CVS-45093
1 parent 4a6c5c6 commit 56a7b71

File tree

5 files changed

+131
-24
lines changed

5 files changed

+131
-24
lines changed

src/pipelinedefinition.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ Status PipelineDefinition::validate(ModelManager& manager) {
5656
}
5757

5858
Status PipelineDefinition::reload(ModelManager& manager, const std::vector<NodeInfo>&& nodeInfos, const pipeline_connections_t&& connections) {
59+
// block creating new unloadGuards
60+
this->status.handle(ReloadEvent());
5961
resetSubscriptions(manager);
6062
while (requestsHandlesCounter > 0) {
6163
std::this_thread::sleep_for(std::chrono::microseconds(1));
@@ -643,7 +645,6 @@ Status PipelineDefinition::getInputsInfo(tensor_map_t& inputsInfo, const ModelMa
643645
return nodeInfo.nodeName == name;
644646
};
645647
};
646-
647648
for (const auto& [dependantNodeName, allMappings] : connections) {
648649
const auto& dependantNodeInfo = std::find_if(std::begin(nodeInfos), std::end(nodeInfos), byName(dependantNodeName));
649650
for (const auto& [dependencyNodeName, specificDependencyMapping] : allMappings) {
@@ -685,7 +686,6 @@ Status PipelineDefinition::getInputsInfo(tensor_map_t& inputsInfo, const ModelMa
685686
}
686687
}
687688
}
688-
689689
return StatusCode::OK;
690690
}
691691

@@ -698,7 +698,6 @@ Status PipelineDefinition::getOutputsInfo(tensor_map_t& outputsInfo, const Model
698698
return nodeInfo.nodeName == name;
699699
};
700700
};
701-
702701
for (const auto& [dependantNodeName, allMappings] : connections) {
703702
const auto& dependantNodeInfo = std::find_if(std::begin(nodeInfos), std::end(nodeInfos), byName(dependantNodeName));
704703
if (dependantNodeInfo->kind != NodeKind::EXIT) {
@@ -742,7 +741,6 @@ Status PipelineDefinition::getOutputsInfo(tensor_map_t& outputsInfo, const Model
742741
}
743742
}
744743
}
745-
746744
return StatusCode::OK;
747745
}
748746

src/pipelinedefinitionstatus.hpp

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ namespace ovms {
3737

3838
enum class PipelineDefinitionStateCode {
3939
BEGIN,
40+
RELOADING,
4041
LOADING_PRECONDITION_FAILED,
4142
LOADING_PRECONDITION_FAILED_REQUIRED_REVALIDATION,
4243
AVAILABLE_REQUIRED_REVALIDATION,
@@ -47,6 +48,7 @@ enum class PipelineDefinitionStateCode {
4748
inline const std::string& pipelineDefinitionStateCodeToString(PipelineDefinitionStateCode code) {
4849
static const std::unordered_map<PipelineDefinitionStateCode, std::string> names{
4950
{PipelineDefinitionStateCode::BEGIN, "BEGIN"},
51+
{PipelineDefinitionStateCode::RELOADING, "RELOADING"},
5052
{PipelineDefinitionStateCode::LOADING_PRECONDITION_FAILED, "LOADING_PRECONDITION_FAILED"},
5153
{PipelineDefinitionStateCode::LOADING_PRECONDITION_FAILED_REQUIRED_REVALIDATION, "LOADING_PRECONDITION_FAILED_REQUIRED_REVALIDATION"},
5254
{PipelineDefinitionStateCode::AVAILABLE_REQUIRED_REVALIDATION, "AVAILABLE_REQUIRED_REVALIDATION"},
@@ -104,6 +106,10 @@ struct AvailableState;
104106
* models changed
105107
*/
106108
struct AvailableRequiredRevalidation;
109+
/**
110+
* State in which pipeline is reloading
111+
*/
112+
struct ReloadState;
107113
/**
108114
* State in which pipeline is defined in config and failed validation.
109115
*/
@@ -132,6 +138,7 @@ struct RetiredState;
132138
const std::string details; \
133139
};
134140

141+
EVENT_STRUCT_WITH_NAME(ReloadEvent);
135142
EVENT_STRUCT_WITH_NAME(ValidationFailedEvent);
136143
EVENT_STRUCT_WITH_NAME(ValidationPassedEvent);
137144
EVENT_STRUCT_WITH_NAME(UsedModelChangedEvent);
@@ -162,6 +169,38 @@ struct BeginState {
162169
void print() const {
163170
SPDLOG_LOGGER_ERROR(modelmanager_logger, pipelineDefinitionStateCodeToString(getStateCode()));
164171
}
172+
StateChanger<ReloadState> handle(const ReloadEvent& e) const {
173+
throw std::logic_error(INVALID_TRANSITION_MESSAGE);
174+
return {};
175+
}
176+
StateChanger<AvailableState> handle(const ValidationPassedEvent& e) const {
177+
return {};
178+
}
179+
StateChanger<LoadingPreconditionFailedState> handle(const ValidationFailedEvent& e) const {
180+
return {};
181+
}
182+
StateKeeper handle(const UsedModelChangedEvent& e) const {
183+
throw std::logic_error(INVALID_TRANSITION_MESSAGE);
184+
return {};
185+
}
186+
StateKeeper handle(const RetireEvent& e) const {
187+
throw std::logic_error(INVALID_TRANSITION_MESSAGE);
188+
return {};
189+
}
190+
};
191+
192+
struct ReloadState {
193+
static const PipelineDefinitionStateCode code = PipelineDefinitionStateCode::RELOADING;
194+
PipelineDefinitionStateCode getStateCode() const {
195+
return code;
196+
}
197+
void print() const {
198+
SPDLOG_LOGGER_ERROR(modelmanager_logger, pipelineDefinitionStateCodeToString(getStateCode()));
199+
}
200+
StateKeeper handle(const ReloadEvent& e) const {
201+
throw std::logic_error(INVALID_TRANSITION_MESSAGE);
202+
return {};
203+
}
165204
StateChanger<AvailableState> handle(const ValidationPassedEvent& e) const {
166205
return {};
167206
}
@@ -186,10 +225,15 @@ struct AvailableState {
186225
void print() const {
187226
SPDLOG_LOGGER_ERROR(modelmanager_logger, pipelineDefinitionStateCodeToString(getStateCode()));
188227
}
228+
StateChanger<ReloadState> handle(const ReloadEvent& e) const {
229+
return {};
230+
}
189231
StateKeeper handle(const ValidationPassedEvent& e) const {
232+
throw std::logic_error(INVALID_TRANSITION_MESSAGE);
190233
return {};
191234
}
192-
StateChanger<LoadingPreconditionFailedState> handle(const ValidationFailedEvent& e) const {
235+
StateKeeper handle(const ValidationFailedEvent& e) const {
236+
throw std::logic_error(INVALID_TRANSITION_MESSAGE);
193237
return {};
194238
}
195239
StateChanger<AvailableRequiredRevalidation> handle(const UsedModelChangedEvent& e) const {
@@ -208,6 +252,9 @@ struct AvailableRequiredRevalidation {
208252
void print() const {
209253
SPDLOG_LOGGER_ERROR(modelmanager_logger, pipelineDefinitionStateCodeToString(getStateCode()));
210254
}
255+
StateChanger<ReloadState> handle(const ReloadEvent& e) const {
256+
return {};
257+
}
211258
StateChanger<AvailableState> handle(const ValidationPassedEvent& e) const {
212259
return {};
213260
}
@@ -230,10 +277,15 @@ struct LoadingPreconditionFailedState {
230277
void print() const {
231278
SPDLOG_LOGGER_ERROR(modelmanager_logger, pipelineDefinitionStateCodeToString(getStateCode()));
232279
}
233-
StateChanger<AvailableState> handle(const ValidationPassedEvent& e) const {
280+
StateChanger<ReloadState> handle(const ReloadEvent& e) const {
281+
return {};
282+
}
283+
StateKeeper handle(const ValidationPassedEvent& e) const {
284+
throw std::logic_error(INVALID_TRANSITION_MESSAGE);
234285
return {};
235286
}
236287
StateKeeper handle(const ValidationFailedEvent& e) const {
288+
throw std::logic_error(INVALID_TRANSITION_MESSAGE);
237289
return {};
238290
}
239291
StateChanger<LoadingFailedLastValidationRequiredRevalidation> handle(const UsedModelChangedEvent& e) const {
@@ -252,6 +304,9 @@ struct LoadingFailedLastValidationRequiredRevalidation {
252304
void print() const {
253305
SPDLOG_LOGGER_ERROR(modelmanager_logger, pipelineDefinitionStateCodeToString(getStateCode()));
254306
}
307+
StateChanger<ReloadState> handle(const ReloadEvent& e) const {
308+
return {};
309+
}
255310
StateChanger<AvailableState> handle(const ValidationPassedEvent& e) const {
256311
return {};
257312
}
@@ -274,10 +329,15 @@ struct RetiredState {
274329
void print() const {
275330
SPDLOG_LOGGER_ERROR(modelmanager_logger, pipelineDefinitionStateCodeToString(getStateCode()));
276331
}
332+
StateChanger<ReloadState> handle(const ReloadEvent& e) const {
333+
return {};
334+
}
277335
StateChanger<AvailableState> handle(const ValidationPassedEvent& e) const {
336+
throw std::logic_error(INVALID_TRANSITION_MESSAGE);
278337
return {};
279338
}
280339
StateChanger<LoadingPreconditionFailedState> handle(const ValidationFailedEvent& e) const {
340+
throw std::logic_error(INVALID_TRANSITION_MESSAGE);
281341
return {};
282342
}
283343
StateKeeper handle(const UsedModelChangedEvent& e) const {
@@ -290,7 +350,7 @@ struct RetiredState {
290350
}
291351
};
292352

293-
class PipelineDefinitionStatus : public MachineState<BeginState, AvailableState, AvailableRequiredRevalidation, LoadingPreconditionFailedState, LoadingFailedLastValidationRequiredRevalidation, RetiredState> {
353+
class PipelineDefinitionStatus : public MachineState<BeginState, ReloadState, AvailableState, AvailableRequiredRevalidation, LoadingPreconditionFailedState, LoadingFailedLastValidationRequiredRevalidation, RetiredState> {
294354
public:
295355
PipelineDefinitionStatus(const std::string& name) :
296356
MachineState(name) {}
@@ -314,6 +374,7 @@ class PipelineDefinitionStatus : public MachineState<BeginState, AvailableState,
314374
std::tuple<ModelVersionState, ModelVersionStatusErrorCode> convertToModelStatus() const {
315375
switch (getStateCode()) {
316376
case PipelineDefinitionStateCode::BEGIN:
377+
case PipelineDefinitionStateCode::RELOADING:
317378
case PipelineDefinitionStateCode::LOADING_PRECONDITION_FAILED_REQUIRED_REVALIDATION:
318379
return {
319380
ModelVersionState::LOADING,

src/test/ensemble_tests.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,6 +2006,7 @@ TEST_F(EnsembleFlowTest, ReloadPipelineDefinitionWithNewModelNameShouldPass) {
20062006
status = pd.reload(managerWithDummyModel, std::move(infoNew), std::move(connections));
20072007
EXPECT_TRUE(status.ok()) << status.string();
20082008
}
2009+
const std::string notifierDetails{"UnusedNotifierDetails"};
20092010

20102011
TEST_F(EnsembleFlowTest, ReloadPipelineDefinitionWithNewNonExistingModelNameShouldFail) {
20112012
ConstructorEnabledModelManager managerWithDummyModel;
@@ -2076,6 +2077,7 @@ TEST_F(EnsembleFlowTest, RevalidatePipelineDefinitionWhen1ModelVersionBecomesAva
20762077
connections[EXIT_NODE_NAME] = {
20772078
{"dummy_node", {{DUMMY_MODEL_OUTPUT_NAME, customPipelineOutputName}}}};
20782079
PipelineDefinition pd(pipelineName, info, connections);
2080+
pd.makeSubscriptions(managerWithDummyModel);
20792081
auto status = pd.validate(managerWithDummyModel);
20802082
ASSERT_TRUE(status.ok()) << status.string();
20812083
managerWithDummyModel.findModelByName("dummy")->retireAllVersions();
@@ -2167,6 +2169,7 @@ TEST_F(EnsembleFlowTest, WaitForLoadingPipelineDefinitionFromBeginStatus) {
21672169
connections[EXIT_NODE_NAME] = {
21682170
{"dummy_node", {{DUMMY_MODEL_OUTPUT_NAME, customPipelineOutputName}}}};
21692171
MockedPipelineDefinitionWithHandlingStatus pd(pipelineName, info, connections);
2172+
pd.makeSubscriptions(managerWithDummyModel);
21702173
std::unique_ptr<Pipeline> pipelineBeforeRetire;
21712174
std::thread t([&managerWithDummyModel, &pd]() {
21722175
std::this_thread::sleep_for(std::chrono::microseconds(PipelineDefinition::WAIT_FOR_LOADED_DEFAULT_TIMEOUT_MICROSECONDS / 4));
@@ -2176,10 +2179,12 @@ TEST_F(EnsembleFlowTest, WaitForLoadingPipelineDefinitionFromBeginStatus) {
21762179
});
21772180
auto status = pd.create(pipelineBeforeRetire, &request, &response, managerWithDummyModel);
21782181
ASSERT_TRUE(status.ok());
2182+
pd.getControlableStatus().handle(UsedModelChangedEvent(notifierDetails));
21792183
pd.getControlableStatus().handle(ValidationFailedEvent());
21802184
status = pd.create(pipelineBeforeRetire, &request, &response, managerWithDummyModel);
21812185
ASSERT_EQ(status, ovms::StatusCode::PIPELINE_DEFINITION_NOT_LOADED_YET);
21822186
pd.getControlableStatus().handle(UsedModelChangedEvent());
2187+
pd.getControlableStatus().handle(UsedModelChangedEvent(notifierDetails));
21832188
status = pd.create(pipelineBeforeRetire, &request, &response, managerWithDummyModel);
21842189
ASSERT_EQ(status, ovms::StatusCode::PIPELINE_DEFINITION_NOT_LOADED_YET);
21852190
std::thread t2([&managerWithDummyModel, &pd]() {

src/test/get_pipeline_metadata_response_test.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ TEST_F(GetPipelineMetadataResponse, PipelineNotLoadedAnymore) {
252252
}
253253

254254
TEST_F(GetPipelineMetadataResponse, PipelineNotLoadedYet) {
255+
this->pipelineDefinition.getPipelineDefinitionStatus().handle(UsedModelChangedEvent());
255256
this->pipelineDefinition.getPipelineDefinitionStatus().handle(ValidationFailedEvent());
256257
auto status = ovms::GetModelMetadataImpl::buildResponse(pipelineDefinition, &response, manager);
257258
ASSERT_EQ(status, ovms::StatusCode::PIPELINE_DEFINITION_NOT_LOADED_YET) << status.string();

src/test/pipelinedefinitionstatus_test.cpp

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -123,35 +123,28 @@ TEST(PipelineDefinitionStatus, ValidationPassThenThenRetireThenRetireShouldThrow
123123
ASSERT_THROW(pds.handle(RetireEvent()), std::logic_error);
124124
}
125125

126-
TEST(PipelineDefinitionStatus, ValidationPassThenThenRetireThenValidationPass) {
126+
TEST(PipelineDefinitionStatus, ValidationPassThenRetireThenReloadThenValidationPass) {
127127
PipelineDefinitionStatus pds(unusedPipelineName);
128128
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
129129
pds.handle(ValidationPassedEvent());
130130
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::AVAILABLE);
131131
pds.handle(RetireEvent());
132132
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::RETIRED);
133+
pds.handle(ReloadEvent());
134+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::RELOADING);
133135
pds.handle(ValidationPassedEvent());
134136
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::AVAILABLE);
135137
}
136138

137-
TEST(PipelineDefinitionStatus, ValidationPassThenThenRetireThenValidationFail) {
138-
PipelineDefinitionStatus pds(unusedPipelineName);
139-
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
140-
pds.handle(ValidationPassedEvent());
141-
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::AVAILABLE);
142-
pds.handle(RetireEvent());
143-
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::RETIRED);
144-
pds.handle(ValidationFailedEvent());
145-
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::LOADING_PRECONDITION_FAILED);
146-
}
147-
148-
TEST(PipelineDefinitionStatus, ValidationPassThenRetireThenValidationFail) {
139+
TEST(PipelineDefinitionStatus, ValidationPassThenRetireThenReloadThenValidationFail) {
149140
PipelineDefinitionStatus pds(unusedPipelineName);
150141
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
151142
pds.handle(ValidationPassedEvent());
152143
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::AVAILABLE);
153144
pds.handle(RetireEvent());
154145
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::RETIRED);
146+
pds.handle(ReloadEvent());
147+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::RELOADING);
155148
pds.handle(ValidationFailedEvent());
156149
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::LOADING_PRECONDITION_FAILED);
157150
}
@@ -167,33 +160,82 @@ TEST(PipelineDefinitionStatus, ValidationPassThenValidationPassShouldThrow) {
167160
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
168161
pds.handle(ValidationPassedEvent());
169162
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::AVAILABLE);
170-
pds.handle(ValidationPassedEvent());
171-
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::AVAILABLE);
163+
// should be reload in between
164+
ASSERT_THROW(pds.handle(ValidationPassedEvent()), std::logic_error);
172165
}
173166

174167
TEST(PipelineDefinitionStatus, ValidationPassThenValidationFailShouldThrow) {
175168
PipelineDefinitionStatus pds(unusedPipelineName);
176169
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
177170
pds.handle(ValidationPassedEvent());
178171
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::AVAILABLE);
172+
// should be reload in between
173+
ASSERT_THROW(pds.handle(ValidationFailedEvent(modelNotifyingDetails)), std::logic_error);
174+
}
175+
176+
TEST(PipelineDefinitionStatus, ValidationFailThenValidationFailShouldThrow) {
177+
PipelineDefinitionStatus pds(unusedPipelineName);
178+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
179179
pds.handle(ValidationFailedEvent());
180180
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::LOADING_PRECONDITION_FAILED);
181+
// should be reload in between
182+
ASSERT_THROW(pds.handle(ValidationFailedEvent(modelNotifyingDetails)), std::logic_error);
181183
}
182184

183-
TEST(PipelineDefinitionStatus, ValidationFailThenValidationFailShouldThrow) {
185+
TEST(PipelineDefinitionStatus, ValidationFailThenValidationPassShouldThrow) {
184186
PipelineDefinitionStatus pds(unusedPipelineName);
185187
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
186188
pds.handle(ValidationFailedEvent());
187189
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::LOADING_PRECONDITION_FAILED);
190+
// should be reload in between
191+
ASSERT_THROW(pds.handle(ValidationPassedEvent()), std::logic_error);
192+
}
193+
194+
TEST(PipelineDefinitionStatus, ValidationFailThenReloadThenValidationFail) {
195+
PipelineDefinitionStatus pds(unusedPipelineName);
196+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
188197
pds.handle(ValidationFailedEvent());
189198
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::LOADING_PRECONDITION_FAILED);
199+
pds.handle(ReloadEvent());
200+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::RELOADING);
201+
pds.handle(ValidationFailedEvent(modelNotifyingDetails));
202+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::LOADING_PRECONDITION_FAILED);
190203
}
191204

192-
TEST(PipelineDefinitionStatus, ValidationFailThenValidationPassShouldThrow) {
205+
TEST(PipelineDefinitionStatus, ValidationFailThenReloadThenValidationPass) {
193206
PipelineDefinitionStatus pds(unusedPipelineName);
194207
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
195208
pds.handle(ValidationFailedEvent());
196209
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::LOADING_PRECONDITION_FAILED);
210+
pds.handle(ReloadEvent());
211+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::RELOADING);
212+
pds.handle(ValidationPassedEvent());
213+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::AVAILABLE);
214+
}
215+
216+
TEST(PipelineDefinitionStatus, ValidationPassThenRetireThenValidationPassShouldThrow) {
217+
PipelineDefinitionStatus pds(unusedPipelineName);
218+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
219+
pds.handle(ValidationPassedEvent());
220+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::AVAILABLE);
221+
pds.handle(RetireEvent());
222+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::RETIRED);
223+
// should be reload in between
224+
ASSERT_THROW(pds.handle(ValidationPassedEvent()), std::logic_error);
225+
}
226+
227+
TEST(PipelineDefinitionStatus, ValidationPassThenRetireThenValidationFailShouldThrow) {
228+
PipelineDefinitionStatus pds(unusedPipelineName);
229+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
197230
pds.handle(ValidationPassedEvent());
198231
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::AVAILABLE);
232+
pds.handle(RetireEvent());
233+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::RETIRED);
234+
// should be reload in between
235+
ASSERT_THROW(pds.handle(ValidationFailedEvent()), std::logic_error);
236+
}
237+
TEST(PipelineDefinitionStatus, ReloadFromBeginShouldThrow) {
238+
PipelineDefinitionStatus pds(unusedPipelineName);
239+
ASSERT_EQ(pds.getStateCode(), ovms::PipelineDefinitionStateCode::BEGIN);
240+
ASSERT_THROW(pds.handle(ReloadEvent()), std::logic_error);
199241
}

0 commit comments

Comments
 (0)