-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add com.jme3.input tests #2757
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
base: master
Are you sure you want to change the base?
Add com.jme3.input tests #2757
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| package com.jme3.input; | ||
|
|
||
| import com.jme3.input.controls.JoyAxisTrigger; | ||
| import com.jme3.input.controls.JoyButtonTrigger; | ||
| import com.jme3.input.controls.Trigger; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.mockito.ArgumentCaptor; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| import static org.junit.jupiter.api.Assertions.assertFalse; | ||
| import static org.junit.jupiter.api.Assertions.assertNull; | ||
| import static org.junit.jupiter.api.Assertions.assertSame; | ||
| import static org.junit.jupiter.api.Assertions.assertThrows; | ||
| import static org.junit.jupiter.api.Assertions.assertTrue; | ||
| import static org.mockito.ArgumentMatchers.eq; | ||
| import static org.mockito.Mockito.mock; | ||
| import static org.mockito.Mockito.verify; | ||
|
|
||
| class DefaultJoystickTest { | ||
|
|
||
| @Test | ||
| void storesAxesAndButtonsAsReadOnlyLogicalCollections() { | ||
| TestJoystick joystick = new TestJoystick(mock(InputManager.class), mock(JoyInput.class), 3, "Gamepad"); | ||
| DefaultJoystickAxis xAxis = new DefaultJoystickAxis(null, joystick, 0, "X Axis", | ||
| JoystickAxis.X_AXIS, true, false, 0.1f); | ||
| DefaultJoystickButton fire = new DefaultJoystickButton(null, joystick, 1, "Fire", | ||
| JoystickButton.BUTTON_1); | ||
|
|
||
| joystick.addTestAxis(xAxis); | ||
| joystick.addTestButton(fire); | ||
|
|
||
| assertSame(xAxis, joystick.getAxis(JoystickAxis.X_AXIS)); | ||
| assertNull(joystick.getAxis(JoystickAxis.Y_AXIS)); | ||
| assertSame(fire, joystick.getButton(JoystickButton.BUTTON_1)); | ||
| assertNull(joystick.getButton(JoystickButton.BUTTON_2)); | ||
| assertEquals(1, joystick.getAxisCount()); | ||
| assertEquals(1, joystick.getButtonCount()); | ||
| assertThrows(UnsupportedOperationException.class, () -> joystick.getAxes().clear()); | ||
| assertThrows(UnsupportedOperationException.class, () -> joystick.getButtons().clear()); | ||
| assertEquals("Joystick[name=Gamepad, id=3, buttons=1, axes=1]", joystick.toString()); | ||
| } | ||
|
|
||
| @Test | ||
| void rumbleDelegatesToJoyInput() { | ||
| JoyInput joyInput = mock(JoyInput.class); | ||
| TestJoystick joystick = new TestJoystick(mock(InputManager.class), joyInput, 7, "Wheel"); | ||
|
|
||
| joystick.rumble(0.75f); | ||
|
|
||
| verify(joyInput).setJoyRumble(7, 0.75f); | ||
| } | ||
|
|
||
| @Test | ||
| void defaultAxisExposesStateAndAssignsPositiveAndNegativeTriggers() { | ||
| InputManager inputManager = mock(InputManager.class); | ||
| TestJoystick joystick = new TestJoystick(inputManager, mock(JoyInput.class), 2, "Arcade Stick"); | ||
| DefaultJoystickAxis axis = new DefaultJoystickAxis(inputManager, joystick, 4, "Throttle", | ||
| "throttle", true, false, 0.2f); | ||
|
|
||
| axis.setDeadZone(0.35f); | ||
| axis.assignAxis("Throttle+", "Throttle-"); | ||
|
|
||
| assertSame(joystick, axis.getJoystick()); | ||
| assertEquals("Throttle", axis.getName()); | ||
| assertEquals("throttle", axis.getLogicalId()); | ||
| assertEquals(4, axis.getAxisId()); | ||
| assertTrue(axis.isAnalog()); | ||
| assertFalse(axis.isRelative()); | ||
| assertEquals(0.35f, axis.getDeadZone()); | ||
| assertEquals(0f, axis.getJitterThreshold()); | ||
| assertEquals("JoystickAxis[name=Throttle, parent=Arcade Stick, id=4, logicalId=throttle, " | ||
| + "isAnalog=true, isRelative=false, deadZone=0.35, jitterThreshold=0.0]", axis.toString()); | ||
|
|
||
| ArgumentCaptor<Trigger[]> positive = ArgumentCaptor.forClass(Trigger[].class); | ||
| ArgumentCaptor<Trigger[]> negative = ArgumentCaptor.forClass(Trigger[].class); | ||
| verify(inputManager).addMapping(eq("Throttle+"), positive.capture()); | ||
| verify(inputManager).addMapping(eq("Throttle-"), negative.capture()); | ||
| JoyAxisTrigger positiveTrigger = (JoyAxisTrigger) positive.getValue()[0]; | ||
| JoyAxisTrigger negativeTrigger = (JoyAxisTrigger) negative.getValue()[0]; | ||
| assertEquals(2, positiveTrigger.getJoyId()); | ||
| assertEquals(4, positiveTrigger.getAxisId()); | ||
| assertFalse(positiveTrigger.isNegative()); | ||
| assertTrue(negativeTrigger.isNegative()); | ||
| } | ||
|
|
||
| @Test | ||
| void defaultAxisWithUnknownIndexDoesNotAssignMappings() { | ||
| InputManager inputManager = mock(InputManager.class); | ||
| TestJoystick joystick = new TestJoystick(inputManager, mock(JoyInput.class), 2, "Unknown"); | ||
| DefaultJoystickAxis axis = new DefaultJoystickAxis(inputManager, joystick, -1, "Unknown", | ||
| "unknown", false, true, 0f); | ||
|
|
||
| axis.assignAxis("Positive", "Negative"); | ||
|
|
||
| org.mockito.Mockito.verifyNoInteractions(inputManager); | ||
| } | ||
|
|
||
| @Test | ||
| void defaultButtonExposesStateAndAssignsTrigger() { | ||
| InputManager inputManager = mock(InputManager.class); | ||
| TestJoystick joystick = new TestJoystick(inputManager, mock(JoyInput.class), 5, "Pad"); | ||
| DefaultJoystickButton button = new DefaultJoystickButton(inputManager, joystick, 6, "Start", | ||
| JoystickButton.BUTTON_XBOX_START); | ||
|
|
||
| button.assignButton("Pause"); | ||
|
|
||
| assertSame(joystick, button.getJoystick()); | ||
| assertEquals("Start", button.getName()); | ||
| assertEquals(JoystickButton.BUTTON_XBOX_START, button.getLogicalId()); | ||
| assertEquals(6, button.getButtonId()); | ||
| assertEquals("JoystickButton[name=Start, parent=Pad, id=6, logicalId=9]", button.toString()); | ||
|
|
||
| ArgumentCaptor<Trigger[]> triggers = ArgumentCaptor.forClass(Trigger[].class); | ||
| verify(inputManager).addMapping(eq("Pause"), triggers.capture()); | ||
| JoyButtonTrigger trigger = (JoyButtonTrigger) triggers.getValue()[0]; | ||
| assertEquals(5, trigger.getJoyId()); | ||
| assertEquals(6, trigger.getAxisId()); | ||
| } | ||
|
|
||
| private static final class TestJoystick extends AbstractJoystick { | ||
| private TestJoystick(InputManager inputManager, JoyInput joyInput, int joyId, String name) { | ||
| super(inputManager, joyInput, joyId, name); | ||
| } | ||
|
|
||
| void addTestAxis(JoystickAxis axis) { | ||
| addAxis(axis); | ||
| } | ||
|
|
||
| void addTestButton(JoystickButton button) { | ||
| addButton(button); | ||
| } | ||
|
|
||
| @Override | ||
| public JoystickAxis getXAxis() { | ||
| return getAxis(JoystickAxis.X_AXIS); | ||
| } | ||
|
|
||
| @Override | ||
| public JoystickAxis getYAxis() { | ||
| return getAxis(JoystickAxis.Y_AXIS); | ||
| } | ||
|
|
||
| @Override | ||
| public JoystickAxis getPovXAxis() { | ||
| return getAxis(JoystickAxis.POV_X); | ||
| } | ||
|
|
||
| @Override | ||
| public JoystickAxis getPovYAxis() { | ||
| return getAxis(JoystickAxis.POV_Y); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| package com.jme3.input; | ||
|
|
||
| import com.jme3.input.event.JoyAxisEvent; | ||
| import com.jme3.input.event.JoyButtonEvent; | ||
| import com.jme3.input.event.KeyInputEvent; | ||
| import com.jme3.input.event.MouseButtonEvent; | ||
| import com.jme3.input.event.MouseMotionEvent; | ||
| import com.jme3.input.event.TouchEvent; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| import static org.junit.jupiter.api.Assertions.assertNull; | ||
|
|
||
| class InputUtilityTest { | ||
|
|
||
| @Test | ||
| void keyNamesReturnStableNamesForRepresentativeKeyGroups() { | ||
| new KeyNames(); | ||
|
|
||
| assertEquals("Unknown", KeyNames.getName(KeyInput.KEY_UNKNOWN)); | ||
| assertEquals("0", KeyNames.getName(KeyInput.KEY_0)); | ||
| assertEquals("A", KeyNames.getName(KeyInput.KEY_A)); | ||
| assertEquals("F12", KeyNames.getName(KeyInput.KEY_F12)); | ||
| assertEquals("Numpad Enter", KeyNames.getName(KeyInput.KEY_NUMPADENTER)); | ||
| assertEquals("Left Ctrl", KeyNames.getName(KeyInput.KEY_LCONTROL)); | ||
| assertEquals("Esc", KeyNames.getName(KeyInput.KEY_ESCAPE)); | ||
| assertEquals("Page Down", KeyNames.getName(KeyInput.KEY_PGDN)); | ||
| assertEquals("Kana", KeyNames.getName(KeyInput.KEY_KANA)); | ||
| assertNull(KeyNames.getName(KeyInput.KEY_LAST)); | ||
| } | ||
|
|
||
| @Test | ||
| void rawInputListenerAdapterAcceptsAllCallbacksAsNoOps() { | ||
| RawInputListener listener = new RawInputListenerAdapter() { | ||
| }; | ||
|
|
||
| listener.beginInput(); | ||
| listener.onJoyAxisEvent((JoyAxisEvent) null); | ||
| listener.onJoyButtonEvent((JoyButtonEvent) null); | ||
| listener.onMouseMotionEvent((MouseMotionEvent) null); | ||
| listener.onMouseButtonEvent((MouseButtonEvent) null); | ||
| listener.onKeyEvent((KeyInputEvent) null); | ||
| listener.onTouchEvent((TouchEvent) null); | ||
| listener.endInput(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| package com.jme3.input; | ||
|
|
||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import java.util.Map; | ||
| import java.util.Properties; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| import static org.junit.jupiter.api.Assertions.assertThrows; | ||
| import static org.mockito.Mockito.mock; | ||
| import static org.mockito.Mockito.when; | ||
|
|
||
| class JoystickCompatibilityMappingsTest { | ||
|
|
||
| @Test | ||
| void remapsSpecificAxisButtonAndGenericComponents() { | ||
| String stick = "Codex Test Stick"; | ||
| JoystickCompatibilityMappings.addAxisMapping(stick, "x_raw", JoystickAxis.X_AXIS); | ||
| JoystickCompatibilityMappings.addButtonMapping(stick, "0_raw", JoystickButton.BUTTON_XBOX_A); | ||
| JoystickCompatibilityMappings.addMapping(stick, "misc_raw", "misc"); | ||
|
|
||
| assertEquals(JoystickAxis.X_AXIS, JoystickCompatibilityMappings.remapAxis(" " + stick + " ", "x_raw")); | ||
| assertEquals(JoystickButton.BUTTON_XBOX_A, JoystickCompatibilityMappings.remapButton(stick, "0_raw")); | ||
| assertEquals("misc", JoystickCompatibilityMappings.remapComponent(stick, "misc_raw")); | ||
| assertEquals("unmapped", JoystickCompatibilityMappings.remapAxis(stick, "unmapped")); | ||
| assertEquals("unmapped", JoystickCompatibilityMappings.remapButton(stick, "unmapped")); | ||
| assertEquals("unmapped", JoystickCompatibilityMappings.remapComponent(stick, "unmapped")); | ||
| } | ||
|
|
||
| @Test | ||
| void returnsUnmodifiableMappingViews() { | ||
| String stick = "Codex Test Mapping View"; | ||
| JoystickCompatibilityMappings.addMapping(stick, "raw", "logical"); | ||
| JoystickCompatibilityMappings.addButtonMapping(stick, "buttonRaw", "buttonLogical"); | ||
|
|
||
| Map<String, String> componentMappings = JoystickCompatibilityMappings.getJoystickMappings(stick); | ||
| Map<String, String> buttonMappings = JoystickCompatibilityMappings.getJoystickButtonMappings(stick); | ||
|
|
||
| assertEquals("logical", componentMappings.get("raw")); | ||
| assertEquals("buttonLogical", buttonMappings.get("buttonRaw")); | ||
| assertThrows(UnsupportedOperationException.class, () -> componentMappings.put("other", "value")); | ||
| assertThrows(UnsupportedOperationException.class, () -> buttonMappings.put("other", "value")); | ||
| assertEquals(0, JoystickCompatibilityMappings.getJoystickMappings("No Such Stick").size()); | ||
| } | ||
|
|
||
| @Test | ||
| void addMappingsParsesTypedEntriesRangesAndNameRegex() { | ||
| Properties properties = new Properties(); | ||
| properties.setProperty("axis.Codex Regex Stick.x", "left_x [-1.0, 1.0]"); | ||
| properties.setProperty("button.Codex Regex Stick.trigger", "fire"); | ||
| properties.setProperty("Codex Regex Stick.misc", "menu"); | ||
| properties.setProperty("Codex Regex Stick.regex", "Codex Regex Stick \\(rev \\d+\\)"); | ||
|
|
||
| JoystickCompatibilityMappings.addMappings(properties); | ||
|
|
||
| String physicalName = "Codex Regex Stick (rev 42)"; | ||
| assertEquals("left_x", JoystickCompatibilityMappings.remapAxis(physicalName, "x")); | ||
| assertEquals("fire", JoystickCompatibilityMappings.remapButton(physicalName, "trigger")); | ||
| assertEquals("menu", JoystickCompatibilityMappings.remapComponent(physicalName, "misc")); | ||
| } | ||
|
|
||
| @Test | ||
| void remapAxisRangeUsesConfiguredRangeAndCachesMissingMappings() { | ||
| String stick = "Codex Test Axis Range"; | ||
| JoystickCompatibilityMappings.addAxisMapping(stick, "slider", "slider", new float[]{0f, 1f}); | ||
| JoystickAxis mappedAxis = axis(stick, "slider"); | ||
| JoystickAxis unmappedAxis = axis(stick, "unknown"); | ||
|
|
||
| assertEquals(0.25f, JoystickCompatibilityMappings.remapAxisRange(mappedAxis, -0.5f)); | ||
| assertEquals(0.75f, JoystickCompatibilityMappings.remapAxisRange(mappedAxis, 0.5f)); | ||
| assertEquals(0.4f, JoystickCompatibilityMappings.remapAxisRange(unmappedAxis, 0.4f)); | ||
| assertEquals(-0.6f, JoystickCompatibilityMappings.remapAxisRange(unmappedAxis, -0.6f)); | ||
| } | ||
|
Comment on lines
+63
to
+73
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current test only covers the range References
|
||
|
|
||
| @Test | ||
| void rejectsInvalidAxisRange() { | ||
| assertThrows(IllegalArgumentException.class, | ||
| () -> JoystickCompatibilityMappings.addAxisMapping("Bad Range", "axis", "axis", new float[]{0f})); | ||
| } | ||
|
|
||
| private static JoystickAxis axis(String joystickName, String axisName) { | ||
| Joystick joystick = mock(Joystick.class); | ||
| when(joystick.getName()).thenReturn(joystickName); | ||
|
|
||
| JoystickAxis axis = mock(JoystickAxis.class); | ||
| when(axis.getJoystick()).thenReturn(joystick); | ||
| when(axis.getName()).thenReturn(axisName); | ||
| return axis; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| package com.jme3.input.controls; | ||
|
|
||
| import com.jme3.input.KeyInput; | ||
| import com.jme3.input.MouseInput; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| import static org.junit.jupiter.api.Assertions.assertFalse; | ||
| import static org.junit.jupiter.api.Assertions.assertThrows; | ||
| import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
|
||
| class InputTriggerTest { | ||
|
|
||
| @Test | ||
| void keyTriggerUsesLowByteHashAndReadableName() { | ||
| KeyTrigger trigger = new KeyTrigger(KeyInput.KEY_SPACE); | ||
|
|
||
| assertEquals(KeyInput.KEY_SPACE, trigger.getKeyCode()); | ||
| assertEquals("KeyCode " + KeyInput.KEY_SPACE, trigger.getName()); | ||
| assertEquals(KeyInput.KEY_SPACE & 0xff, trigger.triggerHashCode()); | ||
| } | ||
|
|
||
| @Test | ||
| void mouseAxisTriggerNamesKnownAxesAndEncodesDirection() { | ||
| MouseAxisTrigger xPositive = new MouseAxisTrigger(MouseInput.AXIS_X, false); | ||
| MouseAxisTrigger wheelNegative = new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true); | ||
|
|
||
| assertEquals(MouseInput.AXIS_X, xPositive.getMouseAxis()); | ||
| assertFalse(xPositive.isNegative()); | ||
| assertEquals("Mouse X Axis Positive", xPositive.getName()); | ||
| assertEquals("Mouse Wheel Negative", wheelNegative.getName()); | ||
| assertEquals(512 | MouseInput.AXIS_X, xPositive.triggerHashCode()); | ||
| assertEquals(768 | MouseInput.AXIS_WHEEL, wheelNegative.triggerHashCode()); | ||
| assertThrows(IllegalArgumentException.class, () -> new MouseAxisTrigger(9, false)); | ||
| } | ||
|
|
||
| @Test | ||
| void mouseButtonTriggerUsesButtonHashAndName() { | ||
| MouseButtonTrigger trigger = new MouseButtonTrigger(MouseInput.BUTTON_RIGHT); | ||
|
|
||
| assertEquals(MouseInput.BUTTON_RIGHT, trigger.getMouseButton()); | ||
| assertEquals("Mouse Button " + MouseInput.BUTTON_RIGHT, trigger.getName()); | ||
| assertEquals(256 | MouseInput.BUTTON_RIGHT, trigger.triggerHashCode()); | ||
| } | ||
|
|
||
| @Test | ||
| void joystickAxisTriggerEncodesJoystickAxisAndSign() { | ||
| JoyAxisTrigger positive = new JoyAxisTrigger(2, 3, false); | ||
| JoyAxisTrigger negative = new JoyAxisTrigger(2, 3, true); | ||
|
|
||
| assertEquals(2, positive.getJoyId()); | ||
| assertEquals(3, positive.getAxisId()); | ||
| assertFalse(positive.isNegative()); | ||
| assertTrue(negative.isNegative()); | ||
| assertEquals("JoyAxis[joyId=2, axisId=3, neg=false]", positive.getName()); | ||
| assertEquals((2048 * 2) | 1024 | 3, positive.triggerHashCode()); | ||
| assertEquals((2048 * 2) | 1280 | 3, negative.triggerHashCode()); | ||
| } | ||
|
|
||
| @Test | ||
| void joystickButtonTriggerEncodesJoystickAndButton() { | ||
| JoyButtonTrigger trigger = new JoyButtonTrigger(4, 7); | ||
|
|
||
| assertEquals(4, trigger.getJoyId()); | ||
| assertEquals(7, trigger.getAxisId()); | ||
| assertEquals("JoyButton[joyId=4, axisId=7]", trigger.getName()); | ||
| assertEquals((2048 * 4) | 1536 | 7, trigger.triggerHashCode()); | ||
| } | ||
|
|
||
| @Test | ||
| void touchTriggerDistinguishesZeroFromNonZeroKeyCodes() { | ||
| TouchTrigger zero = new TouchTrigger(0); | ||
| TouchTrigger key = new TouchTrigger(KeyInput.KEY_RETURN); | ||
|
|
||
| assertEquals("TouchInput KeyCode 0", zero.getName()); | ||
| assertEquals("TouchInput", key.getName()); | ||
| assertEquals(0, zero.getKeyCode()); | ||
| assertEquals(KeyInput.KEY_RETURN, key.getKeyCode()); | ||
| assertEquals(TouchTrigger.touchHash(0), zero.triggerHashCode()); | ||
| assertEquals(TouchTrigger.touchHash(KeyInput.KEY_RETURN), key.triggerHashCode()); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assertion will likely cause an
ArrayIndexOutOfBoundsException. InKeyInput,KEY_LASTis defined as0xFF(255). However, theKEY_NAMESarray inKeyNames.java(line 47) is initialized withnew String[0xFF], which has a size of 255 and valid indices from 0 to 254. Accessing index 255 will throw an exception. The production code inKeyNames.javashould be updated tonew String[0x100]to correctly support all key codes includingKEY_LAST.References