Unit-testing of libgdx-using classes - java

I'm writing a game over libgdx; I'm using the junit framework to simplify unit-testing my code.
Now there's part of the code (a map generator, a class converting my own map format into TiledMap...) which I need to test thoroughly, but it uses libgdx code: from file handling to asset loading.
I'm not planning to test the actual graphical output, or the game itself, in this way: but I want to test the single components (calculation, asset access...) to avoid blatant errors.
I've tried to do something like this in the "setUpBeforeClass" method:
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.useGL20 = true;
cfg.width = 480;
cfg.height = 320;
cfg.resizable = true;
LwjglApplication app = new LwjglApplication( new TestApplicationListener(), cfg);
And calling within tearDownAfterClass():
Gfx.app.exit()
But it does create a window I do not need, and seems overkill when all I need is the file handling initialized. Is there a better way to initialize the libGDX components without creating an entire application object?
Thanks.
EDIT
Going back over it (thanks to Sam in the comments), I realize GL access is needed (loading assets requires it), but this approach does not seem to work: the graphic library does not seem to be initialized. GDX documentation hasn't helped. Any clue?

This question hasn't been answered and I am surprised nobody has pointed out the headless backend, which is ideal for this situation. Combine this with your favorite mocking library and you should be good to go.
public class HeadlessLauncher {
public static void main(final String[] args) {
final HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration();
config.renderInterval = Globals.TICK_RATE; // Likely want 1f/60 for 60 fps
new HeadlessApplication(new MyApplication(), config);
}
}

As already showed there is a HeadlessApplication backend which gives you an initialized libGDX but has no OpenGL context. For working with OpenGL you indeed need the LwjglApplication backend which creates an OpenGL window.
If you have problems writing tests which rely on the OpenGL context keep in mind that OpenGL is only attached to the thread of your LwjglApplication which is not the tread of your tests. Your tests have to call Gdx.app.postRunnable(Runnable r) to access the thread with the OpenGl context.
You may want to use synchronized and CountDownLatch to pause the test while waiting for your application to execute the command.

Related

How to let run only one instance of application at a time?

I am working on a GUI application that uses JavaFX(not fxml) and exported as a JAR. For slow machine, impatient user click more than once on JAR, and multiple instances of application started.
I'm looking for a solution to let only one instance can be run at a time on a system and if the user clicks again while the application is running nothing happens. I think it's called singleton but don't know how to implement it.
You could try JUnique. It's an open source library doing exactly what you ask for. Import junique-1.0.4.jar to your project as a library. It's just 10kb file.
It's manual neatly describes how to implement it on a project. For a JavaFX application, implementation would look something like this:
Make sure to import these classes to your main
import it.sauronsoftware.junique.AlreadyLockedException;
import it.sauronsoftware.junique.JUnique;
public static void main(String[] args) {
String appId = "myapplicationid";
boolean alreadyRunning;
try {
JUnique.acquireLock(appId);
alreadyRunning = false;
} catch (AlreadyLockedException e) {
alreadyRunning = true;
}
if (!alreadyRunning) {
launch(args); // <-- This the your default JavaFX start sequence
}else{ //This else is optional. Just to free up memory if you're calling the program from a terminal.
System.exit(1);
}
}
One easy solution that I've used is, when you start the application, it creates a file (I named it .lock but you can call it whatever you want), unless the file already exists, in which case the application terminates its execution instead of creating the file.
You will need to bind your application with a resource. It can be a file, port etc.
You can change the code on startup to check if the file is locked. The below code will give you some idea
FileOutputStream foStream = new FileOutputStream("/tmp/testfile.txt");
FileChannel channel = fileOutputStream.getChannel();
FileLock lock = channel.lock();
If you'd properly package your JavaFX code as a real application instead of just throwing it into a jar, you might get that functionality for free and without all these hacks. If I package my JavaFX code on my Mac with the jpackage tool, the result will be a full featured macOS application. That means that when I double-click its icon somewhere several times, only one instance of the application will be started. This is the default behaviour on Macs and properly packaged JavaFX applications just stick to that rule too. I can't say however what the behaviour on Windows or Linux is because I currently don't have such a box running. Maybe someone who knows can add this as a comment.

GetClass issue in Java Application Setting Icon

I am trying to do the simple activity of setting the Application Icon in a java application. I have many working examples with me but in this instance it fails. Please help I have tried a) b) c) marked in the code. a) Gives a error hint 'Non-static getClass cannot be referenced from a static context' So I tried b) and c). In both, the program runs, but NO Icon is set, NO errors. (I have put the same image in different paths for test purpose)
private static void createAndShowGUI() {
myFrame = new MyDynamic();
myFrame.setTitle( "Sunsong Public School : Home" );
a)myFrame.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("../Images/Sudan.png")));
b)myFrame.setIconImage(ImageIO.read(new File("../Images/Sudan.png")));
c)Image icoon = Toolkit.getDefaultToolkit().getImage("Sudan.png"
Got the solution from some other source. The funny thing is I have dozens of working Applications with Icon. In all of them I am using the Toolkit-getclass-getresources. But in this case I was tinkering with an old code, and stuck inside a static block. From the static context Calling toolkits non-static getClass is NOT working. Had tried hundreds of examples from the net in the last 20 or so hours. Java IO also NOT working complains cannot 'read from file'.
This is the one Finally worked..
ImageIcon icon = new ImageIcon(ClassLoader.getSystemResource("Sudan.png"));
Image img = icon.getImage();
myFrame.setIconImage(img); // frame is a JFrame

Sharing resources between OpenGL context's on Android

I am trying to use multiple EGL contexts to load textures outside of my main thread. I'm getting an EGL_BAD_CONTEXT error after my eglCreateContext call.
Inside my android.opengl.Renderer
public void onSurfaceCreated (javax.microedition.khronos.opengles.GL10 gl, EGLConfig config) {
// ...
EGLContext sharedContext = egl.getCurrentContext();
EGLDisplay display = eglGetCurrentDisplay();
eglCreateContext(display, config, sharedContext, new int[] { EGL_CONTEXT_CLIENT_VERSION, 2 } );
}
The EGL_BAD_CONTEXT lead me to the documentation here, that says
EGL_BAD_CONTEXT is generated if share_context is not an EGL rendering context of the same client API type as the newly created context and is not EGL_NO_CONTEXT.
That's why I added in the EGL_CONTEXT_CLIENT_VERSION parameter, but it seems to have made no effect.
What I'm seeing is that, even though I'm getting this error, the context seems semi-valid. I'm able to use it on another thread
egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, context);
After this, creating textures on that thread does not cause an error. But I do see that the texture names are not shared, each thread seems to count up from 0 itself.
My next assumption was that I need to share the surface between contexts. But, if I pass through the same surface from the original context into my eglMakeCurrent, but I fail completely with
E/AndroidRuntime(3210): java.lang.IllegalArgumentException
E/AndroidRuntime(3210): at com.google.android.gles_jni.EGLImpl._eglCreateContext(Native Method)
E/AndroidRuntime(3210): at com.google.android.gles_jni.EGLImpl.eglCreateContext(EGLImpl.java:54)
I feel as though I'm almost there, does somebody know what's missing?
Turns out, thanks to some help from this question:
My secondary context requires a surface. It is not the same as the original context's surface.
I needed to create that new surface using eglCreatePbufferSurface. The reason my attempts with this had failed before is that it defaults to a width and height of 0. By setting that to a 1x1 surface, it worked perfectly.
egl.eglCreatePbufferSurface(display, config, new int[] { EGL10.EGL_WIDTH, 1, EGL10.EGL_HEIGHT, 1, EGL10.EGL_NONE });

How do I get a VLC Media Player in Java without a Displayable Component?

I'm working with the VLCJ Bindings and have finally been able to get several roadblocks. Now I am here.
I have no need (at this time), nor desire for, a visible Media Player component (the EmbeddedMediaPlayerComponent). All I need (for now) is to play Audio Files.
I have the following method in place to handle that for me:
public static void Play(File AudioFile){
if (!LibVLCLoader.Loaded) LibVLCLoader.loadLibVLC();
EmbeddedMediaPlayerComponent EMPC = new EmbeddedMediaPlayerComponent();
if (EMPC.getMediaPlayer().prepareMedia(AudioFile.getAbsolutePath())){
EMPC.getMediaPlayer().addMediaPlayerEventListener(new MediaPlayerEventAdapter(){
#Override public void subItemFinished(MediaPlayer p, int i){
EMPC.release(true);
}
});
Platform.runLater(() -> EMPC.getMediaPlayer().play());
}
}
But I keep getting this exception:
Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: The video surface component must be displayable
Which I understand. It makes sense. But I don't NEED it visible. I just need the sound. How can I make that happen?
EmbeddedMediaPlayer is only for the case where you want to literally embed a video surface inside your application.
If you just need audio, there's an AudioMediaPlayerComponent for expressly this purpose.
To create such a component, simply:
AudioMediaPlayerComponent audioMediaPlayerComponent =
new AudioMediaPlayerComponent();
You can subclass it, for example to customise behaviour and easily implement event handlers.
Using the so-called "component" media players gives you a slightly nicer/easier API than using the non-"component" media players that are created via the MediaPlayerFactory.
This works just fine if your media is an audio file.
If your media is actually video, but you only want to play the audio track, then even if you use the AudioMediaPlayerComponent by default VLC will open a video window. In this case you still need to actually disable the video output - the simplest way to do this is to tell VLC to use vcodec=dummy.
I really don't agree with tricks like creating a window and moving it off-screen, or sizing it down to 1x1, it's just not necessary.
In the code posted in the original question there is an unrelated problem. The EMPC and EMP variable will go out-of-scope when the Play() method terminates, making the media player eligible for garbage collection. What will happen is that some random time later your application will likely crash because the native hooks that vlcj uses will call back into a Java object that no longer exists. You need to keep your media player references alive via hard references.
Okay so it turns out you can create your own MediaPlayer object outside of the EmbeddedMediaPlayerComponent like so:
public static void Play(File AudioFile){
if (!LibVLCLoader.Loaded) LibVLCLoader.loadLibVLC();
MediaPlayerFactory MPF = new MediaPlayerFactory(
"--video-title=vlcj video output",
"--no-snapshot-preview",
"--quiet",
"--quiet-synchro",
"--sub-filter=logo:marq",
"--intf=dummy"
);
EmbeddedMediaPlayer EMP = MPF.newEmbeddedMediaPlayer();
if (EMP.prepareMedia(AudioFile.getAbsolutePath())){
EMP.addMediaPlayerEventListener(new MediaPlayerEventAdapter(){
#Override public void subItemFinished(MediaPlayer p, int i){
EMP.release();
MPF.release();
}
});
Platform.runLater(() -> EMP.play());
} else{
EMP.release();
MPF.release();
}
}

Making program extensions

I am making a program for computer surveillance at the moment.
It's for a competition in my country Croatia(InfoKup).
I have several options for sending command to another PC, but I
want to make the possibility for the command extension for people
who know Java. So I want to make the user be able to add some of his
custom commands for the program. For example something like
Minecraft mods. I know it is possible, but how would I go about
doing that.
Any help would be greatly appreciated. My code on GitHub:GitHub
Don't mind the stream thing.
It's something my friend is experimenting with.
EDIT: e.g.
Currently I have the possibility to send popups to another PC. What if the extension maker knew the code to send cmd commands and wants to add that function. He makes an extension and puts it in the extension folder. Voila we have a new possibility.
EDIT 2:
Don't be so harsh on me pls :). Thx for the dynamic class loading tip. I have been looking into that, and it looks promising.
Basically what I want to have possible is the user to drop the "mod/extension/whatever" in the "mod/extension/whatever" folder, and the program would load it and put all of the buttons declared in the class in to the GUI, and with them the function. I think I'm getting the hang of this, but any tips would be helpful.
e.g.
package sth.sth;
import blah.blah.*;
public class ClassSTH extends SchoolarButton{
public ClassSTH(String params){
super(params);
}
#Override
public void OnClick(){
doStuff();
}
}
EDIT:
The problem is easily solvable using Java Reflection! I wish someone posted that as an answer befpre blatanty downvoting a question because pf a GitHub link that was there to prpve that I've actually done something.
This kind of thing can be accomplished by using Java Reflection!
How to load and invoke a method on an external jar:
File f = new File("plugin.jar");
URLClassLoader cl = new URLClassLoader(new URL[]{f.toURI().toURL(), null});
Class<?> clazz = cl.loadClass("epicurus.Client");
Method main = clazz.getMethod("main", String[].class);
main.invoke(null, new Object[]{new String[]{}});

Categories

Resources