Project

General

Profile

Bug #10174

Method/Procedure call overwrites procedure return value

Added by Teodor Gorghe about 1 year ago. Updated about 1 year ago.

Status:
Test
Priority:
Normal
Assignee:
Target version:
-
Start date:
Due date:
% Done:

100%

billable:
No
vendor_id:
GCD
case_num:
version_reported:
version_resolved:
production:
No
env_name:
topics:

History

#1 Updated by Teodor Gorghe about 1 year ago

We have this testcase, which on OE pass and on FWD fail:
  • TestNestedReturn.cls
    USING OpenEdge.Core.Assert FROM PROPATH.
    
    BLOCK-LEVEL ON ERROR UNDO, THROW.
    
    CLASS tests.blocklevel.TestNestedReturn:
        @TEST.
        METHOD PUBLIC VOID TestNestedProcedure():
            RUN tests/blocklevel/p-nested-procedure.p.
            Assert:Equals("asdasdas", RETURN-VALUE).
        END METHOD.
    END CLASS.
    
  • p-nested-procedure.p
    PROCEDURE nested-procedure:
        RETURN "asdasdas".
        FINALLY:
            tests.blocklevel.DummyClass:call1().
        END FINALLY.
    END PROCEDURE.
    
    RUN nested-procedure.
    RETURN RETURN-VALUE.
    
  • DummyClass.cls
    CLASS tests.blocklevel.DummyClass:
        METHOD PUBLIC STATIC VOID call1():
            RETURN.
        END METHOD.
    END CLASS.
    

On FWD, on DummyClass:call1 overwrites the return value from nested-procedure and in this case, we end up with "" as return value from RUN tests/blocklevel/p-nested-procedure.p. in TestNestedProcedure test. The Assert fails because "asdasdas" is not equal with "".

#3 Updated by Teodor Gorghe about 1 year ago

I have done some more investigation of this strange behavior.
  • It is normal on 4GL to change the return of a procedure from a FINNALY block when there are other procedure calls that use RETURN statement.
  • 4GL does not change procedure RETURN-VALUE on a RETURN statement in a method that return void, but FWD changes it. On non-void methods, FWD does not change the RETURN-VALUE.

The cause of this problem:

#4 Updated by Greg Shah about 1 year ago

I was told (many years ago) by someone at Progress, that they implemented OO methods in this way:

  • If the method returns VOID, then it is treated as an internal procedure.
  • If the method has a return value, then it is treated as a function.

This is why we map things as we do (e.g. to BlockManager.internalProcedure() for a void method). In this case, we should just ignore the RETURN TRUE. statement. But we don't fully ignore it.

Please check if a non-OO true internal procedure case also has this bug in FWD.

#5 Updated by Teodor Gorghe about 1 year ago

On OpenEdge, when using a true non-OO true internal procedure, the RETURN statement will write the RETURN-VALUE attribute. This also happens in FWD, this is not a problem here.
When using OE OO void method, the only valid statement is RETURN., which does not write "" into RETURN-VALUE attribute.

#6 Updated by Constantin Asofiei about 1 year ago

Teodor, is this about the FINALLY block? You can test this without OO.

#7 Updated by Teodor Gorghe about 1 year ago

Constantin Asofiei wrote:

Teodor, is this about the FINALLY block? You can test this without OO.

Yes, I have tested without OO, it does write RETURN-VALUE attribute when using non-OO internal/external procedures. It works OK on FWD and OE.
  • p-nested-procedure.p
    PROCEDURE nested-procedure:
        RETURN "asdasdas".
        FINALLY:
            RUN p-return.
        END FINALLY.
    END PROCEDURE.
    
    RUN nested-procedure.
    RETURN RETURN-VALUE.
    /* The return value is "" */
    
  • TestNestedReturn.cls
    USING OpenEdge.Core.Assert FROM PROPATH.
    
    BLOCK-LEVEL ON ERROR UNDO, THROW.
    
    CLASS TestNestedReturn:
        @TEST.
        METHOD PUBLIC VOID TestNestedProcedure():
            RUN p-nested-procedure.p.
            Assert:Equals("", RETURN-VALUE).
        END METHOD.
    END CLASS.
    
  • p-return.p
    RETURN.
    

#8 Updated by Teodor Gorghe about 1 year ago

  • Status changed from New to WIP

Created task branch 10174a

#9 Updated by Teodor Gorghe about 1 year ago

  • Status changed from WIP to Review
  • Assignee set to Teodor Gorghe
  • % Done changed from 0 to 100

Commited revision 15990 in task branch 10174a:
- fix for RETURN statement in OO void method.

#10 Updated by Constantin Asofiei about 1 year ago

  • Status changed from Review to Internal Test

I'm OK with the change.

#11 Updated by Teodor Gorghe about 1 year ago

  • Status changed from Internal Test to WIP
  • % Done changed from 100 to 70

There are some issues with testing. Danut told me that there is a big regression in a customer application. I need to analyze this a little bit more in the depth.

#12 Updated by Teodor Gorghe about 1 year ago

Committed revision 15991 on task branch 10174a:
- fixed regression when using BlockManager.returnNormal.

#13 Updated by Teodor Gorghe about 1 year ago

  • Status changed from WIP to Internal Test

#14 Updated by Teodor Gorghe about 1 year ago

Danut and Lorian told to me that now the tests passes. I have done some smoke tests and some harness tests on two customer apps and it seems OK now.

#15 Updated by Constantin Asofiei about 1 year ago

rtype ReturnType.STORE should match also on rtype ReturnType.NORMAL. Was rtype != ReturnType.ERROR matching on CONSUME also? Because as it is now it doesn't look right to me.

#16 Updated by Teodor Gorghe about 1 year ago

Constantin Asofiei wrote:

rtype ReturnType.STORE should match also on rtype ReturnType.NORMAL. Was rtype != ReturnType.ERROR matching on CONSUME also? Because as it is now it doesn't look right to me.

I am investigating this right now.
There were some regressions and I have just put rtype == ReturnType.STORE because the test that I found uses storeReturnValue. I am looking for the cases where returnNormal and returnConsume is used and test them on 4GL.

#17 Updated by Teodor Gorghe about 1 year ago

  • Status changed from Internal Test to Review

Committed revision 15992 on task branch 10174a:
- Addressed code review from #10174-15: returnNormal and returnConsume should not modify the RETURN-VALUE when they are used on a OO void method. The regression of the revision 15990: when rtype was NORMAL and CONSUME, the exception should have been thrown.

#18 Updated by Constantin Asofiei about 1 year ago

There is also this for CONSUME:

               if (rtype == ReturnType.CONSUME && isPersistentTriggerTopLevel(wa))
               {
                  LogicalTerminal.consumeEvent();
               }

#19 Updated by Teodor Gorghe about 1 year ago

Committed revision 15993 on task branch 10174a:
- Addressed code review #10174-18: moved the if condition, so the LogicalTerminal.consumeEvent() can get executed on ReturnType.CONSUME.

#20 Updated by Constantin Asofiei about 1 year ago

  • Status changed from Review to Internal Test

Teodor Gorghe wrote:

Committed revision 15993 on task branch 10174a:
- Addressed code review #10174-18: moved the if condition, so the LogicalTerminal.consumeEvent() can get executed on ReturnType.CONSUME.

Looks good. Please go with testing.

#21 Updated by Constantin Asofiei about 1 year ago

  • Status changed from Internal Test to Merge Pending

Please merge now.

#22 Updated by Teodor Gorghe about 1 year ago

  • Status changed from Merge Pending to Test
  • % Done changed from 70 to 100

Branch 10174a was merged to trunk rev 16025 and archived.

Also available in: Atom PDF