Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exceptions during ci-test #2539

Closed
bobjacobsen opened this issue Nov 18, 2016 · 4 comments
Closed

Exceptions during ci-test #2539

bobjacobsen opened this issue Nov 18, 2016 · 4 comments
Assignees
Labels

Comments

@bobjacobsen
Copy link
Member

Routinely seeing some exceptions when running "ant ci-test":

   [junit] WARN  - Error loading JoalAudioBuffer: java.io.FileNotFoundException: /Users/jake/Documents/Trains/JMRI/projects/JMRI/resources/sounds/vsd/null (No such file or directory) [main] jmri.jmrit.audio.JoalAudioBuffer.loadBuffer()
   [junit] WARN  - Error loading JoalAudioBuffer: java.io.FileNotFoundException: /Users/jake/Documents/Trains/JMRI/projects/JMRI/resources/sounds/vsd/null (No such file or directory) [main] jmri.jmrit.audio.JoalAudioBuffer.loadBuffer()
   [junit] WARN  - Error loading JoalAudioBuffer: java.io.FileNotFoundException: /Users/jake/Documents/Trains/JMRI/projects/JMRI/resources/sounds/vsd/null (No such file or directory) [main] jmri.jmrit.audio.JoalAudioBuffer.?()
   [junit] WARN  - Error loading JoalAudioBuffer: java.io.FileNotFoundException: /Users/jake/Documents/Trains/JMRI/projects/JMRI/resources/sounds/vsd/null (No such file or directory) [main] jmri.jmrit.audio.JoalAudioBuffer.?()
   [junit] WARN  - Error loading JoalAudioBuffer: java.io.FileNotFoundException: /Users/jake/Documents/Trains/JMRI/projects/JMRI/resources/sounds/vsd/null (No such file or directory) [main] jmri.jmrit.audio.JoalAudioBuffer.?()

There might be a couple things going on here.

resources/sounds/vsd doesn’t exist as a valid directory. Git sometimes acts oddly with empty directories, so maybe something went wrong if/when somebody added it. Haven’t done any research on that, although have noticed that it wasn’t present in SVN either.

jmri.jmrit.vsdecoder.SoundBiteTest mentions a test.wav filename. It doesn’t seem to exist, but it’s not clear that the test intended to open it.

Still, SoundBite does seem to be the cause. A typical traceback looks like:

java.io.FileNotFoundException: /Users/jake/Documents/Trains/JMRI/projects/JMRI/resources/sounds/vsd/null (No such file or directory)
	at com.jogamp.openal.util.ALut.alutLoadWAVFile(ALut.java:120)
	at jmri.jmrit.audio.JoalAudioBuffer.loadBuffer(JoalAudioBuffer.java:233)
	at jmri.jmrit.audio.AbstractAudioBuffer.setURL(AbstractAudioBuffer.java:113)
	at jmri.jmrit.vsdecoder.SoundBite.init(SoundBite.java:103)
	at jmri.jmrit.vsdecoder.SoundBite.<init>(SoundBite.java:59)
	at jmri.jmrit.vsdecoder.SoundBite.<init>(SoundBite.java:49)
	at jmri.jmrit.vsdecoder.SoundBiteTest.TestSetGet(SoundBiteTest.java:43)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

That particular test line is:

        SoundBite uut = new SoundBite(“unitUnderTest”);

Have to drop this now to go to day job, can pick up again tomorrow, but my current hypothesis is that SoundBit is pressing on to ask for a AudioBuffer with a source name set to null, which some toString operation changes to “null”, and the stuff happens. Those might just be tests without proper setup.

@bobjacobsen bobjacobsen self-assigned this Nov 18, 2016
@mattharris
Copy link
Member

@bobjacobsen From a quick look, the problem may be related to the following:

https://github.com/JMRI/JMRI/blob/master/java/src/jmri/jmrit/vsdecoder/VSDSound.java#L35

That line seems to define the base pathname wrongly.

@bobjacobsen bobjacobsen added the Bug label Jan 2, 2017
@bobjacobsen
Copy link
Member Author

I think the code in this area is basically broken, and the test is actually point that out. The VSDSountTest test invokes a valid SoundBite constructor:

VSDSound uut = new SoundBite("unitUnderTest");

That's this code in SoundBite:

    public SoundBite(String name) {
        this(name, BufferMode.BOUND_MODE);
    }

Note that this is a constructor: It's supposed to work always. The this(..) invocation goes to:

    // Constructor to replace QueueSoundBite, really.
    public SoundBite(String name, BufferMode mode) {
        super(name);
        this.filename = null;
        system_name = VSDSound.SrcSysNamePrefix + name;
        user_name = VSDSound.SrcUserNamePrefix + name;
        bufferMode = mode;
        initialized = init(null, mode);
    }

which specifies that filename is null, and then invokes init(...). That in turn is:

    public final boolean init(VSDFile vf, BufferMode mode) {
        AudioManager am = jmri.InstanceManager.getDefault(jmri.AudioManager.class);
        if (!initialized) {
            try {
                sound_src = (AudioSource) am.provideAudio(SrcSysNamePrefix + system_name);
                sound_src.setUserName(BufUserNamePrefix + user_name);
                setLooped(false);
                if (mode == BufferMode.BOUND_MODE) {
                    sound_buf = (AudioBuffer) am.provideAudio(BufSysNamePrefix + system_name);
                    sound_buf.setUserName(BufUserNamePrefix + user_name);
                    if (vf == null) {
                        sound_buf.setURL(vsd_file_base + filename);
                    } else {
                        java.io.InputStream ins = vf.getInputStream(filename);
                        if (ins != null) {
                            sound_buf.setInputStream(ins);
                        } else {
                            return (false);
                        }
                    }
                    sound_src.setAssignedBuffer(sound_buf);
                    setLength();
                }
            } catch (AudioException | IllegalArgumentException ex) {
                log.warn("Problem creating SoundBite: " + ex);
            }
        }
        return (true);
    }

which will invoke (because vf was null from the call chain):

                        sound_buf.setURL(vsd_file_base + filename);

The + operator is a String operation, so the null becomes "null" and is appended.

This just seems wrong. Very wrong. We've got a constructor, which is supposed to always work, which requires a filename in order to operate properly, but there's no way to get that filename into that constructor.

@klk32003
Copy link
Contributor

klk32003 commented Feb 2, 2017

@bobjacobsen Thanks for your explanations. This helped me to do some tests.

I inserted an IF-statement in the second constructor. This would solve the issue with the filename:

// Constructor to replace QueueSoundBite, really.
public SoundBite(String name, BufferMode mode) {
	super(name);
	system_name = VSDSound.SrcSysNamePrefix + name;
	user_name = VSDSound.SrcUserNamePrefix + name;
	bufferMode = mode;
	if (bufferMode == BufferMode.BOUND_MODE) {
		this.filename = name;
	} else {
		this.filename = null;
	}
	initialized = init(null, mode);
}

Note:
You can choose between QUEUE_MODE and BOUND_MODE when creating a new SoundBite. QUEUE_MODE allows queueing filled buffers to a SoundBite after its creation. A filename or VSD file at creation time is not needed!
A new SoundBite created in BOUND_MODE will include a buffer loaded with the WAV file. This needs a VSD filename and a WAV filename. Or at least a WAV filename, when the one-parameter-constructor in SoundBite.java is used.

Next minor issue is the correct folder for the test file "test.wav". @mattharris was right pointing on this.
The test file must be present in folder vsd_file_base (it's in folder "program/java/test/jmri/jmrit/vsdecoder" for now).
vsd_file_base is defined here, as already mentioned above: https://github.com/JMRI/JMRI/blob/master/java/src/jmri/jmrit/vsdecoder/VSDSound.java#L35 (new value since 5e0e665).
An open point is the missing separator "/" between folder and filename. Could be added in #L35 or in SoundBite.java or when new SoundBite is called, e.g. "/test.wav".

Last point is the correct setup of the test class, e.g. SoundBiteTest.testCreateSimple():

@Test
public void testCreateSimple() {
	SoundBite uut = new SoundBite("test.wav");
	Assert.assertEquals("sound name", "test.wav", uut.getName());
	Assert.assertFalse("is playing", uut.isPlaying());
}

Run the test with: ant test-single -Dtest.includes=jmri.jmrit.vsdecoder.SoundBiteTest.
I'm new on JUnit tests. Not sure if my setup for VSDSoundTest and SoundBiteTest is correct.

Sorry, got very long.

bobjacobsen added a commit that referenced this issue Feb 2, 2017
@bobjacobsen
Copy link
Member Author

@klk32003 Thanks! This seems to be fixed now with #3019. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants