@@ -385,3 +385,88 @@ TEST_F(VariationsFixture, OffWithUndefinedOffVariation) {
385385 LDClientClose (client);
386386 LDDetailsClear (&details);
387387}
388+
389+
390+ TEST_F (VariationsFixture, TestNullOffVariationInPrerequisiteDoesNotCauseUseAfterFree) {
391+ struct LDJSON *flag;
392+ struct LDDetails details;
393+ struct LDClient *client;
394+ struct LDUser *user = LDUserNew (" foo" );
395+
396+ ASSERT_TRUE (client = makeTestClient ());
397+
398+ LDDetailsInit (&details);
399+
400+ ASSERT_TRUE (flag = LDNewObject ());
401+ ASSERT_TRUE (LDObjectSetKey (flag, " clientSide" , LDNewBool (LDBooleanFalse)));
402+ ASSERT_TRUE (LDObjectSetKey (flag, " debugEventsUntilDate" , LDNewNull ()));
403+ ASSERT_TRUE (LDObjectSetKey (flag, " deleted" , LDNewBool (LDBooleanFalse)));
404+ ASSERT_TRUE (LDObjectSetKey (flag, " key" , LDNewText (" streaming.03.featureKey" )));
405+ ASSERT_TRUE (LDObjectSetKey (flag, " on" , LDNewBool (LDBooleanTrue)));
406+ ASSERT_TRUE (LDObjectSetKey (flag, " salt" , LDNewText (" " )));
407+ ASSERT_TRUE (LDObjectSetKey (flag, " offVariation" , LDNewNull ()));
408+ ASSERT_TRUE (LDObjectSetKey (flag, " trackEvents" , LDNewBool (LDBooleanTrue)));
409+ ASSERT_TRUE (LDObjectSetKey (flag, " trackEventsFallthrough" , LDNewBool (LDBooleanFalse)));
410+ ASSERT_TRUE (LDObjectSetKey (flag, " targets" , LDNewArray ()));
411+ ASSERT_TRUE (LDObjectSetKey (flag, " rules" , LDNewArray ()));
412+ ASSERT_TRUE (LDObjectSetKey (flag, " version" , LDNewNumber (0 )));
413+
414+
415+ struct LDJSON *variations = LDNewArray ();
416+ ASSERT_TRUE (LDArrayPush (variations, LDNewText (" A" )));
417+ ASSERT_TRUE (LDArrayPush (variations, LDNewText (" B" )));
418+
419+ ASSERT_TRUE (LDObjectSetKey (flag, " variations" , variations));
420+
421+ struct LDJSON *fallthrough;
422+ ASSERT_TRUE (fallthrough = LDNewObject ());
423+ ASSERT_TRUE (LDObjectSetKey (fallthrough, " variation" , LDNewNumber (0 )));
424+ ASSERT_TRUE (LDObjectSetKey (flag, " fallthrough" , fallthrough));
425+
426+ struct LDJSON *prerequisites = LDNewArray ();
427+ struct LDJSON *prereq = LDNewObject ();
428+ ASSERT_TRUE (LDObjectSetKey (prereq, " key" , LDNewText (" streaming.03.prereqFeatureKey" )));
429+ ASSERT_TRUE (LDObjectSetKey (prereq, " variation" , LDNewNumber (0 )));
430+ ASSERT_TRUE (LDArrayPush (prerequisites, prereq));
431+
432+ ASSERT_TRUE (LDObjectSetKey (flag, " prerequisites" , prerequisites));
433+
434+ struct LDJSON *prerequisite = LDNewObject ();
435+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " clientSide" , LDNewBool (LDBooleanFalse)));
436+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " debugEventsUntilDate" , LDNewNull ()));
437+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " deleted" , LDNewBool (LDBooleanFalse)));
438+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " key" , LDNewText (" streaming.03.prereqFeatureKey" )));
439+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " offVariation" , LDNewNull ()));
440+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " on" , LDNewBool (LDBooleanFalse)));
441+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " prerequisites" , LDNewArray ()));
442+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " rules" , LDNewArray ()));
443+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " salt" , LDNewText (" " )));
444+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " trackEvents" , LDNewBool (LDBooleanTrue)));
445+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " trackEventsFallthrough" , LDNewBool (LDBooleanFalse)));
446+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " targets" , LDNewArray ()));
447+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " version" , LDNewNumber (0 )));
448+
449+ struct LDJSON *pfallthrough;
450+ ASSERT_TRUE (pfallthrough = LDNewObject ());
451+ ASSERT_TRUE (LDObjectSetKey (pfallthrough, " variation" , LDNewNumber (0 )));
452+ ASSERT_TRUE (LDObjectSetKey (prerequisite, " fallthrough" , pfallthrough));
453+
454+ struct LDJSON *pvariations = LDNewArray ();
455+ LDArrayPush (pvariations, LDNewText (" first" ));
456+ LDArrayPush (pvariations, LDNewText (" second" ));
457+
458+ LDObjectSetKey (prerequisite, " variations" , pvariations);
459+
460+ ASSERT_TRUE (LDStoreInitEmpty (client->store ));
461+
462+ LDStoreUpsert (client->store , LD_FLAG, prerequisite);
463+ LDStoreUpsert (client->store , LD_FLAG, flag);
464+
465+ char *result = LDStringVariation (client, user, " streaming.03.featureKey" , " default" , &details);
466+
467+ LDUserFree (user);
468+ LDDetailsClear (&details);
469+ LDFree (result);
470+ LDClientClose (client);
471+
472+ }
0 commit comments