@@ -192,6 +192,102 @@ TEST(encode, mset_fail_arity)
192192 EXPECT_THROW (encode (med::octet_encoder{ctx}, proto), med::missing_ie);
193193}
194194
195+ TEST (encode, set_func_ok)
196+ {
197+ PROTO proto;
198+
199+ MSG_SET_FUNC& msg = proto.ref <MSG_SET_FUNC>();
200+
201+ // one mandatory, one conditional + setter, one optional
202+ msg.ref <FLD_UC>().set (0x11 );
203+ msg.ref <FLD_U16>().set (3 );
204+ msg.ref <FLD_IP>().set (1 );
205+
206+ uint8_t buffer[1024 ];
207+ med::encoder_context ctx{buffer};
208+
209+ EXPECT_NO_THROW (encode (med::octet_encoder{ctx}, proto));
210+
211+ // M< T16<0x0b>, FLD_UC >, //<TV>
212+ // M< T16<0x0d>, FLD_FLAGS, FLD_FLAGS::setter >,
213+ // O< T16<0x21>, FLD_U16, FLD_FLAGS::has_bits<FLD_FLAGS::U16> >,
214+ // O< T16<0x89>, FLD_IP >
215+ uint8_t const encoded1[] = { 0x24
216+ , 0 , 0x0b , 0x11
217+ , 0 , 0x0d , 0b0000'0101
218+ , 0 , 0x21 , 0x00 , 0x03
219+ , 0 , 0x89 , 0x00 , 0x00 , 0x00 , 0x01
220+ };
221+ EXPECT_EQ (sizeof (encoded1), ctx.buffer ().get_offset ());
222+ EXPECT_TRUE (Matches (encoded1, buffer));
223+
224+ // one mandatory + setter
225+ ctx.reset ();
226+ msg.clear ();
227+ msg.ref <FLD_UC>().set (0x11 );
228+ EXPECT_NO_THROW (encode (med::octet_encoder{ctx}, proto));
229+
230+ // M< T16<0x0b>, FLD_UC >, //<TV>
231+ // M< T16<0x0d>, FLD_FLAGS, FLD_FLAGS::setter >,
232+ uint8_t const encoded2[] = { 0x24
233+ , 0 , 0x0b , 0x11
234+ , 0 , 0x0d , 0b0000'0000
235+ };
236+ EXPECT_EQ (sizeof (encoded2), ctx.buffer ().get_offset ());
237+ EXPECT_TRUE (Matches (encoded2, buffer));
238+
239+ // full msg
240+ ctx.reset ();
241+ msg.clear ();
242+ msg.ref <FLD_UC>().set (0x11 );
243+ msg.ref <FLD_U16>().set (3 );
244+ msg.ref <FLD_IP>().set (1 );
245+ msg.ref <FLD_U24>().set (2 );
246+ msg.ref <FLD_U8>().set (4 );
247+ msg.ref <FLD_QTY>().set (5 );
248+
249+ // try to set wrong flags
250+ msg.ref <FLD_FLAGS>().set (255 );
251+
252+ EXPECT_NO_THROW (encode (med::octet_encoder{ctx}, proto));
253+
254+ // M< T16<0x0b>, FLD_UC >, //<TV>
255+ // M< T16<0x0d>, FLD_FLAGS, FLD_FLAGS::setter >,
256+ // O< T16<0x0e>, FLD_QTY, FLD_FLAGS::has_bits<FLD_FLAGS::QTY> >,
257+ // O< T16<0x0c>, FLD_U8 >, //<TV>
258+ // O< T16<0x21>, FLD_U16, FLD_FLAGS::has_bits<FLD_FLAGS::U16> >,
259+ // O< T16<0x49>, FLD_U24, FLD_FLAGS::has_bits<FLD_FLAGS::U24> >,
260+ // O< T16<0x89>, FLD_IP >
261+ uint8_t const encoded3[] = { 0x24
262+ , 0 , 0x0b , 0x11
263+ , 0 , 0x0d , 0b0100'0111
264+ , 0 , 0x0e , 0x05
265+ , 0 , 0x0c , 0x04
266+ , 0 , 0x21 , 0x00 , 0x03
267+ , 0 , 0x49 , 0x00 , 0x00 , 0x02
268+ , 0 , 0x89 , 0x00 , 0x00 , 0x00 , 0x01
269+ };
270+
271+ EXPECT_EQ (sizeof (encoded3), ctx.buffer ().get_offset ());
272+ EXPECT_TRUE (Matches (encoded3, buffer));
273+ }
274+
275+ TEST (encode, set_func_fail)
276+ {
277+ PROTO proto;
278+
279+ MSG_SET_FUNC& msg = proto.ref <MSG_SET_FUNC>();
280+
281+ // NO mandatory, one conditional + setter, one optional
282+ msg.ref <FLD_U16>().set (3 );
283+ msg.ref <FLD_IP>().set (1 );
284+
285+ uint8_t buffer[1024 ];
286+ med::encoder_context ctx{buffer};
287+
288+ EXPECT_THROW (encode (med::octet_encoder{ctx}, proto), med::missing_ie);
289+ }
290+
195291TEST (decode, set_ok)
196292{
197293 PROTO proto;
@@ -413,3 +509,98 @@ TEST(decode, mset_fail_arity)
413509 ctx.reset (mandatory_overflow, sizeof (mandatory_overflow));
414510 EXPECT_THROW (decode (med::octet_decoder{ctx}, proto), med::extra_ie);
415511}
512+
513+ TEST (decode, set_func_ok)
514+ {
515+ PROTO proto;
516+
517+ // mandatory fields only
518+ uint8_t const encoded1[] = { 0x24
519+ , 0 , 0x0b , 0x11
520+ , 0 , 0x0d , 0x00 ,
521+ };
522+ med::decoder_context ctx{encoded1};
523+ EXPECT_NO_THROW (decode (med::octet_decoder{ctx}, proto));
524+ {
525+ MSG_SET_FUNC const * msg = proto.get <MSG_SET_FUNC>();
526+ ASSERT_NE (nullptr , msg);
527+
528+ ASSERT_EQ (0x11 , msg->get <FLD_UC>().get ());
529+ ASSERT_EQ (0x00 , msg->get <FLD_FLAGS>().get ());
530+ FLD_U24 const * fld1 = msg->get <FLD_U24>();
531+ FLD_U16 const * fld2 = msg->get <FLD_U16>();
532+ FLD_U8 const * fld3 = msg->get <FLD_U8>();
533+ FLD_IP const * fld4 = msg->get <FLD_IP>();
534+ FLD_QTY const * fld5 = msg->get <FLD_QTY>();
535+ ASSERT_EQ (nullptr , fld1);
536+ ASSERT_EQ (nullptr , fld2);
537+ ASSERT_EQ (nullptr , fld3);
538+ ASSERT_EQ (nullptr , fld4);
539+ ASSERT_EQ (nullptr , fld5);
540+ }
541+ // all fields but in reverse order
542+ uint8_t const encoded2[] = { 0x24
543+ , 0 , 0x89 , 0x00 , 0x00 , 0x00 , 0x01
544+ , 0 , 0x49 , 0x00 , 0x00 , 0x02
545+ , 0 , 0x21 , 0x00 , 0x03
546+ , 0 , 0x0c , 0x04
547+ , 0 , 0x0e , 0x05
548+ , 0 , 0x0b , 0x11
549+ , 0 , 0x0d , 0b0100'0111 ,
550+ };
551+ ctx.reset (encoded2);
552+ EXPECT_NO_THROW (decode (med::octet_decoder{ctx}, proto));
553+ {
554+ MSG_SET_FUNC const * msg = proto.get <MSG_SET_FUNC>();
555+ ASSERT_NE (nullptr , msg);
556+
557+ ASSERT_EQ (0x11 , msg->get <FLD_UC>().get ());
558+ FLD_U24 const * fld1 = msg->get <FLD_U24>();
559+ FLD_U16 const * fld2 = msg->get <FLD_U16>();
560+ FLD_U8 const * fld3 = msg->get <FLD_U8>();
561+ FLD_IP const * fld4 = msg->get <FLD_IP>();
562+ FLD_QTY const * fld5 = msg->get <FLD_QTY>();
563+ ASSERT_NE (nullptr , fld1);
564+ ASSERT_NE (nullptr , fld2);
565+ ASSERT_NE (nullptr , fld3);
566+ ASSERT_NE (nullptr , fld4);
567+ ASSERT_NE (nullptr , fld5);
568+ ASSERT_EQ (2 , fld1->get ());
569+ ASSERT_EQ (3 , fld2->get ());
570+ ASSERT_EQ (4 , fld3->get ());
571+ ASSERT_EQ (1 , fld4->get ());
572+ ASSERT_EQ (5 , fld5->get ());
573+ // ASSERT_EQ(0b0010'1111, msg->get<FLD_FLAGS>().get());
574+ ASSERT_TRUE (FLD_FLAGS::has_bits<FLD_FLAGS::U16>{}(msg->body ()));
575+ ASSERT_TRUE (FLD_FLAGS::has_bits<FLD_FLAGS::U24>{}(msg->body ()));
576+ ASSERT_TRUE (FLD_FLAGS::has_bits<FLD_FLAGS::QTY>{}(msg->body ()));
577+ constexpr size_t u8_qty = 1 ;
578+ ASSERT_TRUE (FLD_FLAGS::has_bits<u8_qty << FLD_FLAGS::U8_QTY>{}(msg->body ()));
579+ auto const uc_qty_minus_one = 1 - 1 ;
580+ ASSERT_FALSE (FLD_FLAGS::has_bits<uc_qty_minus_one << FLD_FLAGS::UC_QTY>{}(msg->body ()));
581+ }
582+ }
583+
584+ TEST (decode, set_func_fail)
585+ {
586+ PROTO proto;
587+
588+ // mandatory fields only, but some flags are set
589+ uint8_t const encoded1[] = { 0x24
590+ , 0 , 0x0b , 0x11
591+ , 0 , 0x0d , 0b0100'0111
592+ };
593+ med::decoder_context ctx{encoded1};
594+ EXPECT_THROW (decode (med::octet_decoder{ctx}, proto), med::missing_ie);
595+
596+ // some conditional fields, but flags are NOT set
597+ uint8_t const encoded2[] = { 0x24
598+ , 0 , 0x49 , 0x00 , 0x00 , 0x02
599+ , 0 , 0x21 , 0x00 , 0x03
600+ , 0 , 0x0c , 0x04
601+ , 0 , 0x0b , 0x11
602+ , 0 , 0x0d , 0b0100'0000
603+ };
604+ ctx.reset (encoded2);
605+ EXPECT_THROW (decode (med::octet_decoder{ctx}, proto), med::extra_ie);
606+ }
0 commit comments