Date   

Re: Review request of #9098 - Refactor OBlock to use an enum instead of maps

danielb987
 

Steve

An enum class cannot extend another enum class. But you can simulate that behaviure. In LogixNG, I have an "enum" that I want to be extendable:

https://github.com/danielb987/JMRI/blob/LogixNG_new2_48/java/src/jmri/jmrit/logixng/Category.java

This enum has no method valueOf(String name) but you can easily add that since the class has a list of registered categories.

It would probably be good to add support for @ServiceProvider for this class so that other Categories can register themselves automatically.

Daniel

2020-10-24 15:29 skrev steve young via groups.io:

Hi Daniel,
Makes a lot of sense to use Enums.
One future project I'd like to look at would be to add Error reporting
status etc. to LE blocks.
The "alternativeColor" field is primarily used for allocation, so
can't be used for track reporting errors / track power shorts.
If / when I take that particular project on ( and I'd like to as I'm
slowly building a physical NX-style panel ), I'd prefer NOT to use
Logix / Jython ) for Allocation / track error status as in
https://groups.io/g/jmriusers/topic/block_alternate_colour_as/77362802
, this really should be selectable with a user interface!
eg. for Light Controllers, there shouldn't be 2 select dropdowns to
select allocated status ( one for OBlocks and one for
LayoutEditorBlocks. ) when imho this is a fundamental block level
property.
I was thinking along the lines of this sort of enum class being at
Block level rather than OBlock level, however when I do look at this,
the OBlock status enum would extend the Block status enum so there
wouldn't need to be changes within OBlocks themselves.
Again, this is just to give an indication of where I might head in
future with block status, definitely not a blocker or request for
change to this PR which I think is a good step forward,
Steve.
Links:
------
[1] https://jmri-developers.groups.io/g/jmri/message/4467
[2] https://groups.io/mt/77748998/1303822
[3] https://jmri-developers.groups.io/g/jmri/post
[4] https://jmri-developers.groups.io/g/jmri/editsub/1303822
[5] https://jmri-developers.groups.io/g/jmri/leave/defanged


Re: Review request of #9098 - Refactor OBlock to use an enum instead of maps

steve young
 

Hi Daniel,

Makes a lot of sense to use Enums.

One future project I'd like to look at would be to add Error reporting status etc. to LE blocks.
The "alternativeColor" field is primarily used for allocation, so can't be used for track reporting errors / track power shorts.

If / when I take that particular project on ( and I'd like to as I'm slowly building a physical NX-style panel ), I'd prefer NOT to use Logix / Jython ) for Allocation / track error status as in https://groups.io/g/jmriusers/topic/block_alternate_colour_as/77362802 , this really should be selectable with a user interface!

eg. for Light Controllers, there shouldn't be 2 select dropdowns to select allocated status ( one for OBlocks and one for LayoutEditorBlocks. ) when imho this is a fundamental block level property.

I was thinking along the lines of this sort of enum class being at Block level rather than OBlock level, however when I do look at this, the OBlock status enum would extend the Block status enum so there wouldn't need to be changes within OBlocks themselves.

Again, this is just to give an indication of where I might head in future with block status, definitely not a blocker or request for change to this PR which I think is a good step forward,

Steve.


Re: splitVal, should max="#" be applied just to the split part?

Dave Heap
 

Egbert,

On 24 Oct 2020, at 7:34 PM, Egbert Broerse <@silverailscolo> wrote:

For the more accessible JMRI Help pages on decoders, I now suggest adding a short xml snippet example showing multiple CVs in the first line, and if we agree the one style is to be preferred over the other looking to the future, add it as a “good” example to the web decoder help as well.
I can write it up, please confirm we agree to describe it as “preferred” indeed.
There's not a "one size fits all" preferred method.

For noncontiguous CVs (such as accessory decoder addresses) the comma-separated form is (with your new mask form) is really the only appropriate one. The old "highCV" and "upperMask" form should not be recommended and we should be steering people away from them.

For contiguous CVs, particularly text fields (splitTextVal) where there may be tens of CVs (e.g. ESU decoders with a text field of 28 CVs), the comma-separated form is inappropriate. In that case the colon followed by a count is most appropriate.

The web help page already has an XML fragment for the colon-count form. I'd suggest we add an XML fragment for the comma-separated form, combined with your new mask style to replace the existing "long address over 2 CVs" example on the web page.

Obviously we need to fix the currently-broken link (it did work has been broken by some web update) to the comprehensive JavaDoc page, pointing out that there are other variant forms available.

I don't think the in-app JMRI help pages are an appropriate place for decoder definition documentation. Anyone writing definitions should be steered to the web decoder help. You don't write definitions within DecoderPro or PanelPro, you do that with a text editor or GitHub desktop/web or an IDE.

Maybe I'm misunderstanding you and it's getting late here now...

Dave


Re: splitVal, should max="#" be applied just to the split part?

Egbert Broerse
 

Dave,
At the time I was happy to find descriptions for the different formats to enter expanding ranges in the javadoc all right, thanks.
 
For the more accessible JMRI Help pages on decoders, I now suggest adding a short xml snippet example showing multiple CVs in the first line, and if we agree the one style is to be preferred over the other looking to the future, add it as a “good” example to the web decoder help as well.
I can write it up, please confirm we agree to describe it as “preferred” indeed.
 
Egbert


Review request of #9098 - Refactor OBlock to use an enum instead of maps

danielb987
 

When adding support of OBlock to LogixNG, I need to handle the different statuses that an oblock can have. And it's more reliable if it's handled by an enum than of constant strings.

This PR adds an enum to OBlock to get an easy way to get the list of statuses that an oblock can have, and it changes the methods getLocalStatusName(), getSystemStatusName() and statusIs() to use this enum.

I added some tests for these three methods before I added the enum to ensure that the change doesn't break anything.

Daniel


Re: Compiling and running JMRI from Eclipse

Jan Boen
 

Hi,


Running on Windows 10, 8 GB of ram, SSD, latest versions.

Compiling itself seems OK.

Just when starting JMRI it freezese and the message is related to some null pointer exception with Logix.


Best regards,


Jan

On 22/10/2020 18:37, rodneyblack2000 via groups.io wrote:
Jan,

What platform (Windows, Mac, Linux) are you using?  I will assume that you read the paragraph on building JMRI with Eclipse on the JMRI web site (https://www.jmri.org/help/en/html/doc/Technical/Eclipse.shtml).  I have built it on both Windows (Eclipse 2020-09) and Linux (I think 2020-09).  Both were a pain.  Be sure to watch carefully for the results of the compile.  For Linux, I had to increase the Ant heap size.  The compiles would fail until I did that.  I will post what I did, if that is the problem you are seeing.  With JMRI 4.20, I had to increase it on Windows, as well.  In addition, I did the "Run As" then "2 Ant Build" from the instructions, then used the Eclipse clean, followed by an Eclipse build.  That worked.  Every time that I pull down a version and try to do a build from scratch, I have to try multiple "Run As" and Eclipse clean and builds to get something that runs and I always forget to write down the combination that worked.

Rodney


Re: Compiling and running JMRI from Eclipse

rodneyblack2000
 

Jan,

What platform (Windows, Mac, Linux) are you using?  I will assume that you read the paragraph on building JMRI with Eclipse on the JMRI web site (https://www.jmri.org/help/en/html/doc/Technical/Eclipse.shtml).  I have built it on both Windows (Eclipse 2020-09) and Linux (I think 2020-09).  Both were a pain.  Be sure to watch carefully for the results of the compile.  For Linux, I had to increase the Ant heap size.  The compiles would fail until I did that.  I will post what I did, if that is the problem you are seeing.  With JMRI 4.20, I had to increase it on Windows, as well.  In addition, I did the "Run As" then "2 Ant Build" from the instructions, then used the Eclipse clean, followed by an Eclipse build.  That worked.  Every time that I pull down a version and try to do a build from scratch, I have to try multiple "Run As" and Eclipse clean and builds to get something that runs and I always forget to write down the combination that worked.

Rodney


Re: splitVal, should max="#" be applied just to the split part?

Dave Heap
 

Egbert,

On 22 Oct 2020, at 9:25 PM, Dave Heap via groups.io <dgheap@...> wrote:

It seems the link to sample multiple-CV formats and expansions in expandCvList is broken. It should be:

The formats given at that link are parsed by multiple regexes and a composite version is used in the schema files to validate any uses in a decoder definition file.

Dave


Re: splitVal, should max="#" be applied just to the split part?

Dave Heap
 

Egbert,

On 22 Oct 2020, at 8:13 PM, Egbert Broerse <dcc2@...> wrote:

Apart from the requirement for 3 - different - masks for the LocoIO, the following note in the SplitValVariable javadoc convinced me to drop Splitval="" 

I see you've remedied the 3 or more masks situation, thanks.
BTW, the JMRI Advanced Decoder help page doesn't (yet) provide an example how to apply this preferred style. Will look at that.

It seems the link to sample multiple-CV formats and expansions in expandCvList is broken. It should be:
But it isn't.

Dave


Re: splitVal, should max="#" be applied just to the split part?

Egbert Broerse
 

Apart from the requirement for 3 - different - masks for the LocoIO, the following note in the SplitValVariable javadoc convinced me to drop Splitval="" 
BTW, the JMRI Advanced Decoder help page doesn't (yet) provide an example how to apply this preferred style. Will look at that.
Egbert
* The preferred technique is now to specify all CVs in the {@code CV} attribute
* alone, as documented at {@link CvUtil#expandCvList expandCvList(String)}.


Re: splitVal, should max="#" be applied just to the split part?

Dave Heap
 

Ken,

On 22 Oct 2020, at 12:33 PM, Ken Cameron <@KenC57> wrote:

The case is a number of the Team Digital decoder files. Many of them use the
following construct:

<variable CV="16" mask="VVVVVVVV" item="PA1" default="1">
<splitVal highCV="17" max="7" upperMask="XXXXVVVV"/>
<label>Address</label>
</variable>

From the revision dates I think it had things done before the other fixes so
is now have many problems. Given how things work now, what is the correct
way to do this? Obvious is the max="7" goes, but what else?
The max="7" goes because it has never worked that way. Prior to my changes, max was totally ignored. Now it applies to the whole variable, it has never applied to the highCV only. Simply removing it will return the definition to historic behaviour.

As it stands, the upperMask="XXXXVVVV" limits the highCV value to 15. If the designer really wants to limit the highCV value to 7, upperMask="XXXXXVVV" will do that.

Dave


Re: splitVal, should max="#" be applied just to the split part?

Ken Cameron
 

Dave H,

The case is a number of the Team Digital decoder files. Many of them use the
following construct:

<variable CV="16" mask="VVVVVVVV" item="PA1" default="1">
<splitVal highCV="17" max="7" upperMask="XXXXVVVV"/>
<label>Address</label>
</variable>

From the revision dates I think it had things done before the other fixes so
is now have many problems. Given how things work now, what is the correct
way to do this? Obvious is the max="7" goes, but what else?

-Ken Cameron, Member JMRI Dev Team
www.jmri.org
www.fingerlakeslivesteamers.org
www.cnymod.org
www.syracusemodelrr.org


Re: Compiling and running JMRI from Eclipse

Steve_G
 

Hi Jan
I would say the maven (mvn) compile/generate hadn't been run. Right click on the pom.xml and do a maven build. If it's messed up you might have to do a realclean first. 
Steve G.


Re: Code changes to Tams to get it to compile

danielb987
 

Hi,

Not sure, but it could be that you need something like:

return (TamsTurnoutManager) classObjectMap.computeIfAbsent(TurnoutManager.class, Class<? extends NamedBean> c) -> { return new TamsTurnoutManager(this); });

or

return (TamsTurnoutManager) classObjectMap.computeIfAbsent(TurnoutManager.class, Class<? extends Manager> c) -> { return new TamsTurnoutManager(this); });

Both Manager and NamedBean are in package jmri, so you might need:
import jmri.NamedBean;
or
import jmri.Manager;

But if you get this problem, you might get this problem in a lot of other places. So it may be that some check are too tight. But I don't use Eclipse so I don't know.

Daniel

2020-10-21 19:59 skrev Jan Boen:

Hi all,
The Tams code was just working fine up to now.
In the new environment I got warnings thrown related to"rawtypes")
Class c
public TamsTurnoutManager getTurnoutManager() {
return (TamsTurnoutManager)
classObjectMap.computeIfAbsent(TurnoutManager.class,
(@SuppressWarnings("rawtypes") Class c) -> { return new
TamsTurnoutManager(this); });
}
also had to add an override here I think
@Override
public <B extends NamedBean> Comparator<B>
getNamedBeanComparator(Class<B> type) {
return new NamedBeanComparator<>();
}
Now all compiles OK.
Any idea why that is?
Thanks,
Jan
Links:
------
[1] https://jmri-developers.groups.io/g/jmri/message/4452
[2] https://groups.io/mt/77710826/1303822
[3] https://jmri-developers.groups.io/g/jmri/post
[4] https://jmri-developers.groups.io/g/jmri/editsub/1303822
[5] https://jmri-developers.groups.io/g/jmri/leave/defanged


Re: splitVal, should max="#" be applied just to the split part?

Dave Heap
 

Ken

On 22 Oct 2020, at 5:16 AM, Ken Cameron <@KenC57> wrote:

Decoder is using a 12 bit value and a max="7" was on the splitVal line
inside the variable. The max is being taken for the whole 12 bit value. Is
that the right way it should work?
That is correct and many definitions rely it applying to the whole user-entered field value, as do all other variable types (to the best of my knowledge).

I think the original was trying to limit
the nibble to a value of 7. Yes if it was really using a full nibble, then
the max should have been 15. I'm just investigating for others.
The original should have used something like:
mask="XXXXXVVV" uppermask="VVVVVVVV"
or the (new alternative)
mask="XXXXXVVV VVVVVVVV"
(Note that simply entering mask="XXXXXVVV" applies that mask to all CVs.)

I don't think max="nn" has ever applied to solely the first CV. It was totally ignored in the last version (16/9/2018) before I introduced the new splitVal.

In the new splitVal I accidentally introduced an invalid form that defaulted max to 256 and was limited to 32,767 (signed 16 bit integer). It applied to the entered (parsed text) field value, never to individual CVs

On 19/6/2019 I temporarily removed the invalid form, after the problem had been reported by users/developers.

On 10/9/2019 I reintroduced a corrected form, which used unsigned long values and comparisons, with default min of 0 and max of the largest unsigned long.

Dave


splitVal, should max="#" be applied just to the split part?

Ken Cameron
 

Decoder is using a 12 bit value and a max="7" was on the splitVal line
inside the variable. The max is being taken for the whole 12 bit value. Is
that the right way it should work? I think the original was trying to limit
the nibble to a value of 7. Yes if it was really using a full nibble, then
the max should have been 15. I'm just investigating for others.

-Ken Cameron, Member JMRI Dev Team
www.jmri.org
www.fingerlakeslivesteamers.org
www.cnymod.org
www.syracusemodelrr.org


Code changes to Tams to get it to compile

Jan Boen
 

Hi all,

The Tams code was just working fine up to now.
In the new environment I got warnings thrown related to"rawtypes") Class c
    public TamsTurnoutManager getTurnoutManager() {
        return (TamsTurnoutManager) classObjectMap.computeIfAbsent(TurnoutManager.class, (@SuppressWarnings("rawtypes") Class c) -> { return new TamsTurnoutManager(this); });
    }
also had to add an override here I think
    @Override
    public <B extends NamedBean> Comparator<B> getNamedBeanComparator(Class<B> type) {
        return new NamedBeanComparator<>();
    }

Now all compiles OK.
Any idea why that is?

Thanks,


Jan


Compiling and running JMRI from Eclipse

Jan Boen
 

Hi all,

I have Eclipse 2020-09 with JMRI in it.
Compiling seems to work.
When I start JMRI from Eclipse it goes up to the point where I select the configuration and then it stops.
This is the debug output:
-normal-jmri-application:
     [echo] Launch normally (no debugger support)
     [java] 2020-10-21 19:49:25,786 util.Log4JUtil                        INFO  - ****** JMRI log ******* [main]
     [java] 2020-10-21 19:49:25,815 util.Log4JUtil                        INFO  - This log is appended to file: C:\Users\Kiwanis\JMRI\log\messages.log [main]
     [java] 2020-10-21 19:49:25,816 util.Log4JUtil                        INFO  - This log is stored in file: C:\Users\Kiwanis\JMRI\log\session.log [main]
     [java] 2020-10-21 19:49:25,833 apps.Apps                             INFO  - PanelPro version 4.21.3ish+Kiwanis+2020-10-21T17:49:17Z starts under Java 15.0.1 on Windows 10 amd64 v10.0 at Wed Oct 21 19:49:25 CEST 2020 [main]
     [java] 2020-10-21 19:49:29,436 apps.Apps                             INFO  - Starting with profile test.3e4bf981 [main]
     [java] 2020-10-21 19:49:29,478 util.ThreadingUtil                    ERROR - Error while on GUI thread [main]
     [java] java.lang.NullPointerException: Required nonnull default for jmri.UserPreferencesManager does not exist.
     [java]     at jmri.InstanceManager.getDefault(InstanceManager.java:206)
     [java]     at apps.Apps.lambda$0(Apps.java:193)
     [java]     at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:306)
     [java]     at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
     [java]     at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
     [java]     at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
     [java]     at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
     [java]     at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
     [java]     at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
     [java]     at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
     [java]     at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
     [java]     at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
     [java]     at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
     [java]     at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
     [java]     at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
     [java] 2020-10-21 19:49:29,480 util.ThreadingUtil                    ERROR -    Came from call to runOnGUI: [main]
     [java] java.lang.reflect.InvocationTargetException
     [java]     at java.desktop/java.awt.EventQueue.invokeAndWait(EventQueue.java:1367)
     [java]     at java.desktop/java.awt.EventQueue.invokeAndWait(EventQueue.java:1342)
     [java]     at java.desktop/javax.swing.SwingUtilities.invokeAndWait(SwingUtilities.java:1480)
     [java]     at jmri.util.ThreadingUtil.runOnGUI(ThreadingUtil.java:116)
     [java]     at apps.Apps.<init>(Apps.java:192)
     [java]     at apps.PanelPro.PanelPro.<init>(PanelPro.java:40)
     [java]     at apps.PanelPro.PanelPro.main(PanelPro.java:120)
     [java] Caused by: java.lang.NullPointerException: Required nonnull default for jmri.UserPreferencesManager does not exist.
     [java]     at jmri.InstanceManager.getDefault(InstanceManager.java:206)
     [java]     at apps.Apps.lambda$0(Apps.java:193)
     [java]     at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:306)
     [java]     at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
     [java]     at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
     [java]     at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
     [java]     at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
     [java]     at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
     [java]     at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
     [java]     at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
     [java]     at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
     [java]     at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
     [java]     at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
     [java]     at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
     [java]     at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
     [java] 2020-10-21 19:49:29,481 apps.Apps                             INFO  - No saved preferences, will open preferences window.  Searched for C:\Users\Kiwanis\JMRI\test.jmri\ProfileConfig.xml [main]
     [java] 2020-10-21 19:49:29,482 util.FileUtilSupport                  INFO  - File path program: is C:\Users\Kiwanis\git\JMRI\ [main]
     [java] 2020-10-21 19:49:29,482 util.FileUtilSupport                  INFO  - File path preference: is C:\Users\Kiwanis\JMRI\test.jmri\ [main]
     [java] 2020-10-21 19:49:29,482 util.FileUtilSupport                  INFO  - File path profile: is C:\Users\Kiwanis\JMRI\test.jmri\ [main]
     [java] 2020-10-21 19:49:29,482 util.FileUtilSupport                  INFO  - File path settings: is C:\Users\Kiwanis\JMRI\ [main]
     [java] 2020-10-21 19:49:29,506 util.FileUtilSupport                  INFO  - File path home: is C:\Users\Kiwanis\ [main]
     [java] 2020-10-21 19:49:29,507 util.FileUtilSupport                  INFO  - File path scripts: is C:\Users\Kiwanis\git\JMRI\jython\ [main]
     [java] 2020-10-21 19:49:29,542 ptionhandler.UncaughtExceptionHandler ERROR - Uncaught Exception caught by jmri.util.exceptionhandler.UncaughtExceptionHandler [main]
     [java] java.lang.NullPointerException: Required nonnull default for jmri.LogixManager does not exist.
     [java]     at jmri.InstanceManager.getDefault(InstanceManager.java:206)
     [java]     at apps.Apps.<init>(Apps.java:304)
     [java]     at apps.PanelPro.PanelPro.<init>(PanelPro.java:40)
     [java]     at apps.PanelPro.PanelPro.main(PanelPro.java:120)

Any idea what is missing?

Thanks,

Jan


Re: Testing Serial Port Code

Andrew Crosland
 

I am out of my depth and will have to abandon enhancing the Serial Driver Adapter tests for now.

I think that the shutdown manager is not the cause of the problem. The TrafficController.terminateThreads() method de-registers the shutdown task but then the test fails with an NPE.

In GcSerialDriverAdapter
if (head == null || headOfs >= head.len) {
try {
head = readAhead.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (head.e != null) {

results in NPE on 'if (head.e...'

I think the previous take() is interrupted (maybe due to the stream becoming unavailable due to calling terminateThreads()) and head is null.

Andrew

------ Original Message ------
From: "danielb987" <db123@...>
To: jmri@jmri-developers.groups.io
Sent: 21/10/2020 03:11:52
Subject: Re: [jmri-developers] Testing Serial Port Code

Andrew,

There is a short section about the shutdown manager here:
https://www.jmri.org/help/en/html/doc/Technical/JUnit.shtml#ResetInstMgr

See the sub section "Working with a ShutDownManager".

You might use the method JUnitUtil.clearShutDownManager() to see if that solves the problem, but that should only be used temporary.

Daniel

2020-10-20 21:10 skrev Andrew Crosland:
Daniel,

Thanks, that helped a lot. I knew nothing about mocking.

I also need to call the configure() method in the serial driver
adapter after calling openPort().

I think my tests are now working but there's an error at the end of
the test run.

I've recreated this in GcSerialDriverAdapterTest:

ERROR - Test
jmri.jmrix.can.adapters.gridconnect.GcSerialDriverAdapterTest left
registered shutdown runnable of type class
jmri.jmrix.AbstractMRTrafficController$$Lambda$314/396842715 [main]
jmri.util.JUnitUtil.checkShutDownManager()
java.lang.Exception: traceback
at jmri.util.JUnitUtil.checkShutDownManager(JUnitUtil.java:1016)
at jmri.util.JUnitUtil.tearDown(JUnitUtil.java:286)
at
jmri.jmrix.can.adapters.gridconnect.GcSerialDriverAdapterTest.tearDown(GcSerialDriverAdapterTest.java:57)

I added a call the theTrafficControll.terminateThreads() method but
this results in a NPE.

ERROR - Exception in receive loop: java.lang.NullPointerException
[gridconnect.GcTrafficController Receive thread]
jmri.jmrix.AbstractMRTrafficController.receiveLoop()
java.lang.NullPointerException
at
jmri.jmrix.can.adapters.gridconnect.GcSerialDriverAdapter$AsyncBufferInputStream.read(GcSerialDriverAdapter.java:331)
at java.io.DataInputStream.read(DataInputStream.java:149)
at
jmri.jmrix.AbstractMRTrafficController.readByteProtected(AbstractMRTrafficController.java:957)
at
jmri.jmrix.can.adapters.gridconnect.GcTrafficController.loadChars(GcTrafficController.java:222)
at
jmri.jmrix.can.AbstractCanTrafficController.handleOneIncomingReply(AbstractCanTrafficController.java:207)
at
jmri.jmrix.AbstractMRTrafficController.receiveLoop(AbstractMRTrafficController.java:878)
at
jmri.jmrix.AbstractMRTrafficController$2.run(AbstractMRTrafficController.java:801)
at java.lang.Thread.run(Thread.java:748)

Unfortunately I am out of time again for the moment.

My branch is at https://github.com/crosland/JMRI/tree/sproggen5-mode-switcher
With my version of GcSerialDriverAdapterTest
https://github.com/crosland/JMRI/blob/sproggen5-mode-switcher/java/test/jmri/jmrix/can/adapters/gridconnect/GcSerialDriverAdapterTest.java

Andrew

------ Original Message ------
From: "danielb987" <db123@...>
To: jmri@jmri-developers.groups.io
Sent: 20/10/2020 00:57:03
Subject: Re: [jmri-developers] Testing Serial Port Code

I'm no expert in mocking things, but I was able to mock the serial port and open it.

I changed the code in GcSerialDriverAdapterTest and you can see my code in my branch:
https://github.com/danielb987/JMRI/tree/mock_serial_port

You can see my changes here:
https://github.com/JMRI/JMRI/compare/master...danielb987:mock_serial_port


The setUp() method creates a fake CommPortIdentifier instance that mocks the method open() to return my fake serial port.

The test method then creates a mock of the static method CommPortIdentifier.getPortIdentifier() to return the mocked CommPortIdentifier.

Feel free to do whatever you want with my code.

Daniel


2020-10-19 18:46 skrev Andrew Crosland:
I am struggling to write tests for code that expects to open hardware
connection, e.g., a COM port on Windows hardware.

I am struggling with the openPort() method in, e.g.,
GcSerialDriverAdapter.java. I have tried to override this in my tests,
but I don't know what to assign to activeSerialPort that will keep the
rest of the code happy.

I looked at GcSerialDriverAdapterTest.java but that has only a simple
constructor test.

I am trying to enhance the tests for various serial driver adapters
(e.g. CanSprogSerialDriverAdapter) that configure a sub-protocol. I
need to call configure() from my test and that wants to open the port.
I am aware of the traffic controller scaffold, if that is in any way
relevant, but in this case the traffic controller object is created in
configure().

Has anyone done this for any hardware type?

Is it too difficult?

Andrew
--
Andrew Crosland


Links:
------
[1] https://jmri-developers.groups.io/g/jmri/message/4444
[2] https://groups.io/mt/77662444/1303822
[3] https://jmri-developers.groups.io/g/jmri/post
[4] https://jmri-developers.groups.io/g/jmri/editsub/1303822
[5] https://jmri-developers.groups.io/g/jmri/leave/defanged








--
Andrew Crosland


Re: Testing Serial Port Code

danielb987
 

Andrew,

There is a short section about the shutdown manager here:
https://www.jmri.org/help/en/html/doc/Technical/JUnit.shtml#ResetInstMgr

See the sub section "Working with a ShutDownManager".

You might use the method JUnitUtil.clearShutDownManager() to see if that solves the problem, but that should only be used temporary.

Daniel

2020-10-20 21:10 skrev Andrew Crosland:

Daniel,
Thanks, that helped a lot. I knew nothing about mocking.
I also need to call the configure() method in the serial driver
adapter after calling openPort().
I think my tests are now working but there's an error at the end of
the test run.
I've recreated this in GcSerialDriverAdapterTest:
ERROR - Test
jmri.jmrix.can.adapters.gridconnect.GcSerialDriverAdapterTest left
registered shutdown runnable of type class
jmri.jmrix.AbstractMRTrafficController$$Lambda$314/396842715 [main]
jmri.util.JUnitUtil.checkShutDownManager()
java.lang.Exception: traceback
at jmri.util.JUnitUtil.checkShutDownManager(JUnitUtil.java:1016)
at jmri.util.JUnitUtil.tearDown(JUnitUtil.java:286)
at
jmri.jmrix.can.adapters.gridconnect.GcSerialDriverAdapterTest.tearDown(GcSerialDriverAdapterTest.java:57)
I added a call the theTrafficControll.terminateThreads() method but
this results in a NPE.
ERROR - Exception in receive loop: java.lang.NullPointerException
[gridconnect.GcTrafficController Receive thread]
jmri.jmrix.AbstractMRTrafficController.receiveLoop()
java.lang.NullPointerException
at
jmri.jmrix.can.adapters.gridconnect.GcSerialDriverAdapter$AsyncBufferInputStream.read(GcSerialDriverAdapter.java:331)
at java.io.DataInputStream.read(DataInputStream.java:149)
at
jmri.jmrix.AbstractMRTrafficController.readByteProtected(AbstractMRTrafficController.java:957)
at
jmri.jmrix.can.adapters.gridconnect.GcTrafficController.loadChars(GcTrafficController.java:222)
at
jmri.jmrix.can.AbstractCanTrafficController.handleOneIncomingReply(AbstractCanTrafficController.java:207)
at
jmri.jmrix.AbstractMRTrafficController.receiveLoop(AbstractMRTrafficController.java:878)
at
jmri.jmrix.AbstractMRTrafficController$2.run(AbstractMRTrafficController.java:801)
at java.lang.Thread.run(Thread.java:748)
Unfortunately I am out of time again for the moment.
My branch is at https://github.com/crosland/JMRI/tree/sproggen5-mode-switcher
With my version of GcSerialDriverAdapterTest
https://github.com/crosland/JMRI/blob/sproggen5-mode-switcher/java/test/jmri/jmrix/can/adapters/gridconnect/GcSerialDriverAdapterTest.java
Andrew
------ Original Message ------
From: "danielb987" <db123@...>
To: jmri@jmri-developers.groups.io
Sent: 20/10/2020 00:57:03
Subject: Re: [jmri-developers] Testing Serial Port Code

I'm no expert in mocking things, but I was able to mock the serial port and open it.
I changed the code in GcSerialDriverAdapterTest and you can see my code in my branch:
https://github.com/danielb987/JMRI/tree/mock_serial_port
You can see my changes here:
https://github.com/JMRI/JMRI/compare/master...danielb987:mock_serial_port
The setUp() method creates a fake CommPortIdentifier instance that mocks the method open() to return my fake serial port.
The test method then creates a mock of the static method CommPortIdentifier.getPortIdentifier() to return the mocked CommPortIdentifier.
Feel free to do whatever you want with my code.
Daniel
2020-10-19 18:46 skrev Andrew Crosland:
I am struggling to write tests for code that expects to open hardware
connection, e.g., a COM port on Windows hardware.
I am struggling with the openPort() method in, e.g.,
GcSerialDriverAdapter.java. I have tried to override this in my tests,
but I don't know what to assign to activeSerialPort that will keep the
rest of the code happy.
I looked at GcSerialDriverAdapterTest.java but that has only a simple
constructor test.
I am trying to enhance the tests for various serial driver adapters
(e.g. CanSprogSerialDriverAdapter) that configure a sub-protocol. I
need to call configure() from my test and that wants to open the port.
I am aware of the traffic controller scaffold, if that is in any way
relevant, but in this case the traffic controller object is created in
configure().
Has anyone done this for any hardware type?
Is it too difficult?
Andrew
--
Andrew Crosland
Links:
------
[1] https://jmri-developers.groups.io/g/jmri/message/4444
[2] https://groups.io/mt/77662444/1303822
[3] https://jmri-developers.groups.io/g/jmri/post
[4] https://jmri-developers.groups.io/g/jmri/editsub/1303822
[5] https://jmri-developers.groups.io/g/jmri/leave/defanged