1+ /* *******************************************************************************
2+ * Copyright (c) 2025 Contributors to the Eclipse Foundation
3+ *
4+ * See the NOTICE file(s) distributed with this work for additional
5+ * information regarding copyright ownership.
6+ *
7+ * This program and the accompanying materials are made available under the
8+ * terms of the Apache License Version 2.0 which is available at
9+ * https://www.apache.org/licenses/LICENSE-2.0
10+ *
11+ * SPDX-License-Identifier: Apache-2.0
12+ ********************************************************************************/
13+
14+ #include " score/mw/com/impl/configuration/lola_service_instance_deployment.h"
15+ #include " score/mw/com/impl/configuration/quality_type.h"
16+
17+ #include < gtest/gtest.h>
18+ #include < gmock/gmock.h>
19+
20+ namespace score ::mw::com::impl
21+ {
22+ namespace
23+ {
24+
25+ class LolaServiceUidMapTest : public ::testing::Test
26+ {
27+ };
28+
29+ TEST_F (LolaServiceUidMapTest, HandleMalformedUidListGracefully)
30+ {
31+ // Test the fix for dangling reference in ConvertJsonToUidMap
32+ // This should trigger the new error handling for invalid UID lists
33+
34+ score::json::Object config_object;
35+
36+ // Add required fields for LolaServiceInstanceDeployment constructor
37+ config_object[" serializationVersion" ] = score::json::Any{1U };
38+ config_object[" strict" ] = score::json::Any{false };
39+ config_object[" events" ] = score::json::Any{score::json::Object{}};
40+ config_object[" fields" ] = score::json::Any{score::json::Object{}};
41+ config_object[" methods" ] = score::json::Any{score::json::Object{}};
42+
43+ // Create JSON with invalid UID list (string instead of array)
44+ score::json::Object malformed_uid_map;
45+ malformed_uid_map[" ASIL_QM" ] = score::json::Any{std::string{" invalid_should_be_array" }};
46+ config_object[" allowedConsumer" ] = score::json::Any{std::move (malformed_uid_map)};
47+
48+ // Valid empty provider map
49+ config_object[" allowedProvider" ] = score::json::Any{score::json::Object{}};
50+
51+ // This should trigger the new error path without crashing
52+ EXPECT_DEATH ({
53+ LolaServiceInstanceDeployment deployment (config_object);
54+ }, " Invalid UID list in configuration" );
55+ }
56+
57+ TEST_F (LolaServiceUidMapTest, HandleNullUidListGracefully)
58+ {
59+ // Test case where UID list is null instead of array
60+ score::json::Object config_object;
61+
62+ // Add required fields for LolaServiceInstanceDeployment constructor
63+ config_object[" serializationVersion" ] = score::json::Any{1U };
64+ config_object[" strict" ] = score::json::Any{false };
65+ config_object[" events" ] = score::json::Any{score::json::Object{}};
66+ config_object[" fields" ] = score::json::Any{score::json::Object{}};
67+ config_object[" methods" ] = score::json::Any{score::json::Object{}};
68+
69+ score::json::Object malformed_uid_map;
70+ malformed_uid_map[" ASIL_QM" ] = score::json::Any{}; // null/empty Any
71+ config_object[" allowedConsumer" ] = score::json::Any{std::move (malformed_uid_map)};
72+
73+ // Valid empty provider map
74+ config_object[" allowedProvider" ] = score::json::Any{score::json::Object{}};
75+
76+ EXPECT_DEATH ({
77+ LolaServiceInstanceDeployment deployment (config_object);
78+ }, " Invalid UID list in configuration" );
79+ }
80+
81+ TEST_F (LolaServiceUidMapTest, HandleObjectInsteadOfUidList)
82+ {
83+ // Test case where UID list is an object instead of array
84+ score::json::Object config_object;
85+
86+ // Add required fields for LolaServiceInstanceDeployment constructor
87+ config_object[" serializationVersion" ] = score::json::Any{1U };
88+ config_object[" strict" ] = score::json::Any{false };
89+ config_object[" events" ] = score::json::Any{score::json::Object{}};
90+ config_object[" fields" ] = score::json::Any{score::json::Object{}};
91+ config_object[" methods" ] = score::json::Any{score::json::Object{}};
92+
93+ score::json::Object malformed_uid_map;
94+ score::json::Object invalid_object;
95+ invalid_object[" key" ] = score::json::Any{42 };
96+ malformed_uid_map[" ASIL_B" ] = score::json::Any{std::move (invalid_object)};
97+ config_object[" allowedConsumer" ] = score::json::Any{std::move (malformed_uid_map)};
98+
99+ // Valid empty provider map
100+ config_object[" allowedProvider" ] = score::json::Any{score::json::Object{}};
101+
102+ EXPECT_DEATH ({
103+ LolaServiceInstanceDeployment deployment (config_object);
104+ }, " Invalid UID list in configuration" );
105+ }
106+
107+ TEST_F (LolaServiceUidMapTest, HandleValidUidMapAfterFix)
108+ {
109+ // Test that valid UID maps still work correctly after the fix
110+ score::json::Object config_object;
111+
112+ // Add required fields for LolaServiceInstanceDeployment constructor
113+ config_object[" serializationVersion" ] = score::json::Any{1U };
114+ config_object[" strict" ] = score::json::Any{false };
115+ config_object[" events" ] = score::json::Any{score::json::Object{}};
116+ config_object[" fields" ] = score::json::Any{score::json::Object{}};
117+ config_object[" methods" ] = score::json::Any{score::json::Object{}};
118+
119+ score::json::Object valid_uid_map;
120+ score::json::List uid_list;
121+ uid_list.emplace_back (score::json::Any{1001 });
122+ uid_list.emplace_back (score::json::Any{1002 });
123+ uid_list.emplace_back (score::json::Any{1003 });
124+ valid_uid_map[" ASIL_QM" ] = score::json::Any{std::move (uid_list)};
125+ config_object[" allowedConsumer" ] = score::json::Any{std::move (valid_uid_map)};
126+
127+ // Valid empty provider map
128+ config_object[" allowedProvider" ] = score::json::Any{score::json::Object{}};
129+
130+ // Should work without errors after the dangling reference fix
131+ LolaServiceInstanceDeployment deployment (config_object);
132+
133+ EXPECT_EQ (deployment.allowed_consumer_ .size (), 1 );
134+ EXPECT_TRUE (deployment.allowed_consumer_ .find (QualityType::kASIL_QM ) != deployment.allowed_consumer_ .end ());
135+
136+ const auto & uids = deployment.allowed_consumer_ .at (QualityType::kASIL_QM );
137+ EXPECT_THAT (uids, ::testing::ElementsAre (1001 , 1002 , 1003 ));
138+ }
139+
140+ TEST_F (LolaServiceUidMapTest, HandleMultipleQualityTypesWithMixedValidity)
141+ {
142+ // Test mixed valid and invalid entries
143+ score::json::Object config_object;
144+
145+ // Add required fields for LolaServiceInstanceDeployment constructor
146+ config_object[" serializationVersion" ] = score::json::Any{1U };
147+ config_object[" strict" ] = score::json::Any{false };
148+ config_object[" events" ] = score::json::Any{score::json::Object{}};
149+ config_object[" fields" ] = score::json::Any{score::json::Object{}};
150+ config_object[" methods" ] = score::json::Any{score::json::Object{}};
151+
152+ score::json::Object mixed_uid_map;
153+ // Valid entry
154+ score::json::List valid_uid_list;
155+ valid_uid_list.emplace_back (score::json::Any{2001 });
156+ mixed_uid_map[" ASIL_QM" ] = score::json::Any{std::move (valid_uid_list)};
157+
158+ // Invalid entry (will be processed after valid one)
159+ mixed_uid_map[" ASIL_B" ] = score::json::Any{std::string{" invalid" }};
160+ config_object[" allowedConsumer" ] = score::json::Any{std::move (mixed_uid_map)};
161+
162+ // Valid empty provider map
163+ config_object[" allowedProvider" ] = score::json::Any{score::json::Object{}};
164+
165+ // Should fail on the invalid entry after successfully processing the valid one
166+ EXPECT_DEATH ({
167+ LolaServiceInstanceDeployment deployment (config_object);
168+ }, " Invalid UID list in configuration" );
169+ }
170+
171+ TEST_F (LolaServiceUidMapTest, VerifyStableReferenceLifetime)
172+ {
173+ // This test specifically validates that the fix properly manages
174+ // the lifetime of references by ensuring no crashes occur during processing
175+
176+ score::json::Object config_object;
177+
178+ // Add required fields for LolaServiceInstanceDeployment constructor
179+ config_object[" serializationVersion" ] = score::json::Any{1U };
180+ config_object[" strict" ] = score::json::Any{false };
181+ config_object[" events" ] = score::json::Any{score::json::Object{}};
182+ config_object[" fields" ] = score::json::Any{score::json::Object{}};
183+ config_object[" methods" ] = score::json::Any{score::json::Object{}};
184+
185+ score::json::Object complex_uid_map;
186+
187+ // Create multiple quality types with valid UID lists
188+ for (const auto & quality_str : {" ASIL_QM" , " ASIL_A" , " ASIL_B" , " ASIL_C" , " ASIL_D" }) {
189+ score::json::List uid_list;
190+
191+ // Add multiple UIDs to stress test reference handling
192+ for (int i = 0 ; i < 10 ; ++i) {
193+ uid_list.emplace_back (score::json::Any{1000 + i});
194+ }
195+
196+ complex_uid_map[quality_str] = score::json::Any{std::move (uid_list)};
197+ }
198+
199+ config_object[" allowedConsumer" ] = score::json::Any{std::move (complex_uid_map)};
200+
201+ // Valid empty provider map
202+ config_object[" allowedProvider" ] = score::json::Any{score::json::Object{}};
203+
204+ // This should complete successfully without any dangling reference issues
205+ LolaServiceInstanceDeployment deployment (config_object);
206+
207+ // Verify the results are correct
208+ EXPECT_EQ (deployment.allowed_consumer_ .size (), 5 );
209+
210+ // Each quality type should have 10 UIDs
211+ for (const auto & [quality_type, uids] : deployment.allowed_consumer_ ) {
212+ EXPECT_EQ (uids.size (), 10 );
213+
214+ // Verify UID values are in expected range
215+ for (const auto & uid : uids) {
216+ EXPECT_GE (uid, 1000 );
217+ EXPECT_LT (uid, 1010 );
218+ }
219+ }
220+ }
221+
222+ TEST_F (LolaServiceUidMapTest, HandleEmptyUidList)
223+ {
224+ // Test empty but valid UID list
225+ score::json::Object config_object;
226+
227+ // Add required fields for LolaServiceInstanceDeployment constructor
228+ config_object[" serializationVersion" ] = score::json::Any{1U };
229+ config_object[" strict" ] = score::json::Any{false };
230+ config_object[" events" ] = score::json::Any{score::json::Object{}};
231+ config_object[" fields" ] = score::json::Any{score::json::Object{}};
232+ config_object[" methods" ] = score::json::Any{score::json::Object{}};
233+
234+ score::json::Object uid_map_with_empty_list;
235+ score::json::List empty_uid_list; // Empty but valid list
236+ uid_map_with_empty_list[" ASIL_QM" ] = score::json::Any{std::move (empty_uid_list)};
237+ config_object[" allowedConsumer" ] = score::json::Any{std::move (uid_map_with_empty_list)};
238+
239+ // Valid empty provider map
240+ config_object[" allowedProvider" ] = score::json::Any{score::json::Object{}};
241+
242+ LolaServiceInstanceDeployment deployment (config_object);
243+
244+ EXPECT_EQ (deployment.allowed_consumer_ .size (), 1 );
245+ EXPECT_TRUE (deployment.allowed_consumer_ .find (QualityType::kASIL_QM ) != deployment.allowed_consumer_ .end ());
246+ EXPECT_TRUE (deployment.allowed_consumer_ .at (QualityType::kASIL_QM ).empty ());
247+ }
248+
249+ } // namespace
250+ } // namespace score::mw::com::impl
0 commit comments