osate / osate2

Open Source AADL2 Tool Environment
http://osate.org
Eclipse Public License 2.0
39 stars 8 forks source link

Error message on connection when starting a flow source implementation with a data subcomponent #1987

Closed AaronGreenhouse closed 5 years ago

AaronGreenhouse commented 5 years ago

Summary

AADL allows a flow source implementation to begin with a data subcomponent. However, the current OSATE implementation gives an error on the subsequent connection in the flow implementation when you try to do this.

Expected and Current Behavior

The expected behavior is that there should not be an error reported on the declarative model. In actuality there is an error of the form

The source of connection _connectionid does not match the preceding subcomponent _subcomponentid

Interestingly, there is no analogous error when ending a flow sink implementation at a data subcomponent.

Steps to Reproduce

Consider the example

package DataTest
public
    data D

    end D;

    thread T
        features
            output: out data port D;
        flows
            fsrc: flow source output;
    end T;

    thread implementation T.i
        subcomponents
            myData: data D;
        connections
            c: port myData -> output;
        flows
            fsrc: flow source myData -> c -> output;
    end T.i;

    thread TT
        features
            input: in data port D;
        flows 
            fsnk: flow sink input;
    end TT;

    thread implementation TT.i
        subcomponents
            myData: data D;
        connections
            c: port input -> myData;
        flows
            fsnk: flow sink input -> c -> myData;
    end TT.i;
end DataTest;

OSATE will show an error marker on the connection identifier c in the flow source implementation fsrc of T.i. The error is

The source of connection 'c' does not match the preceding subcomponent 'myData'

Interestingly there is no similar error in the flow sink implementation fsnk of TT.i.

The error comes from Aadl2JavaValidator.checkFlowConnectionEnds(). In this case, the source of the connection is the data subcomponent but the connection source context is null. It seems like the method is not considering this case, but instead expects the connection source to be a feature of a subprogram?

AaronGreenhouse commented 5 years ago

I get source and destination errors in an end to flow destination in the following example:

package EndToEndFlowData
public
    data D
        -- empty        
    end D;

    data E
        -- empty
    end E;

    thread T
        features
            input: in data port D;
            output: out data port E;
        flows
            fpath: flow path input -> output;
    end T;

    process P
        -- empty
    end P;

    process implementation P.top
        subcomponents
            dataD: data D;
            dataE: data E;
            threadT: thread T;
        connections
            c1: port dataD -> threadT.input;
            c2: port threadT.output -> dataE;
        flows
            e2e: end to end flow dataD -> c1 -> threadT.fpath -> c2 -> dataE;
    end P.top;
end EndToEndFlowData;

Here I get errors on c1 and c2 in the end to end flow e2e:

The destination of connection 'c2' does not match the succeeding subcomponent or in flow spec feature 'dataE'

The source of connection 'c1' does not match the preceding subcomponent or out flow spec feature 'dataD'

AaronGreenhouse commented 5 years ago

After some time in the debugger, I have found that the flow sink case in DataTest::TT.i (the first example above) does indeed report an error. Or at least it tries to. But because it tries to dereference the cxt of the connection, which is null, it causes an exception instead. Not sure where this exception gets logged or swallowed. But if I remove the use of cxt in the error message, it gets reported on the model.

Of course the problem here is that we shouldn't be reporting an error in this case and we should be checking that cxt is null as part of the filter.

I feel better knowing it's trying to report an error because it didn't make sense that the flow source and flow sink cases would be handled differently.

AaronGreenhouse commented 5 years ago

The case is missing appropriate error checking too, I think. I think I need to add checks in this case that the named data component in the connection is the same as the one in the flow.

AaronGreenhouse commented 5 years ago

The code for checking connections vs. subcomponents in flows is in method checkFlowConnectionEnds() in Aadl2JavaValidator around line 1511 (for the case of subcomponent -> connection):

                        if (prevFlowElement != cxt && !(cxt instanceof SubprogramCall
                                && ((SubprogramCall) cxt).getCalledSubprogram() == prevFlowElement)) {
                            error(flow.getOwnedFlowSegments().get(i),
                                    "The source of connection '" + connection.getName()
                                            + "' does not match the preceding subcomponent '"
                                            + ((Subcomponent) prevFlowElement).getName() + '\'');
                        }

(The source code for checking connection -> subcomponent) is similar around line 1567.)

But this doesn't work. The first part checks if prevFlowElement and cxt are equal. I think this is supposed to be handling the case of data subcomponents. But this doesn't work because cxt is null in the case.

The other part is trying to deal the case of the connection being a parameter connection, but it has other problems. If I try to make an example that creates a flow from a subprogram, it doesn't work (which I think we already have an issue for):

    data D
    end D;

    subprogram SP
        features
            p1: in out parameter D; 
    end SP;

    thread T
        features
            output: out data port D;
        flows
            fsrc: flow source output;
    end T;

    thread implementation T.i
        subcomponents
            myData: data D;
        calls
            q: {
                call1: subprogram SP;
            };
        connections
            c: parameter call1.p1 -> output;
        flows
            fsrc: flow source call1 -> c -> output;
    end T.i;

Looking at flow source fsrc in T.i, I get an error on call1

Couldn't resolve reference to FlowElement 'call1'.

If I change it to sp (which seems to be what the above code is trying to require), that also doesn't resolve.

AaronGreenhouse commented 5 years ago

Fixed checkFlowConnectionEnds(FlowImplementation).

Still need to fix checkFlowConnectionEnds(EndToEndFlow)

AaronGreenhouse commented 5 years ago

Fixed checkFlowConnectionEnds(EndToEndFlow) by updating getConnectionSubcomponent() to not check if the connection is an Access connection, and just check if the connection context is null.

Still need unit tests

AaronGreenhouse commented 5 years ago

Added Unit tests