MethodBehaviorJsonAdapter implements JsonSerializer<MethodBehavior>, JsonDeserializer<MethodBehavior> { private static JsonElement toJson(MethodYield methodYield, int arity) { JsonObject yield = new JsonObject(); JsonArray jsonParameterConstraints = new JsonArray(); for (int i = 0; i < arity; i++) { jsonParameterConstraints.add(toJson(methodYield.parametersConstraints.get(i))); } yield.add(JSON_PARAMETERS_CONSTRAINTS, jsonParameterConstraints); if (methodYield instanceof HappyPathYield) { HappyPathYield happyPathYield = (HappyPathYield) methodYield; yield.addProperty(JSON_RESULT_INDEX, happyPathYield.resultIndex()); yield.add(JSON_RESULT_CONSTRAINTS, toJson(happyPathYield.resultConstraint())); } else if (methodYield instanceof ExceptionalYield) { ExceptionalYield exceptionalYield = (ExceptionalYield) methodYield; yield.addProperty(JSON_THROWN_EXCEPTION, exceptionalYield.getExceptionType()); } else { throw new IllegalStateException("Hardcoded yields should only be HappyPathYield or ExceptionalYield."); } return yield; } private  MethodBehaviorJsonAdapter(); static Gson gson(); @Override MethodBehavior deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context); @Override JsonElement serialize(MethodBehavior src, Type typeOfSrc, JsonSerializationContext context);  }
@Test void serialization() { MethodBehavior isInstancePrecomputed = cache.get(IS_INSTANCE_SIGNATURE); assertThat(isInstancePrecomputed).isNotNull(); String isInstanceSerialized = gson.toJson(isInstancePrecomputed); assertThat(isInstanceSerialized).isEqualTo(IS_INSTANCE_METHOD_BEHAVIOR); }
@Test void serialization_unknown_yield_type_should_throw_an_exception() { MethodBehavior mb = newMethodBehavior("org.bar.A#foo()Z"); mb.addYield(new CustomMethodYield(mb)); mb.completed(); IllegalStateException e = assertThrows(IllegalStateException.class, () -> gson.toJson(mb)); assertThat(e).hasMessage("Hardcoded yields should only be HappyPathYield or ExceptionalYield."); }
@Test void serialization_unsupported_constraint_should_be_ignored() { MethodBehavior mb = newMethodBehavior("org.bar.A#foo()Z"); HappyPathYield happyPathYield = new HappyPathYield(mb); happyPathYield.setResult(-1, ConstraintsByDomain.empty().put(CustomConstraint.SQUARE).put(ObjectConstraint.NOT_NULL)); mb.addYield(happyPathYield); mb.completed(); assertThat(gson.toJson(mb)) .contains("resultConstraint\": [\n" + " \"NOT_NULL\"\n" + " ]") .doesNotContain("SQUARE"); }
@Test void serialization_null_constraints_should_be_stored_as_null() { MethodBehavior mb = newMethodBehavior("org.bar.A#foo()Z"); HappyPathYield happyPathYield = new HappyPathYield(mb); happyPathYield.setResult(-1, null); mb.addYield(happyPathYield); mb.completed(); assertThat(gson.toJson(mb)) .contains("\"resultConstraint\": null") .contains("\"parametersConstraints\": []"); }
@Test void deserialization_serialization() { MethodBehavior customBehavior = newMethodBehavior("org.bar.A#foo(Ljava/lang/Object;)Z"); customBehavior.setDeclaredExceptions(Arrays.asList("org.foo.MyException", "org.bar.MyOtherException")); customBehavior.setVarArgs(true); HappyPathYield hpy = new HappyPathYield(customBehavior); hpy.setResult(-1, ConstraintsByDomain.empty().put(BooleanConstraint.TRUE)); hpy.parametersConstraints.add(ConstraintsByDomain.empty().put(ObjectConstraint.NOT_NULL)); customBehavior.addYield(hpy); ExceptionalYield ey = new ExceptionalYield(customBehavior); ey.setExceptionType("org.bar.MyOtherException"); ey.parametersConstraints.add(ConstraintsByDomain.empty().put(ObjectConstraint.NULL)); customBehavior.addYield(ey); customBehavior.completed(); String serialized = gson.toJson(customBehavior); assertThat(serialized).isEqualTo( "{\n" + " \"signature\": \"org.bar.A#foo(Ljava/lang/Object;)Z\",\n" + " \"varArgs\": true,\n" + " \"declaredExceptions\": [\n" + " \"org.foo.MyException\",\n" + " \"org.bar.MyOtherException\"\n" + " ],\n" + " \"yields\": [\n" + " {\n" + " \"parametersConstraints\": [\n" + " [\n" + " \"NULL\"\n" + " ]\n" + " ],\n" + " \"exception\": \"org.bar.MyOtherException\"\n" + " },\n" + " {\n" + " \"parametersConstraints\": [\n" + " [\n" + " \"NOT_NULL\"\n" + " ]\n" + " ],\n" + " \"resultIndex\": -1,\n" + " \"resultConstraint\": [\n" + " \"TRUE\"\n" + " ]\n" + " }\n" + " ]\n" + "}"); MethodBehavior deserialized = gson.fromJson(serialized, MethodBehavior.class); assertThat(deserialized).isEqualTo(customBehavior); }
@Test void exceptional_yield_serialization_deserialaization() { MethodBehavior mb = newMethodBehavior("org.foo.A.bar(Ljava/lang/Object;)Z"); ExceptionalYield yield = new ExceptionalYield(mb); yield.setExceptionType("java.lang.Exception"); yield.parametersConstraints.add(ConstraintsByDomain.empty().put(ObjectConstraint.NULL)); mb.addYield(yield); mb.completed(); String serialized = gson.toJson(mb); assertThat(serialized).contains("\"yields\": [\n" + " {\n" + " \"parametersConstraints\": [\n" + " [\n" + " \"NULL\"\n" + " ]\n" + " ],\n" + " \"exception\": \"java.lang.Exception\"\n" + " }\n" + " ]"); MethodBehavior deserialized = gson.fromJson(serialized, MethodBehavior.class); assertThat(deserialized).isEqualTo(mb); }