public static void getSemanticPropsDualFromString(
            DualInputSemanticProperties result,
            String[] forwardedFirst,
            String[] forwardedSecond,
            String[] nonForwardedFirst,
            String[] nonForwardedSecond,
            String[] readFieldsFirst,
            String[] readFieldsSecond,
            TypeInformation<?> inType1,
            TypeInformation<?> inType2,
            TypeInformation<?> outType) {
        getSemanticPropsDualFromString(
                result,
                forwardedFirst,
                forwardedSecond,
                nonForwardedFirst,
                nonForwardedSecond,
                readFieldsFirst,
                readFieldsSecond,
                inType1,
                inType2,
                outType,
                false);
    }
@Test
    void testForwardedDual() {
        String[] forwardedFieldsFirst = {"f1->f2; f2->f3"};
        String[] forwardedFieldsSecond = {"f1->f1; f2->f0"};
        DualInputSemanticProperties dsp = new DualInputSemanticProperties();
        SemanticPropUtil.getSemanticPropsDualFromString(
                dsp,
                forwardedFieldsFirst,
                forwardedFieldsSecond,
                null,
                null,
                null,
                null,
                fourIntTupleType,
                fourIntTupleType,
                fourIntTupleType);

        assertThat(dsp.getForwardingTargetFields(0, 1)).contains(2);
        assertThat(dsp.getForwardingTargetFields(0, 2)).contains(3);
        assertThat(dsp.getForwardingTargetFields(1, 1)).contains(1);
        assertThat(dsp.getForwardingTargetFields(1, 2)).contains(0);
        assertThat(dsp.getForwardingTargetFields(0, 0)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(1, 3)).isEmpty();

        forwardedFieldsFirst[0] = "f1->f0;f3->f1";
        forwardedFieldsSecond[0] = "*->f2.*";
        dsp = new DualInputSemanticProperties();
        SemanticPropUtil.getSemanticPropsDualFromString(
                dsp,
                forwardedFieldsFirst,
                forwardedFieldsSecond,
                null,
                null,
                null,
                null,
                fourIntTupleType,
                pojoType,
                pojoInTupleType);

        assertThat(dsp.getForwardingTargetFields(0, 0)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 1)).contains(0);
        assertThat(dsp.getForwardingTargetFields(0, 2)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 3)).contains(1);
        assertThat(dsp.getForwardingTargetFields(1, 0)).contains(2);
        assertThat(dsp.getForwardingTargetFields(1, 1)).contains(3);
        assertThat(dsp.getForwardingTargetFields(1, 2)).contains(4);
        assertThat(dsp.getForwardingTargetFields(1, 3)).contains(5);

        forwardedFieldsFirst[0] = "f1.f0.f2->int1; f2->pojo1.int3";
        forwardedFieldsSecond[0] = "string1; int2->pojo1.int1; int1->pojo1.int2";
        dsp = new DualInputSemanticProperties();
        SemanticPropUtil.getSemanticPropsDualFromString(
                dsp,
                forwardedFieldsFirst,
                forwardedFieldsSecond,
                null,
                null,
                null,
                null,
                deepNestedTupleType,
                pojoType,
                nestedPojoType);

        assertThat(dsp.getForwardingTargetFields(0, 0)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 1)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 2)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 3)).contains(0);
        assertThat(dsp.getForwardingTargetFields(0, 4)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 5)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 6)).contains(3);
        assertThat(dsp.getForwardingTargetFields(1, 0)).contains(2);
        assertThat(dsp.getForwardingTargetFields(1, 1)).contains(1);
        assertThat(dsp.getForwardingTargetFields(1, 2)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(1, 3)).contains(5);

        String[] forwardedFieldsFirst2 = {"f1.f0.f2->int1", "f2->pojo1.int3"};
        String[] forwardedFieldsSecond2 = {"string1", "int2->pojo1.int1", "int1->pojo1.int2"};
        dsp = new DualInputSemanticProperties();
        SemanticPropUtil.getSemanticPropsDualFromString(
                dsp,
                forwardedFieldsFirst2,
                forwardedFieldsSecond2,
                null,
                null,
                null,
                null,
                deepNestedTupleType,
                pojoType,
                nestedPojoType);

        assertThat(dsp.getForwardingTargetFields(0, 0)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 1)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 2)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 3)).contains(0);
        assertThat(dsp.getForwardingTargetFields(0, 4)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 5)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(0, 6)).contains(3);
        assertThat(dsp.getForwardingTargetFields(1, 0)).contains(2);
        assertThat(dsp.getForwardingTargetFields(1, 1)).contains(1);
        assertThat(dsp.getForwardingTargetFields(1, 2)).isEmpty();
        assertThat(dsp.getForwardingTargetFields(1, 3)).contains(5);
    }