From 42d8d55067057757223dbf3e2e263cca1448da43 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 22 Aug 2023 04:27:30 -0400 Subject: [PATCH] Unit Test Suite (#119) * Initial test suite * Fix some build warnings * Implemented working unit tests with coverage * Reduced some warnings * Fix a mac-specific issue * Add 2 additional unit test classes. * Multiple new unit tests * Some fixins * Remove auto-generated file * WIP on hiding ignored tests * Added list of debug hotkeys * Remove old website * Remove empty file * Add more unit tests * Fix bug where arrows would nudge BF * Fix bug where ctrl/alt would flash capsules * Fixed bug where bf-old easter egg broke * Remove duplicate lines * More test-related stuff * Some code cleanup * Add mocking and a test assets folder * More TESTS! * Update Hmm... * Update artist on Monster * More minor fixes to individual functions * 1.38% unit test coverage! * Even more tests? :O * More unit test work * Rework migration for BaseRegistry * gameover fix * Fix an issue with Lime * Fix issues with version parsing on data files * 100 total unit tests! * Added even MORE unit tests! * Additional test tweaks :3 * Fixed tests on windows by updating libraries. * Set versions for flixel-ui and hamcrest --------- Co-authored-by: Cameron Taylor --- docs/CNAME | 1 - docs/Funkin' Debug Hotkeys.md | 31 + docs/img/skin-funkin-cardbordtoast.jpg | Bin 237156 -> 0 bytes docs/index.html | 60 -- docs/readme.md | 7 - docs/styles.css | 97 --- hmm.json | 37 +- source/funkin/Conductor.hx | 21 +- source/funkin/Controls.hx | 2 +- source/funkin/FreeplayState.hx | 16 - source/funkin/data/BaseRegistry.hx | 45 +- source/funkin/data/level/LevelRegistry.hx | 8 +- .../data/notestyle/NoteStyleRegistry.hx | 8 +- source/funkin/freeplayStuff/DJBoyfriend.hx | 21 - source/funkin/freeplayStuff/SongMenuItem.hx | 3 - source/funkin/modding/PolymodHandler.hx | 2 +- source/funkin/modding/module/ModuleHandler.hx | 31 +- source/funkin/play/HealthIcon.hx | 4 +- source/funkin/play/PlayState.hx | 8 - source/funkin/play/character/CharacterData.hx | 2 +- .../play/cutscene/dialogue/Conversation.hx | 10 +- .../funkin/play/notes/notestyle/NoteStyle.hx | 9 +- source/funkin/play/song/SongMigrator.hx | 4 +- source/funkin/play/stage/StageData.hx | 2 +- .../charting/ChartEditorDialogHandler.hx | 2 + .../debug/charting/ChartEditorEventSprite.hx | 2 +- .../ui/debug/charting/ChartEditorState.hx | 2 +- source/funkin/ui/story/Level.hx | 2 +- source/funkin/util/BezierUtil.hx | 7 +- source/funkin/util/Constants.hx | 11 +- source/funkin/util/DateUtil.hx | 5 +- source/funkin/util/SaveDataUtil.hx | 1 - source/funkin/util/SerializerUtil.hx | 28 +- source/funkin/util/VersionUtil.hx | 40 +- source/funkin/util/assets/FlxAnimationUtil.hx | 2 +- source/funkin/util/tools/ArraySortTools.hx | 3 + source/funkin/util/tools/MapTools.hx | 1 + source/funkin/util/tools/StringTools.hx | 1 + tests/unit/.gitignore | 7 + tests/unit/.munit | 7 + tests/unit/.vscode/launch.json | 13 + tests/unit/README.md | 50 ++ .../unit/assets/preload/data/anotherFile.txt | 0 .../unit/assets/preload/data/levels/test.json | 47 ++ .../assets/preload/data/mytype/blablabla.json | 6 + .../assets/preload/data/mytype/fizzbuzz.json | 15 + .../assets/preload/data/mytype/foobar.json | 5 + .../unit/assets/preload/data/mytype/junk.json | 4 + .../preload/data/notestyles/funkin.json | 59 ++ .../assets/preload/data/notestyles/test2.json | 18 + .../assets/preload/data/test/blablabla.json | 0 .../unit/assets/preload/data/test/test1.json | 0 .../unit/assets/preload/data/test/test2.json | 0 tests/unit/assets/shared/images/arrows.png | Bin 0 -> 4806 bytes tests/unit/assets/shared/images/arrows.xml | 32 + tests/unit/project.xml | 91 +++ tests/unit/source/FunkinAssert.hx | 77 +++ tests/unit/source/FunkinTest.hx | 105 ++++ tests/unit/source/MockTest.hx | 60 ++ tests/unit/source/TestMain.hx | 77 +++ tests/unit/source/_template.hxtemplate | 30 + tests/unit/source/flixel/FlxGTest.hx | 107 ++++ tests/unit/source/funkin/ConductorTest.hx | 550 ++++++++++++++++++ .../source/funkin/data/BaseRegistryTest.hx | 228 ++++++++ .../data/notestyle/NoteStyleRegistryTest.hx | 90 +++ .../play/notes/notestyle/NoteStyleTest.hx | 77 +++ .../unit/source/funkin/util/BezierUtilTest.hx | 137 +++++ .../source/funkin/util/ClipboardUtilTest.hx | 71 +++ tests/unit/source/funkin/util/DateUtilTest.hx | 35 ++ .../source/funkin/util/SerializerUtilTest.hx | 87 +++ tests/unit/source/funkin/util/SortUtilTest.hx | 63 ++ .../source/funkin/util/VersionUtilTest.hx | 64 ++ .../funkin/util/assets/DataAssetsTest.hx | 42 ++ .../util/assets/FlxAnimationUtilTest.hx | 118 ++++ .../funkin/util/tools/ArraySortToolsTest.hx | 165 ++++++ .../funkin/util/tools/ArrayToolsTest.hx | 65 +++ .../funkin/util/tools/IteratorToolsTest.hx | 59 ++ .../source/funkin/util/tools/MapToolsTest.hx | 55 ++ .../funkin/util/tools/StringToolsTest.hx | 59 ++ tests/unit/source/import.hx | 21 + tests/unit/start-mac-native.sh | 3 + tests/unit/start-mac-web.sh | 3 + tests/unit/start-win-native.bat | 3 + tests/unit/test-cpp.hxml | 11 + tests/unit/test-web.hxml | 5 + tests/unit/test.hxml | 32 + tests/unit/test.hxml-old | 24 + 87 files changed, 3123 insertions(+), 290 deletions(-) delete mode 100644 docs/CNAME create mode 100644 docs/Funkin' Debug Hotkeys.md delete mode 100644 docs/img/skin-funkin-cardbordtoast.jpg delete mode 100644 docs/index.html delete mode 100644 docs/readme.md delete mode 100644 docs/styles.css delete mode 100644 source/funkin/util/SaveDataUtil.hx create mode 100644 tests/unit/.gitignore create mode 100644 tests/unit/.munit create mode 100644 tests/unit/.vscode/launch.json create mode 100644 tests/unit/README.md create mode 100644 tests/unit/assets/preload/data/anotherFile.txt create mode 100644 tests/unit/assets/preload/data/levels/test.json create mode 100644 tests/unit/assets/preload/data/mytype/blablabla.json create mode 100644 tests/unit/assets/preload/data/mytype/fizzbuzz.json create mode 100644 tests/unit/assets/preload/data/mytype/foobar.json create mode 100644 tests/unit/assets/preload/data/mytype/junk.json create mode 100644 tests/unit/assets/preload/data/notestyles/funkin.json create mode 100644 tests/unit/assets/preload/data/notestyles/test2.json create mode 100644 tests/unit/assets/preload/data/test/blablabla.json create mode 100644 tests/unit/assets/preload/data/test/test1.json create mode 100644 tests/unit/assets/preload/data/test/test2.json create mode 100644 tests/unit/assets/shared/images/arrows.png create mode 100644 tests/unit/assets/shared/images/arrows.xml create mode 100644 tests/unit/project.xml create mode 100644 tests/unit/source/FunkinAssert.hx create mode 100644 tests/unit/source/FunkinTest.hx create mode 100644 tests/unit/source/MockTest.hx create mode 100644 tests/unit/source/TestMain.hx create mode 100644 tests/unit/source/_template.hxtemplate create mode 100644 tests/unit/source/flixel/FlxGTest.hx create mode 100644 tests/unit/source/funkin/ConductorTest.hx create mode 100644 tests/unit/source/funkin/data/BaseRegistryTest.hx create mode 100644 tests/unit/source/funkin/data/notestyle/NoteStyleRegistryTest.hx create mode 100644 tests/unit/source/funkin/play/notes/notestyle/NoteStyleTest.hx create mode 100644 tests/unit/source/funkin/util/BezierUtilTest.hx create mode 100644 tests/unit/source/funkin/util/ClipboardUtilTest.hx create mode 100644 tests/unit/source/funkin/util/DateUtilTest.hx create mode 100644 tests/unit/source/funkin/util/SerializerUtilTest.hx create mode 100644 tests/unit/source/funkin/util/SortUtilTest.hx create mode 100644 tests/unit/source/funkin/util/VersionUtilTest.hx create mode 100644 tests/unit/source/funkin/util/assets/DataAssetsTest.hx create mode 100644 tests/unit/source/funkin/util/assets/FlxAnimationUtilTest.hx create mode 100644 tests/unit/source/funkin/util/tools/ArraySortToolsTest.hx create mode 100644 tests/unit/source/funkin/util/tools/ArrayToolsTest.hx create mode 100644 tests/unit/source/funkin/util/tools/IteratorToolsTest.hx create mode 100644 tests/unit/source/funkin/util/tools/MapToolsTest.hx create mode 100644 tests/unit/source/funkin/util/tools/StringToolsTest.hx create mode 100644 tests/unit/source/import.hx create mode 100755 tests/unit/start-mac-native.sh create mode 100755 tests/unit/start-mac-web.sh create mode 100644 tests/unit/start-win-native.bat create mode 100644 tests/unit/test-cpp.hxml create mode 100644 tests/unit/test-web.hxml create mode 100644 tests/unit/test.hxml create mode 100644 tests/unit/test.hxml-old diff --git a/docs/CNAME b/docs/CNAME deleted file mode 100644 index 3d0ec4d52..000000000 --- a/docs/CNAME +++ /dev/null @@ -1 +0,0 @@ -funkin.me \ No newline at end of file diff --git a/docs/Funkin' Debug Hotkeys.md b/docs/Funkin' Debug Hotkeys.md new file mode 100644 index 000000000..c560c5422 --- /dev/null +++ b/docs/Funkin' Debug Hotkeys.md @@ -0,0 +1,31 @@ +# Funkin' Debug Hotkeys + +`F4` (EVERYWHERE) - Leave Current State and move to Main Menu +`F5` (EVERYWHERE) - Hot Reload Data Files + +`Y` (Title Screen) - WOAH + +`~` (Main Menu) - Access Debug Menu + +`U` (Play) - Open Stage Editor State +`H` (Play) - Show/Hide HUD +`1` (Play) - End Song +`2` (Play) - Add 10% Health +`3` (Play) - Subtract 5% Health +`7` (Play) - (NOT WORKING) Open Chart Editor +`8` (Play) - Open Animation Editor +`9` (Play) - (Easter Egg) Classic Health Icon +`PGUP`/`Fn+Up` (Play) - Skip Forward In Time +`PGDN`/`Fn+Down` (Play) - 🦃 That's right, we're going to go BACK IN TIME + +`F` (Freeplay Menu) - Move to Favorites +`P` (Freeplay Menu) - Switch to Pico (probably doesn't work) +`T` (Freeplay Menu) - Start typing in search bar +`Q` (Freeplay Menu) - Back one letter +`E` (Freeplay Menu) - Forward one letter + +`Arrows` (Stage Editor) - Move Prop +`Ctrl-Z` (Stage Editor) - Undo +`Y` (Stage Editor) - Leave Stage Editor + +`H` (Pause Menu) - Hide the Pause Menu UI (good for screenshots!) diff --git a/docs/img/skin-funkin-cardbordtoast.jpg b/docs/img/skin-funkin-cardbordtoast.jpg deleted file mode 100644 index dd0e96e606b5fcf83f912e0a4e43bc05a9f92364..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 237156 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 B%Deyo diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 11137c674..000000000 --- a/docs/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - Friday Night Funkin' - - - - - - - - - -
-
- - - Friday Night Funkin - -
-

Friday Night Funkin' - Rhythm game extraordinaire

- - -
-
- -
-
- - -
-

Friday Night Funkin' is a dope ass rhythm game.

-

It is made by ninjamuffin99 (programmer), PhantomArcade (animator), evilsk8r (artist), - and Kawaisprite (musician) originally for Ludum Dare 47.

-
- - - - - -
- - \ No newline at end of file diff --git a/docs/readme.md b/docs/readme.md deleted file mode 100644 index aba261b5f..000000000 --- a/docs/readme.md +++ /dev/null @@ -1,7 +0,0 @@ -this is for funkin website stuff -if you're compiling game, you can ignore this folder completely! - -if not, dawg check out [funkin.me](https://funkin.me) - -note that i probably won't accept any major pull requests for this -cuz I wanna make the website as a nice lil project to teach myself HTML and CSS and all that!! diff --git a/docs/styles.css b/docs/styles.css deleted file mode 100644 index 5ee1062fb..000000000 --- a/docs/styles.css +++ /dev/null @@ -1,97 +0,0 @@ -.coolBox { - background: #1a1a1aCC; - margin: 40px 4vw; - padding: 25px; - font-size: 120%; - border-radius: 10px; -} - -#wrapper -{ - padding: 20px; - margin: auto; -} - -marquee { - margin: auto; - text-align: center; - display: inline-block; -} - -h1 { - text-align: center; -} - -body { - background-image: url('img/skin-funkin-cardbordtoast.jpg'); - background-repeat: no-repeat; - background-attachment: fixed; - background-size: cover; - color:white; - background-color: #000; - font-family: Arial, Helvetica, sans-serif; - -} - -a { color:inherit; - text-decoration: none;} - - -.hovertext a{ - color:white; - text-shadow: 0px 0px #00000077; - transition: color 1s, text-shadow 1s; -} - -.hovertext a:hover -{ - text-shadow: 2px 2px #00000077; - color: #ffb50e; -} - -.linktext { - text-align: center; - display:block; - font-size: 130%; - padding-bottom: 10px; -} - -.linktext a { - font-weight: bold; -} - -.linktext a:hover { - border-radius: 5px; -} - -#itch a:hover -{ - color: #fa5c5c; -} -#twitter a:hover -{ - color: #00acee; -} - - -#coolervidwrapper { - padding-left: min(12em, 75%); - padding-right: min(12em, 75%); - min-width: 30%; -} - -.videoWrapper { - position: relative; - padding-bottom: 56.25%; /* 16:9 */ - height: 0; - - max-block-size: 1400px; -} -.videoWrapper iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - -} diff --git a/hmm.json b/hmm.json index 52d5ffad8..150a4f242 100644 --- a/hmm.json +++ b/hmm.json @@ -24,7 +24,7 @@ { "name": "flixel-ui", "type": "haxelib", - "version": "2.4.0" + "version": "2.5.0" }, { "name": "flxanimate", @@ -38,6 +38,11 @@ "type": "haxelib", "version": "3.5.0" }, + { + "name": "hamcrest", + "type": "haxelib", + "version": "3.0.0" + }, { "name": "haxeui-core", "type": "git", @@ -92,12 +97,33 @@ "url": "https://github.com/EliteMasterEric/lime" }, { - "name": "mockatoo", + "name": "mconsole", "type": "git", "dir": null, "ref": "master", + "url": "https://github.com/massive-oss/mconsole" + }, + { + "name": "mcover", + "type": "git", + "dir": "src", + "ref": "master", + "url": "https://github.com/massive-oss/mcover" + }, + { + "name": "mockatoo", + "type": "git", + "dir": "src", + "ref": "master", "url": "https://github.com/EliteMasterEric/mockatoo" }, + { + "name": "munit", + "type": "git", + "dir": "src", + "ref": "master", + "url": "https://github.com/EliteMasterEric/MassiveUnit" + }, { "name": "openfl", "type": "git", @@ -121,6 +147,13 @@ "name": "tink_json", "type": "haxelib", "version": "0.11.0" + }, + { + "name": "hmm", + "type": "git", + "dir": null, + "ref": "d514d7786cabf18b90e60fcee38399fd44c2ddfb", + "url": "https://github.com/andywhite37/hmm" } ] } diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 3c6470373..9bd668b69 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -180,9 +180,15 @@ class Conductor */ public static function forceBPM(?bpm:Float = null) { - if (bpm != null) trace('[CONDUCTOR] Forcing BPM to ' + bpm); + if (bpm != null) + { + trace('[CONDUCTOR] Forcing BPM to ${bpm}'); + } else - trace('[CONDUCTOR] Resetting BPM to default'); + { + // trace('[CONDUCTOR] Resetting BPM to default'); + } + Conductor.bpmOverride = bpm; } @@ -272,9 +278,9 @@ class Conductor if (currentTimeChange.timeStamp > 0.0 && timeChanges.length > 0) { var prevTimeChange:SongTimeChange = timeChanges[timeChanges.length - 1]; - currentTimeChange.beatTime = prevTimeChange.beatTime - + ((currentTimeChange.timeStamp - prevTimeChange.timeStamp) * prevTimeChange.bpm / Constants.SECS_PER_MIN / Constants.MS_PER_SEC) - + 0.01; + currentTimeChange.beatTime = FlxMath.roundDecimal(prevTimeChange.beatTime + + ((currentTimeChange.timeStamp - prevTimeChange.timeStamp) * prevTimeChange.bpm / Constants.SECS_PER_MIN / Constants.MS_PER_SEC), + 4); } } } @@ -282,7 +288,10 @@ class Conductor timeChanges.push(currentTimeChange); } - trace('Done mapping time changes: ' + timeChanges); + if (timeChanges.length > 0) + { + trace('Done mapping time changes: ${timeChanges}' + timeChanges); + } // Update currentStepTime Conductor.update(Conductor.songPosition); diff --git a/source/funkin/Controls.hx b/source/funkin/Controls.hx index e8a66cb14..81055fb34 100644 --- a/source/funkin/Controls.hx +++ b/source/funkin/Controls.hx @@ -50,7 +50,7 @@ enum Control #end } -@:enum +enum abstract Action(String) to String from String { var UI_UP = "ui_up"; diff --git a/source/funkin/FreeplayState.hx b/source/funkin/FreeplayState.hx index 9ad27bfcc..dd87e7d36 100644 --- a/source/funkin/FreeplayState.hx +++ b/source/funkin/FreeplayState.hx @@ -492,22 +492,6 @@ class FreeplayState extends MusicBeatSubState } } - // if (regexp != null) - // tempSongs = songs.filter(item -> regexp.match(item.songName)); - - // tempSongs.sort(function(a, b):Int - // { - // var tempA = a.songName.toUpperCase(); - // var tempB = b.songName.toUpperCase(); - - // if (tempA < tempB) - // return -1; - // else if (tempA > tempB) - // return 1; - // else - // return 0; - // }); - for (i in 0...tempSongs.length) { var funnyMenu:SongMenuItem = new SongMenuItem(FlxG.width, (i * 150) + 160, tempSongs[i].songName); diff --git a/source/funkin/data/BaseRegistry.hx b/source/funkin/data/BaseRegistry.hx index 36b1d26e3..98393fda4 100644 --- a/source/funkin/data/BaseRegistry.hx +++ b/source/funkin/data/BaseRegistry.hx @@ -2,6 +2,7 @@ package funkin.data; import openfl.Assets; import funkin.util.assets.DataAssets; +import funkin.util.VersionUtil; import haxe.Constraints.Constructible; /** @@ -24,16 +25,23 @@ abstract class BaseRegistry & Constructible; + /** + * The version rule to use when loading entries. + * If the entry's version does not match this rule, migration is needed. + */ + final versionRule:thx.semver.VersionRule; + // public abstract static final instance:BaseRegistry = new BaseRegistry<>(); /** * @param registryId A readable ID for this registry, used when logging. * @param dataFilePath The path (relative to `assets/data`) to search for JSON files. */ - public function new(registryId:String, dataFilePath:String) + public function new(registryId:String, dataFilePath:String, versionRule:thx.semver.VersionRule = null) { this.registryId = registryId; this.dataFilePath = dataFilePath; + this.versionRule = versionRule == null ? "1.0.x" : versionRule; this.entries = new Map(); } @@ -125,6 +133,13 @@ abstract class BaseRegistry & Constructible + { + var entryStr:String = loadEntryFile(id); + var entryVersion:thx.semver.Version = VersionUtil.getVersionFromJSON(entryStr); + return entryVersion; + } + function log(message:String):Void { trace('[' + registryId + '] ' + message); @@ -154,10 +169,36 @@ abstract class BaseRegistry & Constructible; + /** + * Read, parse, and validate the JSON data and produce the corresponding data object, + * accounting for old versions of the data. + * + * NOTE: Extend this function to handle migration. + */ + public function parseEntryDataWithMigration(id:String, version:thx.semver.Version):Null + { + // If a version rule is not specified, do not check against it. + if (versionRule == null || VersionUtil.validateVersion(version, versionRule)) + { + return parseEntryData(id); + } + else + { + throw '[${registryId}] Entry ${id} does not support migration.'; + } + + // Example: + // if (VersionUtil.validateVersion(version, "0.1.x")) { + // return parseEntryData_v0_1_x(id); + // } else { + // super.parseEntryDataWithMigration(id, version); + // } + } + /** * Retrieve the list of scripted class names to load. * @return An array of scripted class names. diff --git a/source/funkin/data/level/LevelRegistry.hx b/source/funkin/data/level/LevelRegistry.hx index 54ed81093..36ce883ea 100644 --- a/source/funkin/data/level/LevelRegistry.hx +++ b/source/funkin/data/level/LevelRegistry.hx @@ -11,13 +11,15 @@ class LevelRegistry extends BaseRegistry * Handle breaking changes by incrementing this value * and adding migration to the `migrateStageData()` function. */ - public static final LEVEL_DATA_VERSION:String = "1.0.0"; + public static final LEVEL_DATA_VERSION:thx.semver.Version = "1.0.0"; + + public static final LEVEL_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; public static final instance:LevelRegistry = new LevelRegistry(); public function new() { - super('LEVEL', 'levels'); + super('LEVEL', 'levels', LEVEL_DATA_VERSION_RULE); } /** @@ -34,7 +36,7 @@ class LevelRegistry extends BaseRegistry if (parser.errors.length > 0) { - trace('Failed to parse entry data: ${id}'); + trace('[${registryId}] Failed to parse entry data: ${id}'); for (error in parser.errors) { trace(error); diff --git a/source/funkin/data/notestyle/NoteStyleRegistry.hx b/source/funkin/data/notestyle/NoteStyleRegistry.hx index d666a037c..65f6f627a 100644 --- a/source/funkin/data/notestyle/NoteStyleRegistry.hx +++ b/source/funkin/data/notestyle/NoteStyleRegistry.hx @@ -11,7 +11,9 @@ class NoteStyleRegistry extends BaseRegistry * Handle breaking changes by incrementing this value * and adding migration to the `migrateNoteStyleData()` function. */ - public static final NOTE_STYLE_DATA_VERSION:String = "1.0.0"; + public static final NOTE_STYLE_DATA_VERSION:thx.semver.Version = "1.0.0"; + + public static final NOTE_STYLE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; public static final DEFAULT_NOTE_STYLE_ID:String = "funkin"; @@ -19,7 +21,7 @@ class NoteStyleRegistry extends BaseRegistry public function new() { - super('NOTESTYLE', 'notestyles'); + super('NOTESTYLE', 'notestyles', NOTE_STYLE_DATA_VERSION_RULE); } public function fetchDefault():NoteStyle @@ -43,7 +45,7 @@ class NoteStyleRegistry extends BaseRegistry if (parser.errors.length > 0) { - trace('Failed to parse entry data: ${id}'); + trace('[${registryId}] Failed to parse entry data: ${id}'); for (error in parser.errors) { trace(error); diff --git a/source/funkin/freeplayStuff/DJBoyfriend.hx b/source/funkin/freeplayStuff/DJBoyfriend.hx index b109fb03f..5bee4129a 100644 --- a/source/funkin/freeplayStuff/DJBoyfriend.hx +++ b/source/funkin/freeplayStuff/DJBoyfriend.hx @@ -40,27 +40,6 @@ class DJBoyfriend extends FlxSprite { super.update(elapsed); - if (FlxG.keys.justPressed.LEFT) - { - animOffsets["confirm"] = [animOffsets["confirm"][0] + 1, animOffsets["confirm"][1]]; - applyAnimOffset(); - } - else if (FlxG.keys.justPressed.RIGHT) - { - animOffsets["confirm"] = [animOffsets["confirm"][0] - 1, animOffsets["confirm"][1]]; - applyAnimOffset(); - } - else if (FlxG.keys.justPressed.UP) - { - animOffsets["confirm"] = [animOffsets["confirm"][0], animOffsets["confirm"][1] + 1]; - applyAnimOffset(); - } - else if (FlxG.keys.justPressed.DOWN) - { - animOffsets["confirm"] = [animOffsets["confirm"][0], animOffsets["confirm"][1] - 1]; - applyAnimOffset(); - } - switch (currentState) { case Intro: diff --git a/source/funkin/freeplayStuff/SongMenuItem.hx b/source/funkin/freeplayStuff/SongMenuItem.hx index 3d9f9dd04..37198f6d7 100644 --- a/source/funkin/freeplayStuff/SongMenuItem.hx +++ b/source/funkin/freeplayStuff/SongMenuItem.hx @@ -103,9 +103,6 @@ class SongMenuItem extends FlxSpriteGroup y = CoolUtil.coolLerp(y, targetPos.y, 0.4); } - if (FlxG.keys.justPressed.ALT) selected = false; - if (FlxG.keys.justPressed.CONTROL) selected = true; - super.update(elapsed); } diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index 1ff2c0caa..3f5752acc 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -24,7 +24,7 @@ class PolymodHandler * Bug fixes increment the patch version, new features increment the minor version. * Changes that break old mods increment the major version. */ - static final API_VERSION = "0.1.0"; + static final API_VERSION:String = "0.1.0"; /** * Where relative to the executable that mods are located. diff --git a/source/funkin/modding/module/ModuleHandler.hx b/source/funkin/modding/module/ModuleHandler.hx index 5a1c4dd6a..3cc7b7984 100644 --- a/source/funkin/modding/module/ModuleHandler.hx +++ b/source/funkin/modding/module/ModuleHandler.hx @@ -67,19 +67,26 @@ class ModuleHandler { modulePriorityOrder = moduleCache.keys().array(); - modulePriorityOrder.sort(function(a:String, b:String):Int { - var aModule:Module = moduleCache.get(a); - var bModule:Module = moduleCache.get(b); + modulePriorityOrder.sort(sortByPriority); + } - if (aModule.priority != bModule.priority) - { - return aModule.priority - bModule.priority; - } - else - { - return SortUtil.alphabetically(a, b); - } - }); + /** + * Given two module IDs, sort them by priority. + * @return 1 or -1 depending on which module has a higher priority. + */ + static function sortByPriority(a:String, b:String) + { + var aModule:Module = moduleCache.get(a); + var bModule:Module = moduleCache.get(b); + + if (aModule.priority != bModule.priority) + { + return aModule.priority - bModule.priority; + } + else + { + return SortUtil.alphabetically(a, b); + } } public static function getModule(moduleId:String):Module diff --git a/source/funkin/play/HealthIcon.hx b/source/funkin/play/HealthIcon.hx index e4802b99c..7785fb4b1 100644 --- a/source/funkin/play/HealthIcon.hx +++ b/source/funkin/play/HealthIcon.hx @@ -146,13 +146,13 @@ class HealthIcon extends FlxSprite */ public function toggleOldIcon():Void { - if (characterId == 'beta') + if (characterId == 'bf-old') { characterId = PlayState.instance.currentPlayerId; } else { - characterId = 'beta'; + characterId = 'bf-old'; } } diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a28c35c67..d01c7b049 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -666,14 +666,6 @@ class PlayState extends MusicBeatSubState super.update(elapsed); - if (FlxG.keys.justPressed.U) - { - // hack for HaxeUI generation, doesn't work unless persistentUpdate is false at state creation!! - disableKeys = true; - persistentUpdate = false; - openSubState(new StageOffsetSubState()); - } - updateHealthBar(); updateScoreText(); diff --git a/source/funkin/play/character/CharacterData.hx b/source/funkin/play/character/CharacterData.hx index 18a537a40..710eb884b 100644 --- a/source/funkin/play/character/CharacterData.hx +++ b/source/funkin/play/character/CharacterData.hx @@ -382,7 +382,7 @@ class CharacterDataParser input.version = CHARACTER_DATA_VERSION; } - if (!VersionUtil.validateVersion(input.version, CHARACTER_DATA_VERSION_RULE)) + if (!VersionUtil.validateVersionStr(input.version, CHARACTER_DATA_VERSION_RULE)) { trace('ERROR: Could not load character data for "$id": bad version (got ${input.version}, expected ${CHARACTER_DATA_VERSION_RULE})'); return null; diff --git a/source/funkin/play/cutscene/dialogue/Conversation.hx b/source/funkin/play/cutscene/dialogue/Conversation.hx index 0816e1d25..a6851f0f9 100644 --- a/source/funkin/play/cutscene/dialogue/Conversation.hx +++ b/source/funkin/play/cutscene/dialogue/Conversation.hx @@ -5,7 +5,7 @@ import flixel.group.FlxSpriteGroup; import flixel.util.FlxColor; import flixel.tweens.FlxTween; import flixel.tweens.FlxEase; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import funkin.util.SortUtil; import flixel.util.FlxSort; import funkin.modding.events.ScriptEvent; @@ -18,7 +18,7 @@ import flixel.addons.display.FlxPieDial; /** * A high-level handler for dialogue. - * + * * This shit is great for modders but it's pretty elaborate for how much it'll actually be used, lolol. -Eric */ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass @@ -299,7 +299,7 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass /** * Dispatch an event to attempt to advance the conversation. * This is done once at the start of the conversation, and once whenever the user presses CONFIRM to advance the conversation. - * + * * The broadcast event may be cancelled by modules or ScriptedConversations. This will prevent the conversation from actually advancing. * This is useful if you want to manually play an animation or something. */ @@ -365,7 +365,7 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass /** * Dispatch an event to attempt to immediately end the conversation. - * + * * The broadcast event may be cancelled by modules or ScriptedConversations. This will prevent the conversation from being cancelled. * This is useful if you want to prevent an animation from being skipped or something. */ @@ -567,7 +567,7 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass /** * As this event is dispatched to the Conversation, it is also dispatched to the active speaker. - * @param event + * @param event */ function propagateEvent(event:ScriptEvent):Void { diff --git a/source/funkin/play/notes/notestyle/NoteStyle.hx b/source/funkin/play/notes/notestyle/NoteStyle.hx index 6cb9e7cdc..fd45342a0 100644 --- a/source/funkin/play/notes/notestyle/NoteStyle.hx +++ b/source/funkin/play/notes/notestyle/NoteStyle.hx @@ -104,6 +104,10 @@ class NoteStyle implements IRegistryEntry noteFrames = Paths.getSparrowAtlas(getNoteAssetPath(), getNoteAssetLibrary()); + if (noteFrames == null) { + throw 'Could not load note frames for note style: $id'; + } + noteFrames.parent.persist = true; return noteFrames; @@ -161,7 +165,8 @@ class NoteStyle implements IRegistryEntry { if (raw) { - var rawPath:Null = _data?.assets?.holdNote?.assetPath; + // TODO: figure out why ?. didn't work here + var rawPath:Null = (_data?.assets?.holdNote == null) ? null : _data?.assets?.holdNote?.assetPath; return (rawPath == null) ? fallback.getHoldNoteAssetPath(true) : rawPath; } @@ -299,6 +304,6 @@ class NoteStyle implements IRegistryEntry public function _fetchData(id:String):Null { - return NoteStyleRegistry.instance.parseEntryData(id); + return NoteStyleRegistry.instance.parseEntryDataWithMigration(id, NoteStyleRegistry.instance.fetchEntryVersion(id)); } } diff --git a/source/funkin/play/song/SongMigrator.hx b/source/funkin/play/song/SongMigrator.hx index f561c4d3e..bb8718bb7 100644 --- a/source/funkin/play/song/SongMigrator.hx +++ b/source/funkin/play/song/SongMigrator.hx @@ -32,7 +32,7 @@ class SongMigrator { if (jsonData.version != null) { - if (VersionUtil.validateVersion(jsonData.version, CHART_VERSION_RULE)) + if (VersionUtil.validateVersionStr(jsonData.version, CHART_VERSION_RULE)) { trace('Song (${songId}) metadata version (${jsonData.version}) is valid and up-to-date.'); @@ -70,7 +70,7 @@ class SongMigrator { if (jsonData.version) { - if (VersionUtil.validateVersion(jsonData.version, CHART_VERSION_RULE)) + if (VersionUtil.validateVersionStr(jsonData.version, CHART_VERSION_RULE)) { trace('Song (${songId}) chart version (${jsonData.version}) is valid and up-to-date.'); diff --git a/source/funkin/play/stage/StageData.hx b/source/funkin/play/stage/StageData.hx index de8804cfb..867c6e1a5 100644 --- a/source/funkin/play/stage/StageData.hx +++ b/source/funkin/play/stage/StageData.hx @@ -217,7 +217,7 @@ class StageDataParser return null; } - if (!VersionUtil.validateVersion(input.version, STAGE_DATA_VERSION_RULE)) + if (!VersionUtil.validateVersionStr(input.version, STAGE_DATA_VERSION_RULE)) { trace('ERROR: Could not load stage data for "$id": bad version (got ${input.version}, expected ${STAGE_DATA_VERSION_RULE})'); return null; diff --git a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx index 43e8ac96c..df5a25b62 100644 --- a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx +++ b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx @@ -257,6 +257,7 @@ class ChartEditorDialogHandler * @param closable Whether the dialog can be closed by the user. * @return The dialog that was opened. */ + @:haxe.warning("-WVarInit") public static function openUploadInstDialog(state:ChartEditorState, ?closable:Bool = true):Dialog { var dialog:Dialog = openDialog(state, CHART_EDITOR_DIALOG_UPLOAD_INST_LAYOUT, true, closable); @@ -416,6 +417,7 @@ class ChartEditorDialogHandler * @param state The ChartEditorState instance. * @return The dialog to open. */ + @:haxe.warning("-WVarInit") public static function openSongMetadataDialog(state:ChartEditorState):Dialog { var dialog:Dialog = openDialog(state, CHART_EDITOR_DIALOG_SONG_METADATA_LAYOUT, true, false); diff --git a/source/funkin/ui/debug/charting/ChartEditorEventSprite.hx b/source/funkin/ui/debug/charting/ChartEditorEventSprite.hx index 768e0be52..2cd9ab2fe 100644 --- a/source/funkin/ui/debug/charting/ChartEditorEventSprite.hx +++ b/source/funkin/ui/debug/charting/ChartEditorEventSprite.hx @@ -95,7 +95,7 @@ class ChartEditorEventSprite extends FlxSprite public function correctAnimationName(name:String):String { if (this.animation.exists(name)) return name; - trace('Warning: Invalid animation name "' + name + '" for song event. Using "${DEFAULT_EVENT}"'); + trace('Warning: Invalid animation name "${name}" for song event. Using "${DEFAULT_EVENT}"'); return DEFAULT_EVENT; } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index e1ed75b06..aa6e70714 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -15,7 +15,7 @@ import flixel.addons.transition.FlxTransitionableState; import flixel.input.keyboard.FlxKey; import flixel.math.FlxPoint; import flixel.math.FlxRect; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.tweens.misc.VarTween; diff --git a/source/funkin/ui/story/Level.hx b/source/funkin/ui/story/Level.hx index 7913ac8ca..1e5d60bf3 100644 --- a/source/funkin/ui/story/Level.hx +++ b/source/funkin/ui/story/Level.hx @@ -181,6 +181,6 @@ class Level implements IRegistryEntry public function _fetchData(id:String):Null { - return LevelRegistry.instance.parseEntryData(id); + return LevelRegistry.instance.parseEntryDataWithMigration(id, LevelRegistry.instance.fetchEntryVersion(id)); } } diff --git a/source/funkin/util/BezierUtil.hx b/source/funkin/util/BezierUtil.hx index 56d20cf48..b3cf51d1d 100644 --- a/source/funkin/util/BezierUtil.hx +++ b/source/funkin/util/BezierUtil.hx @@ -15,7 +15,7 @@ class BezierUtil /** * Linearly interpolate between three values. - * Depending on p, 0 = a, 0.5 = b, 1 = c, 0.25 = halfway between a and c, etc. + * Depending on p, 0 = a, 0.5 = b, 1 = c, 0.25 = halfway between a and b, etc. */ static inline function mix3(p:Float, a:Float, b:Float, c:Float):Float { @@ -32,11 +32,6 @@ class BezierUtil return mix2(p, mix4(p, a, b, c, d), mix4(p, b, c, d, e)); } - static inline function mix6(p:Float, a:Float, b:Float, c:Float, d:Float, e:Float, f:Float):Float - { - return mix2(p, mix5(p, a, b, c, d, e), mix5(p, b, c, d, e, f)); - } - /** * A bezier curve with two points. * This is really just linear interpolation but whatever. diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index c06911e4e..71cfe7b8e 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -88,12 +88,17 @@ class Constants public static final COLOR_HEALTH_BAR_GREEN:FlxColor = 0xFF66FF33; /** - * The base colors of the notes. + * The base colors used by notes. */ - public static final COLOR_NOTES:Array = [0xFFFF22AA, 0xFF00EEFF, 0xFF00CC00, 0xFFCC1111]; + public static var COLOR_NOTES:Array = [ + 0xFFFF22AA, // left (0) + 0xFF00EEFF, // down (1) + 0xFF00CC00, // up (2) + 0xFFCC1111 // right (3) + ]; /** - * STAGE DEFAULTS + * GAME DEFAULTS */ // ============================== diff --git a/source/funkin/util/DateUtil.hx b/source/funkin/util/DateUtil.hx index 715371f80..72838477c 100644 --- a/source/funkin/util/DateUtil.hx +++ b/source/funkin/util/DateUtil.hx @@ -2,9 +2,10 @@ package funkin.util; class DateUtil { - public static function generateTimestamp():String + public static function generateTimestamp(?date:Date = null):String { - var date = Date.now(); + if (date == null) date = Date.now(); + return '${date.getFullYear()}-${Std.string(date.getMonth() + 1).lpad('0', 2)}-${Std.string(date.getDate()).lpad('0', 2)}-${Std.string(date.getHours()).lpad('0', 2)}-${Std.string(date.getMinutes()).lpad('0', 2)}-${Std.string(date.getSeconds()).lpad('0', 2)}'; } diff --git a/source/funkin/util/SaveDataUtil.hx b/source/funkin/util/SaveDataUtil.hx deleted file mode 100644 index 202536aad..000000000 --- a/source/funkin/util/SaveDataUtil.hx +++ /dev/null @@ -1 +0,0 @@ -package funkin.util; diff --git a/source/funkin/util/SerializerUtil.hx b/source/funkin/util/SerializerUtil.hx index d731aee8f..0075e83c0 100644 --- a/source/funkin/util/SerializerUtil.hx +++ b/source/funkin/util/SerializerUtil.hx @@ -11,26 +11,21 @@ typedef ScoreInput = var t:Int; // Start timestamp } +/** + * A class of functions dedicated to serializing and deserializing data. + */ class SerializerUtil { static final INDENT_CHAR = "\t"; /** * Convert a Haxe object to a JSON string. - **/ + */ public static function toJSON(input:Dynamic, ?pretty:Bool = true):String { return Json.stringify(input, replacer, pretty ? INDENT_CHAR : null); } - /** - * Convert a JSON string to a Haxe object of the chosen type. - */ - public static function fromJSONTyped(input:String, type:Class):T - { - return cast Json.parse(input); - } - /** * Convert a JSON string to a Haxe object. */ @@ -76,14 +71,19 @@ class SerializerUtil if (Std.isOfType(value, String)) return value; // Stringify Version objects. - var valueVersion:thx.semver.Version = cast value; - var result = '${valueVersion.major}.${valueVersion.minor}.${valueVersion.patch}'; - if (valueVersion.hasPre) result += '-${valueVersion.pre}'; - if (valueVersion.hasBuild) result += '+${valueVersion.build}'; - return result; + return serializeVersion(cast value); } // Else, return the value as-is. return value; } + + static inline function serializeVersion(value:thx.semver.Version):String + { + var result = '${value.major}.${value.minor}.${value.patch}'; + if (value.hasPre) result += '-${value.pre}'; + // TODO: Merge fix for version.hasBuild + if (value.build.length > 0) result += '+${value.build}'; + return result; + } } diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx index 08cde69a6..368bb12de 100644 --- a/source/funkin/util/VersionUtil.hx +++ b/source/funkin/util/VersionUtil.hx @@ -14,13 +14,11 @@ class VersionUtil * Checks that a given verison number satisisfies a given version rule. * Version rule can be complex, e.g. "1.0.x" or ">=1.0.0,<1.1.0", or anything NPM supports. */ - public static function validateVersion(version:String, versionRule:String):Bool + public static function validateVersion(version:thx.semver.Version, versionRule:thx.semver.VersionRule):Bool { try { - var v:Version = version; // Perform a cast. - var vr:VersionRule = versionRule; // Perform a cast. - return v.satisfies(vr); + return version.satisfies(versionRule); } catch (e) { @@ -28,4 +26,38 @@ class VersionUtil return false; } } + + /** + * Checks that a given verison number satisisfies a given version rule. + * Version rule can be complex, e.g. "1.0.x" or ">=1.0.0,<1.1.0", or anything NPM supports. + */ + public static function validateVersionStr(version:String, versionRule:String):Bool + { + try + { + var version:thx.semver.Version = version; + var versionRule:thx.semver.VersionRule = versionRule; + return version.satisfies(versionRule); + } + catch (e) + { + trace('[VERSIONUTIL] Invalid semantic version: ${version}'); + return false; + } + } + + /** + * Get and parse the semantic version from a JSON string. + * @param input The JSON string to parse. + * @return The semantic version, or null if it could not be parsed. + */ + public static function getVersionFromJSON(input:String):Null + { + var parsed = SerializerUtil.fromJSON(input); + if (parsed == null) return null; + if (parsed.version == null) return null; + var versionStr:String = parsed.version; // Dynamic -> String cast + var version:thx.semver.Version = versionStr; // Implicit, not explicit, cast. + return version; + } } diff --git a/source/funkin/util/assets/FlxAnimationUtil.hx b/source/funkin/util/assets/FlxAnimationUtil.hx index 0e32a1918..f94dc4dc3 100644 --- a/source/funkin/util/assets/FlxAnimationUtil.hx +++ b/source/funkin/util/assets/FlxAnimationUtil.hx @@ -19,7 +19,7 @@ class FlxAnimationUtil if (anim.frameIndices != null && anim.frameIndices.length > 0) { // trace('addByIndices(${anim.name}, ${anim.prefix}, ${anim.frameIndices}, ${frameRate}, ${looped}, ${flipX}, ${flipY})'); - target.animation.addByIndices(anim.name, anim.prefix, anim.frameIndices, "", frameRate, looped, flipX, flipY); + target.animation.addByIndices(anim.name, anim.prefix, anim.frameIndices, '', frameRate, looped, flipX, flipY); // trace('RESULT:${target.animation.getAnimationList()}'); } else diff --git a/source/funkin/util/tools/ArraySortTools.hx b/source/funkin/util/tools/ArraySortTools.hx index 3af114b98..9a3f8b349 100644 --- a/source/funkin/util/tools/ArraySortTools.hx +++ b/source/funkin/util/tools/ArraySortTools.hx @@ -108,6 +108,9 @@ class ArraySortTools input[i] = input[j]; input[j] = temp; } + + // Don't expect to get here. + return -1; } /** diff --git a/source/funkin/util/tools/MapTools.hx b/source/funkin/util/tools/MapTools.hx index 461b88bbf..739c5efdb 100644 --- a/source/funkin/util/tools/MapTools.hx +++ b/source/funkin/util/tools/MapTools.hx @@ -27,6 +27,7 @@ class MapTools /** * Return a list of keys from the map (as an array, rather than an iterator). + * TODO: Rename this? */ public static function keyValues(map:Map):Array { diff --git a/source/funkin/util/tools/StringTools.hx b/source/funkin/util/tools/StringTools.hx index 8ff76a080..0585ffeae 100644 --- a/source/funkin/util/tools/StringTools.hx +++ b/source/funkin/util/tools/StringTools.hx @@ -51,6 +51,7 @@ class StringTools /** * Parses the string data as JSON and returns the resulting object. + * This is here so you can use `string.parseJSON()` when `using StringTools`. * * @return The parsed object. */ diff --git a/tests/unit/.gitignore b/tests/unit/.gitignore new file mode 100644 index 000000000..abb6c9cf9 --- /dev/null +++ b/tests/unit/.gitignore @@ -0,0 +1,7 @@ + +bin/ +# auto-generated +source/TestSuite.hx +.temp/ +report/ +build/ diff --git a/tests/unit/.munit b/tests/unit/.munit new file mode 100644 index 000000000..61de57963 --- /dev/null +++ b/tests/unit/.munit @@ -0,0 +1,7 @@ +version=2.3.5 +src=source +bin=bin +report=report +hxml=test.hxml +classPaths=../../source +coveragePackages=funkin diff --git a/tests/unit/.vscode/launch.json b/tests/unit/.vscode/launch.json new file mode 100644 index 000000000..a255f1644 --- /dev/null +++ b/tests/unit/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Lime", + "type": "lime", + "request": "launch" + } + ] +} \ No newline at end of file diff --git a/tests/unit/README.md b/tests/unit/README.md new file mode 100644 index 000000000..00fed78e5 --- /dev/null +++ b/tests/unit/README.md @@ -0,0 +1,50 @@ +Flixel Unit Tests +----------------- + +This is a unit test project using [munit](https://github.com/massiveinteractive/MassiveUnit). It's good practice to add tests for fixed bugs or new features. + +TODO Make sure the unit tests are automatically run on GitHub Actions. + +There's a 1:1 mapping between `.hx` files in `source/` and the unit test project - tests for `funkin.Conductor` go into `funkin.ConductorTest` etc. + +### Building + +Run one of the `test-*.hxml` files in this directory to run the tests on that specific target, e.g. `haxe test-cpp.hxml`. Currently supported are: + +- `web` (HTML5) +- `cpp` (Native) + +Alternatively, this can be done from within Visual Studio Code - (`F1` -> `Tasks: Run Task` -> Choose the target to test). + +#### Adding Tests + +- Run `haxelib run munit create com.FooBarTest -for com.Foo` +- Use `@:allow(full.package.name.ClassName)` to allow a test class to call private functions. +- Use `mockatoo.Mockatoo.mock(ClassName)` to mock a class. See [Mockatoo docs](https://github.com/misprintt/mockatoo). + +#### Functions + +- `@Before` functions are named `before()` +- Each `@Test` function starts with `test` and describes what exactly it tests. This can lead to long function names like `FlxEmitter#testStartShouldNotReviveMembers()` and serves as self-documentation. +- Another thing that helps with self-documentation is adding a comment for tests that are related an issue on GitHub. + + ```haxe + @Test // #1203 + function testColorWithAlphaComparison() + ``` + +### `FunkinTest` base class + +Test classes extend `FunkinTest`, which is a base class with some utility functions for testing. + +### `step()` + +`step()` advances the `FlxGame` exactly one step. This is useful for tests that depend on game time advancing / `FlxGame#step()` being executed, such as physics of `add()`ed objects, state switches, or just time passing for tweens or timers. + +There are two parameters: +- `steps` - specifies the amount of steps to advance (defaults to 1) +- `callback` - an optional callback function that is executed after each step + +### `testDestroy()` + +`testDestroy()` tests whether an `IFlxDestroyable` can safely be `destroy()`ed more than once (null reference errors are fairly common here). For this, `destroyable` has to be set during `before()` of the test class. diff --git a/tests/unit/assets/preload/data/anotherFile.txt b/tests/unit/assets/preload/data/anotherFile.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/assets/preload/data/levels/test.json b/tests/unit/assets/preload/data/levels/test.json new file mode 100644 index 000000000..8b004e213 --- /dev/null +++ b/tests/unit/assets/preload/data/levels/test.json @@ -0,0 +1,47 @@ +{ + "version": "1.0.0", + "name": "TEACHING TIME", + "titleAsset": "storymenu/titles/tutorial", + "props": [ + { + "assetPath": "storymenu/props/gf", + "scale": 1.0, + "danceEvery": 2, + "offsets": [80, 80], + "animations": [ + { + "name": "danceLeft", + "prefix": "idle0", + "frameIndices": [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] + }, + { + "name": "danceRight", + "prefix": "idle0", + "frameIndices": [ + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 + ] + } + ] + }, + { + "assetPath": "storymenu/props/bf", + "scale": 1.0, + "danceEvery": 2, + "offsets": [150, 80], + "animations": [ + { + "name": "idle", + "prefix": "idle0", + "frameRate": 24 + }, + { + "name": "confirm", + "prefix": "confirm0", + "frameRate": 24 + } + ] + } + ], + "background": "#F9CF51", + "songs": ["tutorial"] +} diff --git a/tests/unit/assets/preload/data/mytype/blablabla.json b/tests/unit/assets/preload/data/mytype/blablabla.json new file mode 100644 index 000000000..cf7d16746 --- /dev/null +++ b/tests/unit/assets/preload/data/mytype/blablabla.json @@ -0,0 +1,6 @@ +{ + "version": "1.0.0", + "id": "blablabla", + "name": "blablabla API", + "data": [] +} diff --git a/tests/unit/assets/preload/data/mytype/fizzbuzz.json b/tests/unit/assets/preload/data/mytype/fizzbuzz.json new file mode 100644 index 000000000..9b160ff55 --- /dev/null +++ b/tests/unit/assets/preload/data/mytype/fizzbuzz.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "id": "fizzbuzz", + "name": "nodejs-express-mongoose-demo", + "data": [ + { + "foo": "bar", + "bar": "foo" + }, + { + "foo": "baz", + "bar": "baz" + } + ] +} diff --git a/tests/unit/assets/preload/data/mytype/foobar.json b/tests/unit/assets/preload/data/mytype/foobar.json new file mode 100644 index 000000000..0377a2262 --- /dev/null +++ b/tests/unit/assets/preload/data/mytype/foobar.json @@ -0,0 +1,5 @@ +{ + "version": "0.1.0", + "id": 1, + "name": "My First App" +} diff --git a/tests/unit/assets/preload/data/mytype/junk.json b/tests/unit/assets/preload/data/mytype/junk.json new file mode 100644 index 000000000..13ae5d1a0 --- /dev/null +++ b/tests/unit/assets/preload/data/mytype/junk.json @@ -0,0 +1,4 @@ +{ + "version": "3.0.0", + "info": "stuff" +} diff --git a/tests/unit/assets/preload/data/notestyles/funkin.json b/tests/unit/assets/preload/data/notestyles/funkin.json new file mode 100644 index 000000000..abb039150 --- /dev/null +++ b/tests/unit/assets/preload/data/notestyles/funkin.json @@ -0,0 +1,59 @@ +{ + "version": "1.0.0", + "name": "Funkin'", + "author": "PhantomArcade", + "fallback": null, + "assets": { + "note": { + "assetPath": "shared:arrows", + "scale": 1.0, + "isPixel": true, + "data": { + "left": { "prefix": "noteLeft" }, + "down": { "prefix": "noteDown" }, + "up": { "prefix": "noteUp" }, + "right": { "prefix": "noteRight" } + } + }, + "noteStrumline": { + "assetPath": "shared:arrows", + "scale": 1.0, + "offsets": [28, 32], + "isPixel": true, + "data": { + "leftStatic": { "prefix": "staticLeft0" }, + "leftPress": { "prefix": "pressedLeft0" }, + "leftConfirm": { "prefix": "confirmLeft0" }, + "leftConfirmHold": { "prefix": "confirmLeft0" }, + "downStatic": { "prefix": "staticDown0" }, + "downPress": { "prefix": "pressedDown0" }, + "downConfirm": { "prefix": "confirmDown0" }, + "downConfirmHold": { "prefix": "confirmDown0" }, + "upStatic": { "prefix": "staticUp0" }, + "upPress": { "prefix": "pressedUp0" }, + "upConfirm": { "prefix": "confirmUp0" }, + "upConfirmHold": { "prefix": "confirmUp0" }, + "rightStatic": { "prefix": "staticRight0" }, + "rightPress": { "prefix": "pressedRight0" }, + "rightConfirm": { "prefix": "confirmRight0" }, + "rightConfirmHold": { "prefix": "confirmRight0" } + } + }, + "holdNote": { + "assetPath": "NOTE_hold_assets", + "data": {} + }, + "noteSplash": { + "assetPath": "", + "data": { + "enabled": true + } + }, + "holdNoteCover": { + "assetPath": "", + "data": { + "enabled": true + } + } + } +} diff --git a/tests/unit/assets/preload/data/notestyles/test2.json b/tests/unit/assets/preload/data/notestyles/test2.json new file mode 100644 index 000000000..95a669077 --- /dev/null +++ b/tests/unit/assets/preload/data/notestyles/test2.json @@ -0,0 +1,18 @@ +{ + "version": "1.0.0", + "name": "Test2", + "author": "Eric", + "fallback": "funkin", + "assets": { + "note": { + "assetPath": "shared:coolstuff", + "scale": 1.8, + "data": { + "left": { "prefix": "noteLeft1" }, + "down": { "prefix": "noteDown3" }, + "up": { "prefix": "noteUp2" }, + "right": { "prefix": "noteRight4" } + } + } + } +} diff --git a/tests/unit/assets/preload/data/test/blablabla.json b/tests/unit/assets/preload/data/test/blablabla.json new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/assets/preload/data/test/test1.json b/tests/unit/assets/preload/data/test/test1.json new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/assets/preload/data/test/test2.json b/tests/unit/assets/preload/data/test/test2.json new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/assets/shared/images/arrows.png b/tests/unit/assets/shared/images/arrows.png new file mode 100644 index 0000000000000000000000000000000000000000..a443684327b409e3297d9456cb28afddd889b499 GIT binary patch literal 4806 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 Iso@a*KZ!k4q5uE@ literal 0 HcmV?d00001 diff --git a/tests/unit/assets/shared/images/arrows.xml b/tests/unit/assets/shared/images/arrows.xml new file mode 100644 index 000000000..8f3355462 --- /dev/null +++ b/tests/unit/assets/shared/images/arrows.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/unit/project.xml b/tests/unit/project.xml new file mode 100644 index 000000000..ccfadce8c --- /dev/null +++ b/tests/unit/project.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/unit/source/FunkinAssert.hx b/tests/unit/source/FunkinAssert.hx new file mode 100644 index 000000000..acfba6723 --- /dev/null +++ b/tests/unit/source/FunkinAssert.hx @@ -0,0 +1,77 @@ +package; + +import flixel.math.FlxPoint; +import flixel.math.FlxRect; +import haxe.PosInfos; +import massive.munit.Assert; + +using flixel.util.FlxArrayUtil; + +/** + * @see https://github.com/HaxeFlixel/flixel/tree/dev/tests/unit + */ +class FunkinAssert +{ + /** + * Assert if `expected` is within `margin` of `actual`, and fail if not. + * Useful for comparting Float values. + * + * @param expected The expected value of the test. + * @param actual The actual value of the test. + * @param margin The allowed margin of error between the expected and actual values. + * @param info Info on the position this function was called from. Magic value, passed automatically. + */ + public static function areNear(expected:Float, actual:Float, margin:Float = 0.001, ?info:PosInfos):Void + { + if (areNearHelper(expected, actual)) Assert.assertionCount++; + else + Assert.fail('Value [$actual] is not within [$margin] of [$expected]', info); + } + + public static function rectsNear(expected:FlxRect, actual:FlxRect, margin:Float = 0.001, ?info:PosInfos):Void + { + var areNear = areNearHelper(expected.x, actual.x, margin) + && areNearHelper(expected.y, actual.y, margin) + && areNearHelper(expected.width, actual.width, margin) + && areNearHelper(expected.height, actual.height, margin); + + if (areNear) Assert.assertionCount++; + else + Assert.fail('Value [$actual] is not within [$margin] of [$expected]', info); + } + + static function areNearHelper(expected:Float, actual:Float, margin:Float = 0.001):Bool + { + return actual >= expected - margin && actual <= expected + margin; + } + + public static function arraysEqual(expected:Array, actual:Array, ?info:PosInfos):Void + { + if (expected.equals(actual)) Assert.assertionCount++; + else + Assert.fail('\nExpected\n ${expected}\nbut was\n ${actual}\n', info); + } + + public static function arraysNotEqual(expected:Array, actual:Array, ?info:PosInfos):Void + { + if (!expected.equals(actual)) Assert.assertionCount++; + else + Assert.fail('\nValue\n ${actual}\nwas equal to\n ${expected}\n', info); + } + + public static function pointsEqual(expected:FlxPoint, actual:FlxPoint, ?msg:String, ?info:PosInfos) + { + if (expected.equals(actual)) Assert.assertionCount++; + else if (msg != null) Assert.fail(msg, info); + else + Assert.fail("Value [" + actual + "] was not equal to expected value [" + expected + "]", info); + } + + public static function pointsNotEqual(expected:FlxPoint, actual:FlxPoint, ?msg:String, ?info:PosInfos) + { + if (!expected.equals(actual)) Assert.assertionCount++; + else if (msg != null) Assert.fail(msg, info); + else + Assert.fail("Value [" + actual + "] was equal to value [" + expected + "]", info); + } +} diff --git a/tests/unit/source/FunkinTest.hx b/tests/unit/source/FunkinTest.hx new file mode 100644 index 000000000..7e0e0b26c --- /dev/null +++ b/tests/unit/source/FunkinTest.hx @@ -0,0 +1,105 @@ +package; + +import openfl.utils.Assets; +import openfl.errors.Error; +import flixel.FlxG; +import flixel.FlxState; +import flixel.tweens.FlxTween; +import flixel.util.FlxDestroyUtil.IFlxDestroyable; +import massive.munit.Assert; + +/** + * @see https://github.com/HaxeFlixel/flixel/tree/dev/tests/unit + */ +class FunkinTest +{ + public static final MS_PER_STEP:Float = 1.0 / 60.0 * 1000; + + // approx. amount of ticks at 60 fps + static inline var TICKS_PER_FRAME:UInt = 25; + static var totalSteps:UInt = 0; + + var destroyable:IFlxDestroyable; + + public function new() {} + + @After + @:access(flixel) + function after() + { + // Redefine how the game gets the time during tests. + FlxG.game.getTimer = function() { + return totalSteps * TICKS_PER_FRAME; + } + + // make sure we have the same starting conditions for each test + resetGame(); + } + + /** + * Advance the game simulation. + * @param steps The amount to advance the game by. + * @param callback A function to call after each step. + */ + @:access(flixel) + function step(steps:UInt = 1, ?callback:Void->Void) + { + for (i in 0...steps) + { + FlxG.game.step(); + if (callback != null) callback(); + totalSteps++; + } + } + + function resetGame() + { + FlxG.resetGame(); + step(); + } + + function switchState(nextState:FlxState) + { + FlxG.switchState(nextState); + step(); + } + + function resetState() + { + FlxG.resetState(); + step(); + } + + @Test + public function testAssert() + { + Assert.areEqual(4, 2 + 2); + } + + @Test + function testDestroy() + { + if (destroyable == null) + { + return; + } + + try + { + destroyable.destroy(); + destroyable.destroy(); + } + catch (e:Error) + { + Assert.fail(e.message); + } + } + + function finishTween(tween:FlxTween) + { + while (!tween.finished) + { + step(); + } + } +} diff --git a/tests/unit/source/MockTest.hx b/tests/unit/source/MockTest.hx new file mode 100644 index 000000000..c1ae0a90d --- /dev/null +++ b/tests/unit/source/MockTest.hx @@ -0,0 +1,60 @@ +package; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.DateUtil; + +class MockTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testMock() + { + // Test that mocking works. + + var mockSprite = mockatoo.Mockatoo.mock(flixel.FlxSprite); + var mockAnim = mockatoo.Mockatoo.mock(flixel.animation.FlxAnimationController); + mockSprite.animation = mockAnim; + + var animData:funkin.data.animation.AnimationData = + { + name: "testAnim", + prefix: "blablabla" + }; + + mockSprite.animation.addByPrefix("testAnim", "blablabla", 24, false, false, false); + + // Verify that the method was called once. + // If not, a VerificationException will be thrown and the test will fail. + mockatoo.Mockatoo.verify(mockAnim.addByPrefix("testAnim", "blablabla", 24, false, false, false), times(1)); + + try + { + // Attempt to verify the method was called. + // This should FAIL, since we didn't call the method. + mockatoo.Mockatoo.verify(mockAnim.addByIndices("testAnim", "blablabla", [], "", 24, false, false, false), times(1)); + Assert.fail("Mocking function should have thrown but didn't."); + } + catch (_:mockatoo.exception.VerificationException) + { + // Expected. + } + } +} diff --git a/tests/unit/source/TestMain.hx b/tests/unit/source/TestMain.hx new file mode 100644 index 000000000..a3fbdb428 --- /dev/null +++ b/tests/unit/source/TestMain.hx @@ -0,0 +1,77 @@ +package; + +import openfl.Lib; +import flixel.FlxGame; +import flixel.FlxState; +import massive.munit.TestRunner; +import massive.munit.client.HTTPClient; +import massive.munit.client.SummaryReportClient; + +/** + * Auto generated Test Application. + * Refer to munit command line tool for more information (haxelib run munit) + */ +class TestMain +{ + /** + * If true, include a report with each ignored test and their descriptions. + */ + static final INCLUDE_IGNORED_REPORT:Bool = false; + + static function main() + { + new TestMain(); + } + + public function new() + { + // Flixel was not designed for unit testing so we can only have one instance for now. + Lib.current.stage.addChild(new FlxGame(640, 480, FlxState, 60, 60, true)); + + var suites = new Array>(); + suites.push(TestSuite); + + #if MCOVER + // Print individual test results alongside coverage results for each test class, + // as well as a final coverage report for the entire test suite. + var innerClient = new massive.munit.client.RichPrintClient(INCLUDE_IGNORED_REPORT); + var client = new mcover.coverage.munit.client.MCoverPrintClient(innerClient); + // Print final test results alongside detailed coverage results for the test suite. + var httpClient = new HTTPClient(new mcover.coverage.munit.client.MCoverSummaryReportClient()); + // NOTE: You can also create a custom ICoverageTestResultClient implementation + + mcover.coverage.MCoverage.getLogger().addClient(new mcover.coverage.client.CodecovJsonPrintClient()); + #else + // Print individual test results. + var client = new massive.munit.client.RichPrintClient(INCLUDE_IGNORED_REPORT); + // Print final test suite results. + var httpClient = new HTTPClient(new SummaryReportClient()); + #end + + var runner = new TestRunner(client); + runner.addResultClient(httpClient); + + runner.completionHandler = completionHandler; + runner.run(suites); + } + + /** + * updates the background color and closes the current browser + * for flash and html targets (useful for continuos integration servers) + */ + function completionHandler(successful:Bool):Void + { + try + { + #if flash + openfl.external.ExternalInterface.call("testResult", successful); + #elseif js + js.Lib.eval("testResult(" + successful + ");"); + #elseif sys + Sys.exit(successful ? 0 : 1); + #end + } + // if run from outside browser can get error which we can ignore + catch (e:Dynamic) {} + } +} diff --git a/tests/unit/source/_template.hxtemplate b/tests/unit/source/_template.hxtemplate new file mode 100644 index 000000000..47a546bd0 --- /dev/null +++ b/tests/unit/source/_template.hxtemplate @@ -0,0 +1,30 @@ +package funkin.play; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.play.PlayState; + +@:access(funkin.play.PlayState) +class Template extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function test() {} +} diff --git a/tests/unit/source/flixel/FlxGTest.hx b/tests/unit/source/flixel/FlxGTest.hx new file mode 100644 index 000000000..5f201a9f0 --- /dev/null +++ b/tests/unit/source/flixel/FlxGTest.hx @@ -0,0 +1,107 @@ +package flixel; + +import massive.munit.Assert; + +@:access(flixel.FlxG) +class FlxGTest extends FunkinTest +{ + @Test function testVERSIONNull():Void + Assert.isNotNull(FlxG.VERSION); + + @Test function testGameNull():Void + Assert.isNotNull(FlxG.game); + + @Test function testStageNull():Void + Assert.isNotNull(FlxG.stage); + + @Test function testStateNull():Void + Assert.isNotNull(FlxG.state); + + @Test function testWorldBoundsNull():Void + Assert.isNotNull(FlxG.worldBounds); + + @Test function testSaveNull():Void + Assert.isNotNull(FlxG.save); + + #if FLX_MOUSE + @Test function testMouseNull():Void + Assert.isNotNull(FlxG.mouse); + #end + + #if FLX_TOUCH + @Test function testTouchNull():Void + Assert.isNotNull(FlxG.touches); + #end + + #if FLX_POINTER_INPUT + @Test function testSwipesNull():Void + Assert.isNotNull(FlxG.swipes); + #end + + #if FLX_KEYBOARD + @Test function testKeysNull():Void + Assert.isNotNull(FlxG.keys); + #end + + #if FLX_GAMEPAD + @Test function testGamepadsNull():Void + Assert.isNotNull(FlxG.gamepads); + #end + + #if android + @Test function testAndroidNull():Void + Assert.isNotNull(FlxG.android); + #end + + #if js + @Test function testHtml5Null():Void + Assert.isNotNull(FlxG.html5); + #end + + @Test function testInputsNull():Void + Assert.isNotNull(FlxG.inputs); + + @Test function testConsoleNull():Void + Assert.isNotNull(FlxG.console); + + @Test function testLogNull():Void + Assert.isNotNull(FlxG.log); + + @Test function testWatchNull():Void + Assert.isNotNull(FlxG.watch); + + @Test function testDebuggerNull():Void + Assert.isNotNull(FlxG.debugger); + + @Test function testVcrNull():Void + Assert.isNotNull(FlxG.vcr); + + @Test function testBitmapNull():Void + Assert.isNotNull(FlxG.bitmap); + + @Test function testCamerasNull():Void + Assert.isNotNull(FlxG.cameras); + + @Test function testPluginsNull():Void + Assert.isNotNull(FlxG.plugins); + + #if FLX_SOUND_SYSTEM + @Test function testSoundNull():Void + Assert.isNotNull(FlxG.sound); + #end + + @Test function testScaleModeNull():Void + Assert.isNotNull(FlxG.scaleMode); + + @Test + function testDefaultWidth():Void + { + Assert.areEqual(640, FlxG.width); + } + + @Test + function testDefaultHeight():Void + { + Assert.areEqual(480, FlxG.height); + } +} diff --git a/tests/unit/source/funkin/ConductorTest.hx b/tests/unit/source/funkin/ConductorTest.hx new file mode 100644 index 000000000..856c52186 --- /dev/null +++ b/tests/unit/source/funkin/ConductorTest.hx @@ -0,0 +1,550 @@ +package funkin; + +import flixel.FlxG; +import flixel.FlxState; +import funkin.Conductor; +import funkin.play.song.SongData.SongTimeChange; +import funkin.util.Constants; +import massive.munit.Assert; + +@:access(funkin.Conductor) +class ConductorTest extends FunkinTest +{ + var conductorState:ConductorState; + + @Before + function before() + { + resetGame(); + + // The ConductorState will advance the conductor when step() is called. + FlxG.switchState(conductorState = new ConductorState()); + + Conductor.reset(); + } + + @Test + function testDefaultValues():Void + { + // NOTE: Expected value comes first. + + Assert.areEqual([], Conductor.timeChanges); + Assert.areEqual(null, Conductor.currentTimeChange); + + Assert.areEqual(0, Conductor.songPosition); + Assert.areEqual(Constants.DEFAULT_BPM, Conductor.bpm); + Assert.areEqual(null, Conductor.bpmOverride); + + Assert.areEqual(600, Conductor.beatLengthMs); + + Assert.areEqual(4, Conductor.timeSignatureNumerator); + Assert.areEqual(4, Conductor.timeSignatureDenominator); + + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + Assert.areEqual(0.0, Conductor.currentStepTime); + + Assert.areEqual(150, Conductor.stepLengthMs); + } + + /** + * Tests implementation of `update()`, and how it affects + * `currentBeat`, `currentStep`, `currentStepTime`, and the `beatHit` and `stepHit` signals. + */ + @Test + function testUpdate():Void + { + Assert.areEqual(0, Conductor.songPosition); + + step(); // 1 + + var BPM_100_STEP_TIME = 1 / 9; + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + FunkinAssert.areNear(1 / 9, Conductor.currentStepTime); + + step(7); // 8 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 8, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + FunkinAssert.areNear(8 / 9, Conductor.currentStepTime); + + Assert.areEqual(0, conductorState.beatsHit); + Assert.areEqual(0, conductorState.stepsHit); + + step(); // 9 + + Assert.areEqual(0, conductorState.beatsHit); + Assert.areEqual(1, conductorState.stepsHit); + conductorState.beatsHit = 0; + conductorState.stepsHit = 0; + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 9, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(1, Conductor.currentStep); + FunkinAssert.areNear(1.0, Conductor.currentStepTime); + + step(35 - 9); // 35 + + Assert.areEqual(0, conductorState.beatsHit); + Assert.areEqual(2, conductorState.stepsHit); + conductorState.beatsHit = 0; + conductorState.stepsHit = 0; + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 35, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(3, Conductor.currentStep); + FunkinAssert.areNear(3.0 + 8 / 9, Conductor.currentStepTime); + + step(); // 36 + + Assert.areEqual(1, conductorState.beatsHit); + Assert.areEqual(1, conductorState.stepsHit); + conductorState.beatsHit = 0; + conductorState.stepsHit = 0; + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 36, Conductor.songPosition); + Assert.areEqual(1, Conductor.currentBeat); + Assert.areEqual(4, Conductor.currentStep); + FunkinAssert.areNear(4.0, Conductor.currentStepTime); + + step(50 - 36); // 50 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 50, Conductor.songPosition); + Assert.areEqual(1, Conductor.currentBeat); + Assert.areEqual(5, Conductor.currentStep); + FunkinAssert.areNear(5.555555, Conductor.currentStepTime); + + step(49); // 99 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 99, Conductor.songPosition); + Assert.areEqual(2, Conductor.currentBeat); + Assert.areEqual(11, Conductor.currentStep); + FunkinAssert.areNear(11.0, Conductor.currentStepTime); + + step(1); // 100 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 100, Conductor.songPosition); + Assert.areEqual(2, Conductor.currentBeat); + Assert.areEqual(11, Conductor.currentStep); + FunkinAssert.areNear(11.111111, Conductor.currentStepTime); + } + + @Test + function testUpdateForcedBPM():Void + { + Conductor.forceBPM(60); + + Assert.areEqual(0, Conductor.songPosition); + + // 60 beats per minute = 1 beat per second + // 1 beat per second = 1/60 beats per frame = 4/60 steps per frame + step(); // Advances time 1/60 of 1 second. + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + FunkinAssert.areNear(4 / 60, Conductor.currentStepTime); // 1/60 of 1 beat = 4/60 of 1 step + + step(14 - 1); // 14 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 14, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + FunkinAssert.areNear(1.0 - 4 / 60, Conductor.currentStepTime); // 1/60 of 1 beat = 4/60 of 1 step + + step(); // 15 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 15, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(1, Conductor.currentStep); + FunkinAssert.areNear(1.0, Conductor.currentStepTime); // 1/60 of 1 beat = 4/60 of 1 step + + step(45 - 1); // 59 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(3, Conductor.currentStep); + FunkinAssert.areNear(4.0 - 4 / 60, Conductor.currentStepTime); + + step(); // 60 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.songPosition); + Assert.areEqual(1, Conductor.currentBeat); + Assert.areEqual(4, Conductor.currentStep); + FunkinAssert.areNear(4.0, Conductor.currentStepTime); + + step(); // 61 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.songPosition); + Assert.areEqual(1, Conductor.currentBeat); + Assert.areEqual(4, Conductor.currentStep); + FunkinAssert.areNear(4.0 + 4 / 60, Conductor.currentStepTime); + } + + @Test + function testSingleTimeChange():Void + { + // Start the song with a BPM of 120. + var songTimeChanges:Array = [ + { + t: 0, + b: 0, + bpm: 120, + n: 4, + d: 4, + bt: [4, 4, 4, 4] + }, // 120 bpm starting 0 sec/0 beats + ]; + Conductor.mapTimeChanges(songTimeChanges); + + // All should be at 0. + FunkinAssert.areNear(0, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + FunkinAssert.areNear(0.0, Conductor.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step + + // 120 beats per minute = 2 beat per second + // 2 beat per second = 2/60 beats per frame = 16/120 steps per frame + step(); // Advances time 1/60 of 1 second. + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + FunkinAssert.areNear(16 / 120, Conductor.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step + + step(15 - 1); // 15 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 15, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(2, Conductor.currentStep); + FunkinAssert.areNear(2.0, Conductor.currentStepTime); // 2/60 of 1 beat = 8/60 of 1 step + + step(45 - 1); // 59 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.songPosition); + Assert.areEqual(1, Conductor.currentBeat); + Assert.areEqual(7, Conductor.currentStep); + FunkinAssert.areNear(7.0 + 104 / 120, Conductor.currentStepTime); + + step(); // 60 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.songPosition); + Assert.areEqual(2, Conductor.currentBeat); + Assert.areEqual(8, Conductor.currentStep); + FunkinAssert.areNear(8.0, Conductor.currentStepTime); + + step(); // 61 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.songPosition); + Assert.areEqual(2, Conductor.currentBeat); + Assert.areEqual(8, Conductor.currentStep); + FunkinAssert.areNear(8.0 + 8 / 60, Conductor.currentStepTime); + } + + @Test + function testDoubleTimeChange():Void + { + // Start the song with a BPM of 120. + var songTimeChanges:Array = [ + { + t: 0, + b: 0, + bpm: 120, + n: 4, + d: 4, + bt: [4, 4, 4, 4] + }, // 120 bpm starting 0 sec/0 beats + { + t: 3000, + b: 6, + bpm: 90, + n: 4, + d: 4, + bt: [4, 4, 4, 4] + } // 90 bpm starting 3 sec/6 beats + ]; + Conductor.mapTimeChanges(songTimeChanges); + + // All should be at 0. + FunkinAssert.areNear(0, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + FunkinAssert.areNear(0.0, Conductor.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step + + // 120 beats per minute = 2 beat per second + // 2 beat per second = 2/60 beats per frame = 16/120 steps per frame + step(); // Advances time 1/60 of 1 second. + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + FunkinAssert.areNear(16 / 120, Conductor.currentStepTime); // 4/120 of 1 beat = 16/120 of 1 step + + step(60 - 1 - 1); // 59 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.songPosition); + Assert.areEqual(1, Conductor.currentBeat); + Assert.areEqual(7, Conductor.currentStep); + FunkinAssert.areNear(7.0 + 104 / 120, Conductor.currentStepTime); + + step(); // 60 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.songPosition); + Assert.areEqual(2, Conductor.currentBeat); + Assert.areEqual(8, Conductor.currentStep); + FunkinAssert.areNear(8.0, Conductor.currentStepTime); + + step(); // 61 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.songPosition); + Assert.areEqual(2, Conductor.currentBeat); + Assert.areEqual(8, Conductor.currentStep); + FunkinAssert.areNear(8.0 + 8 / 60, Conductor.currentStepTime); + + step(179 - 61); // 179 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 179, Conductor.songPosition); + Assert.areEqual(5, Conductor.currentBeat); + Assert.areEqual(23, Conductor.currentStep); + FunkinAssert.areNear(23.0 + 52 / 60, Conductor.currentStepTime); + + step(); // 180 (3 seconds) + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 180, Conductor.songPosition); + Assert.areEqual(6, Conductor.currentBeat); + Assert.areEqual(24, Conductor.currentStep); + FunkinAssert.areNear(24.0, Conductor.currentStepTime); + + step(); // 181 (3 + 1/60 seconds) + // BPM has switched to 90! + // 90 beats per minute = 1.5 beat per second + // 1.5 beat per second = 1.5/60 beats per frame = 3/120 beats per frame + // = 12/120 steps per frame + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 181, Conductor.songPosition); + Assert.areEqual(6, Conductor.currentBeat); + Assert.areEqual(24, Conductor.currentStep); + FunkinAssert.areNear(24.0 + 12 / 120, Conductor.currentStepTime); + + step(59); // 240 (4 seconds) + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 240, Conductor.songPosition); + Assert.areEqual(7, Conductor.currentBeat); + Assert.areEqual(30, Conductor.currentStep); + FunkinAssert.areNear(30.0, Conductor.currentStepTime); + + step(); // 241 (4 + 1/60 seconds) + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 241, Conductor.songPosition); + Assert.areEqual(7, Conductor.currentBeat); + Assert.areEqual(30, Conductor.currentStep); + FunkinAssert.areNear(30.0 + 12 / 120, Conductor.currentStepTime); + } + + @Test + function testTripleTimeChange():Void + { + // Start the song with a BPM of 120, then move to 90, then move to 180. + var songTimeChanges:Array = [ + { + t: 0, + b: null, + bpm: 120, + n: 4, + d: 4, + bt: [4, 4, 4, 4] + }, // 120 bpm starting 0 sec/0 beats + { + t: 3000, + b: null, + bpm: 90, + n: 4, + d: 4, + bt: [4, 4, 4, 4] + }, // 90 bpm starting 3 sec/6 beats + { + t: 6000, + b: null, + bpm: 180, + n: 4, + d: 4, + bt: [4, 4, 4, 4] + } // 90 bpm starting 3 sec/6 beats + ]; + Conductor.mapTimeChanges(songTimeChanges); + + // Verify time changes. + Assert.areEqual(3, Conductor.timeChanges.length); + FunkinAssert.areNear(0, Conductor.timeChanges[0].beatTime); + FunkinAssert.areNear(6, Conductor.timeChanges[1].beatTime); + FunkinAssert.areNear(10.5, Conductor.timeChanges[2].beatTime); + + // All should be at 0. + FunkinAssert.areNear(0, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + FunkinAssert.areNear(0.0, Conductor.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step + + // 120 beats per minute = 2 beat per second + // 2 beat per second = 2/60 beats per frame = 16/120 steps per frame + step(); // Advances time 1/60 of 1 second. + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.songPosition); + Assert.areEqual(0, Conductor.currentBeat); + Assert.areEqual(0, Conductor.currentStep); + FunkinAssert.areNear(16 / 120, Conductor.currentStepTime); // 4/120 of 1 beat = 16/120 of 1 step + + step(60 - 1 - 1); // 59 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.songPosition); + Assert.areEqual(1, Conductor.currentBeat); + Assert.areEqual(7, Conductor.currentStep); + FunkinAssert.areNear(7 + 104 / 120, Conductor.currentStepTime); + + step(); // 60 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.songPosition); + Assert.areEqual(2, Conductor.currentBeat); + Assert.areEqual(8, Conductor.currentStep); + FunkinAssert.areNear(8.0, Conductor.currentStepTime); + + step(); // 61 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.songPosition); + Assert.areEqual(2, Conductor.currentBeat); + Assert.areEqual(8, Conductor.currentStep); + FunkinAssert.areNear(8.0 + 8 / 60, Conductor.currentStepTime); + + step(179 - 61); // 179 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 179, Conductor.songPosition); + Assert.areEqual(5, Conductor.currentBeat); + Assert.areEqual(23, Conductor.currentStep); + FunkinAssert.areNear(23.0 + 52 / 60, Conductor.currentStepTime); + + step(); // 180 (3 seconds) + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 180, Conductor.songPosition); + Assert.areEqual(6, Conductor.currentBeat); + Assert.areEqual(24, Conductor.currentStep); // 23.999 => 24 + FunkinAssert.areNear(24.0, Conductor.currentStepTime); + + step(); // 181 (3 + 1/60 seconds) + // BPM has switched to 90! + // 90 beats per minute = 1.5 beat per second + // 1.5 beat per second = 1.5/60 beats per frame = 3/120 beats per frame + // = 12/120 steps per frame + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 181, Conductor.songPosition); + Assert.areEqual(6, Conductor.currentBeat); + Assert.areEqual(24, Conductor.currentStep); + FunkinAssert.areNear(24.0 + 12 / 120, Conductor.currentStepTime); + + step(60 - 1 - 1); // 240 (4 seconds) + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 239, Conductor.songPosition); + Assert.areEqual(7, Conductor.currentBeat); + Assert.areEqual(29, Conductor.currentStep); + FunkinAssert.areNear(29.0 + 108 / 120, Conductor.currentStepTime); + + step(); // 240 (4 seconds) + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 240, Conductor.songPosition); + Assert.areEqual(7, Conductor.currentBeat); + Assert.areEqual(30, Conductor.currentStep); + FunkinAssert.areNear(30.0, Conductor.currentStepTime); + + step(); // 241 (4 + 1/60 seconds) + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 241, Conductor.songPosition); + Assert.areEqual(7, Conductor.currentBeat); + Assert.areEqual(30, Conductor.currentStep); + FunkinAssert.areNear(30.0 + 12 / 120, Conductor.currentStepTime); + + step(359 - 241); // 359 (5 + 59/60 seconds) + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 359, Conductor.songPosition); + Assert.areEqual(10, Conductor.currentBeat); + Assert.areEqual(41, Conductor.currentStep); + FunkinAssert.areNear(41 + 108 / 120, Conductor.currentStepTime); + + step(); // 360 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 360, Conductor.songPosition); + Assert.areEqual(10, Conductor.currentBeat); + Assert.areEqual(42, Conductor.currentStep); // 41.999 + FunkinAssert.areNear(42.0, Conductor.currentStepTime); + + step(); // 361 + // BPM has switched to 180! + // 180 beats per minute = 3 beat per second + // 3 beat per second = 3/60 beats per frame + // = 12/60 steps per frame + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 361, Conductor.songPosition); + Assert.areEqual(10, Conductor.currentBeat); + Assert.areEqual(42, Conductor.currentStep); + FunkinAssert.areNear(42.0 + 12 / 60, Conductor.currentStepTime); + + step(); // 362 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 362, Conductor.songPosition); + Assert.areEqual(10, Conductor.currentBeat); + Assert.areEqual(42, Conductor.currentStep); + FunkinAssert.areNear(42.0 + 24 / 60, Conductor.currentStepTime); + + step(3); // 365 + + FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 365, Conductor.songPosition); + Assert.areEqual(10, Conductor.currentBeat); + Assert.areEqual(43, Conductor.currentStep); // 42.999 => 42 + FunkinAssert.areNear(43.0, Conductor.currentStepTime); + } +} + +class ConductorState extends FlxState +{ + public var beatsHit:Int = 0; + public var stepsHit:Int = 0; + + public function new() + { + super(); + } + + function beatHit():Void + { + beatsHit += 1; + } + + function stepHit():Void + { + stepsHit += 1; + } + + public override function create():Void + { + super.create(); + Conductor.beatHit.add(this.beatHit); + Conductor.stepHit.add(this.stepHit); + } + + public override function destroy():Void + { + super.destroy(); + Conductor.beatHit.remove(this.beatHit); + Conductor.stepHit.remove(this.stepHit); + } + + public override function update(elapsed:Float) + { + super.update(elapsed); + + // On each step, increment the Conductor as though the song was playing. + Conductor.update(Conductor.songPosition + elapsed * Constants.MS_PER_SEC); + } +} diff --git a/tests/unit/source/funkin/data/BaseRegistryTest.hx b/tests/unit/source/funkin/data/BaseRegistryTest.hx new file mode 100644 index 000000000..3532c4403 --- /dev/null +++ b/tests/unit/source/funkin/data/BaseRegistryTest.hx @@ -0,0 +1,228 @@ +package funkin.data; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.data.BaseRegistry; +import funkin.util.SortUtil; +import funkin.util.VersionUtil; + +@:access(funkin.data.BaseRegistry) +class BaseRegistryTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testMyTypeRegistry() + { + // This shouldn't crash. + MyTypeRegistry.instance.loadEntries(); + + // Ensure all entries were loaded. + var entryList = MyTypeRegistry.instance.listEntryIds(); + entryList.sort(SortUtil.alphabetically); + + Assert.areEqual(entryList, [ + "blablabla", + "fizzbuzz", + "foobar", + // "junk" + ]); + + // Ensure this one is not in the list. + Assert.areEqual(entryList.indexOf("junk"), -1); + + // Ensure blablabla got parsed correctly. + var blablabla = MyTypeRegistry.instance.fetchEntry("blablabla"); + Assert.areEqual(blablabla.id, "blablabla"); + Assert.areEqual(blablabla._data.version, "1.0.0"); + Assert.areEqual(blablabla._data.name, "blablabla API"); + } +} + +typedef MyTypeData = +{ + /** + * The version number of the data schema. + * When making changes to the note style data format, this should be incremented, + * and a migration function should be added to handle old versions. + */ + @:default(funkin.data.BaseRegistryTest.MyTypeRegistry.DATA_VERSION) + var version:String; + + var id:String; + var name:String; + var data:Array; +} + +typedef MySubTypeData = +{ + var foo:String; + var bar:String; +}; + +typedef MyTypeData_v0_1_x = +{ + var version:String; + var id:Int; + var name:String; +}; + +class MyType implements IRegistryEntry +{ + /** + * The ID of the mytype. + */ + public final id:String; + + /** + * Mytype data as parsed from the JSON file. + */ + public final _data:MyTypeData; + + /** + * @param id The ID of the JSON file to parse. + */ + public function new(id:String) + { + this.id = id; + _data = _fetchData(id); + + if (_data == null) + { + throw 'Could not parse mytype data for id: $id'; + } + } + + public function destroy():Void {} + + public function toString():String + { + return 'MyType($id)'; + } + + public function _fetchData(id:String):Null + { + return MyTypeRegistry.instance.parseEntryDataWithMigration(id, MyTypeRegistry.instance.fetchEntryVersion(id)); + } + + public function getSubData():Array + { + return _data.data; + } +} + +class MyTypeRegistry extends BaseRegistry +{ + /** + * The current version string for the note style data format. + * Handle breaking changes by incrementing this value + * and adding migration to the `migrateMyTypeData()` function. + */ + public static final DATA_VERSION:String = "1.0.0"; + + public static final instance:MyTypeRegistry = new MyTypeRegistry(); + + public function new() + { + super('MYTYPE', 'mytype'); + } + + /** + * Read, parse, and validate the JSON data and produce the corresponding data object. + */ + public function parseEntryData(id:String):Null + { + // JsonParser does not take type parameters, + // otherwise this function would be in BaseRegistry. + var parser = new json2object.JsonParser(); + var jsonStr:String = loadEntryFile(id); + + parser.fromJson(jsonStr); + + if (parser.errors.length > 0) + { + trace('[${registryId}] Failed to parse entry data: ${id}'); + for (error in parser.errors) + { + trace(error); + } + return null; + } + return parser.value; + } + + /** + * Read, parse, and validate the JSON data and produce the corresponding data object. + */ + public function parseEntryData_v0_1_x(id:String):Null + { + // JsonParser does not take type parameters, + // otherwise this function would be in BaseRegistry. + var parser = new json2object.JsonParser(); + var jsonStr:String = loadEntryFile(id); + + parser.fromJson(jsonStr); + + if (parser.errors.length > 0) + { + trace('[${registryId}] Failed to parse entry data: ${id}'); + for (error in parser.errors) + { + trace(error); + } + return null; + } + + var oldData:MyTypeData_v0_1_x = parser.value; + + var result:MyTypeData = + { + version: DATA_VERSION, + id: '${oldData.id}', + name: oldData.name, + data: [] + }; + + return result; + } + + public override function parseEntryDataWithMigration(id:String, version:thx.semver.Version):Null + { + if (VersionUtil.validateVersion(version, "0.1.x")) + { + trace('Migrating mytype data from ${version} to ${DATA_VERSION}'); + return parseEntryData_v0_1_x(id); + } + else + { + trace('Parsing mytype data with version ${version}'); + return super.parseEntryDataWithMigration(id, version); + } + } + + function createScriptedEntry(clsName:String):MyType + { + return null; + } + + function getScriptedClassNames():Array + { + return []; + } +} diff --git a/tests/unit/source/funkin/data/notestyle/NoteStyleRegistryTest.hx b/tests/unit/source/funkin/data/notestyle/NoteStyleRegistryTest.hx new file mode 100644 index 000000000..ec33b37d7 --- /dev/null +++ b/tests/unit/source/funkin/data/notestyle/NoteStyleRegistryTest.hx @@ -0,0 +1,90 @@ +package funkin.data.notestyle; + +import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notestyle.NoteStyle; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import massive.munit.util.Timer; + +@:access(funkin.play.notes.notestyle.NoteStyle) +@:access(funkin.data.notestyle.NoteStyleRegistry) +class NoteStyleRegistryTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() + { + NoteStyleRegistry.instance.loadEntries(); + } + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testValid() + { + Assert.isNotNull(NoteStyleRegistry.instance); + } + + @Test + public function testParseEntryData() + { + var result:NoteStyleData = NoteStyleRegistry.instance.parseEntryData("test2"); + + Assert.areEqual(result.version, "1.0.0"); + Assert.areEqual(result.name, "Test2"); + Assert.areEqual(result.author, "Eric"); + Assert.areEqual(result.fallback, "funkin"); + + Assert.areEqual(result.assets.note.assetPath, "shared:coolstuff"); + Assert.areEqual(result.assets.note.scale, 1.8); + Assert.areEqual(result.assets.note.data.left.prefix, "noteLeft1"); + Assert.areEqual(result.assets.note.data.down.prefix, "noteDown3"); + Assert.areEqual(result.assets.note.data.up.prefix, "noteUp2"); + Assert.areEqual(result.assets.note.data.right.prefix, "noteRight4"); + } + + @Test + public function testFetchEntry() + { + var result:NoteStyle = NoteStyleRegistry.instance.fetchEntry("test2"); + + Assert.areEqual(result.toString(), "NoteStyle(test2)"); + Assert.areEqual(result.getName(), "Test2"); + Assert.areEqual(result.getAuthor(), "Eric"); + Assert.areEqual(result.getFallbackID(), "funkin"); + } + + @Test + public function testFetchBadEntry() + { + var result:NoteStyle = NoteStyleRegistry.instance.fetchEntry("blablabla"); + + Assert.areEqual(result, null); + } + + @Test + public function testFetchDefault() + { + var nsrMock:NoteStyleRegistry = mock(NoteStyleRegistry); + + nsrMock.fetchDefault().callsRealMethod(); + + // Perform the call. + nsrMock.fetchDefault(); + + // Verify the underlying call. + + nsrMock.fetchEntry(NoteStyleRegistry.DEFAULT_NOTE_STYLE_ID).verify(times(1)); + } +} diff --git a/tests/unit/source/funkin/play/notes/notestyle/NoteStyleTest.hx b/tests/unit/source/funkin/play/notes/notestyle/NoteStyleTest.hx new file mode 100644 index 000000000..31e8e38ae --- /dev/null +++ b/tests/unit/source/funkin/play/notes/notestyle/NoteStyleTest.hx @@ -0,0 +1,77 @@ +package funkin.play.notes.notestyle; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notestyle.NoteStyle; +import flixel.animation.FlxAnimationController; + +@:access(funkin.play.notes.notestyle.NoteStyle) +class NoteStyleTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() + { + NoteStyleRegistry.instance.loadEntries(); + } + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + @Ignore("This test doesn't work, crashes when the project has 2 mocks of the same class???") + public function testBuildNoteSprite() + { + var target:NoteStyle = NoteStyleRegistry.instance.fetchEntry("funkin"); + + var mockNoteSprite:NoteSprite = mock(NoteSprite); + // var mockAnim = mock(FlxAnimationController); + // mockNoteSprite.animation = mockAnim; + + target.buildNoteSprite(mockNoteSprite); + + Assert.areEqual(mockNoteSprite.frames, []); + } + + @Test + public function testFallbackBehavior() + { + var target1:NoteStyle = NoteStyleRegistry.instance.fetchEntry("funkin"); + var target2:NoteStyle = NoteStyleRegistry.instance.fetchEntry("test2"); + + Assert.areEqual("funkin", target1.id); + Assert.areEqual("test2", target2.id); + + Assert.areEqual("Funkin'", target1.getName()); + Assert.areEqual("Test2", target2.getName()); + + Assert.isNull(target1.getFallbackID()); + Assert.areEqual(target1.id, target2.getFallbackID()); + + // Overridden fields are different. + Assert.areEqual("arrows", target1.getNoteAssetPath(false)); + Assert.areEqual("coolstuff", target2.getNoteAssetPath(false)); + + Assert.areEqual("shared:arrows", target1.getNoteAssetPath(true)); + Assert.areEqual("shared:coolstuff", target2.getNoteAssetPath(true)); + + // Unspecified fields use the fallback. + // Should NOT return null! + Assert.areEqual("assets/images/NOTE_hold_assets.png", target1.getHoldNoteAssetPath(false)); + Assert.areEqual("assets/images/NOTE_hold_assets.png", target2.getHoldNoteAssetPath(false)); + + Assert.areEqual("NOTE_hold_assets", target1.getHoldNoteAssetPath(true)); + } +} diff --git a/tests/unit/source/funkin/util/BezierUtilTest.hx b/tests/unit/source/funkin/util/BezierUtilTest.hx new file mode 100644 index 000000000..90186c111 --- /dev/null +++ b/tests/unit/source/funkin/util/BezierUtilTest.hx @@ -0,0 +1,137 @@ +package funkin.util; + +import flixel.math.FlxPoint; +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.BezierUtil; + +@:access(funkin.util.BezierUtil) +class BezierUtilTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testBezier2() + { + var point1:FlxPoint = FlxPoint.get(1, 1); + var point2:FlxPoint = FlxPoint.get(2, 2); + + var result:FlxPoint = BezierUtil.bezier2(0.5, point1, point2); + + Assert.areEqual(result.x, 1.5); + Assert.areEqual(result.y, 1.5); + + result = BezierUtil.bezier2(0.25, point1, point2); + + Assert.areEqual(result.x, 1.25); + Assert.areEqual(result.y, 1.25); + + result = BezierUtil.bezier2(0.75, point1, point2); + + Assert.areEqual(result.x, 1.75); + Assert.areEqual(result.y, 1.75); + } + + @Test + public function testBezier3() + { + var point1:FlxPoint = FlxPoint.get(1, 1); + var point2:FlxPoint = FlxPoint.get(2, 2); + var point3:FlxPoint = FlxPoint.get(3, 3); + + var result:FlxPoint = BezierUtil.bezier3(0.5, point1, point2, point3); + + Assert.areEqual(result.x, 2); + Assert.areEqual(result.y, 2); + + result = BezierUtil.bezier3(0.25, point1, point2, point3); + + Assert.areEqual(result.x, 1.5); + Assert.areEqual(result.y, 1.5); + + result = BezierUtil.bezier3(0.75, point1, point2, point3); + + Assert.areEqual(result.x, 2.5); + Assert.areEqual(result.y, 2.5); + + result = BezierUtil.bezier3(0.5, point1, point2, point3); + + Assert.areEqual(result.x, 2); + Assert.areEqual(result.y, 2); + + result = BezierUtil.bezier3(0.6, point1, point2, point3); + + Assert.areEqual(result.x, 2.2); + Assert.areEqual(result.y, 2.2); + } + + @Test + public function testBezier4() + { + var point1:FlxPoint = FlxPoint.get(1, 1); + var point2:FlxPoint = FlxPoint.get(2, 2); + var point3:FlxPoint = FlxPoint.get(3, 3); + var point4:FlxPoint = FlxPoint.get(4, 4); + + var result:FlxPoint = BezierUtil.bezier4(0.5, point1, point2, point3, point4); + + Assert.areEqual(result.x, 2.5); + Assert.areEqual(result.y, 2.5); + + result = BezierUtil.bezier4(0.25, point1, point2, point3, point4); + + Assert.areEqual(result.x, 1.75); + Assert.areEqual(result.y, 1.75); + + result = BezierUtil.bezier4(0.75, point1, point2, point3, point4); + + Assert.areEqual(result.x, 3.25); + Assert.areEqual(result.y, 3.25); + } + + @Test + public function testBezier5() + { + var point1:FlxPoint = FlxPoint.get(1, 1); + var point2:FlxPoint = FlxPoint.get(2, 2); + var point3:FlxPoint = FlxPoint.get(3, 3); + var point4:FlxPoint = FlxPoint.get(4, 4); + var point5:FlxPoint = FlxPoint.get(5, 5); + + var result:FlxPoint = BezierUtil.bezier5(0.5, point1, point2, point3, point4, point5); + + Assert.areEqual(result.x, 3); + Assert.areEqual(result.y, 3); + + result = BezierUtil.bezier5(0.25, point1, point2, point3, point4, point5); + + Assert.areEqual(result.x, 2); + Assert.areEqual(result.y, 2); + + result = BezierUtil.bezier5(0.75, point1, point2, point3, point4, point5); + + Assert.areEqual(result.x, 4); + Assert.areEqual(result.y, 4); + + result = BezierUtil.bezier5(0.5, point1, point2, point3, point4, point5); + + Assert.areEqual(result.x, 3); + Assert.areEqual(result.y, 3); + } +} diff --git a/tests/unit/source/funkin/util/ClipboardUtilTest.hx b/tests/unit/source/funkin/util/ClipboardUtilTest.hx new file mode 100644 index 000000000..9efd96d34 --- /dev/null +++ b/tests/unit/source/funkin/util/ClipboardUtilTest.hx @@ -0,0 +1,71 @@ +package funkin.util; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.ClipboardUtil; + +@:access(funkin.util.ClipboardUtil) +class ClipboardUtilTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testGetSetClipboard() + { + var testString = "test string"; + ClipboardUtil.setClipboard(testString); + var clipboardString = ClipboardUtil.getClipboard(); + Assert.areEqual(testString, clipboardString); + } + + @Ignore("This test doesn't work, Lime issue?") + @Test + public function testAddRemoveListener() + { + ClipboardUtil.addListener(onClipboardChange); + + var testString = "test string"; + ClipboardUtil.setClipboard(testString); + + var clipboardString = ClipboardUtil.getClipboard(); + Assert.areEqual(testString, clipboardString); + + step(); + + // TODO: Fix issue where this test fails + Assert.areEqual(1, count); + + ClipboardUtil.removeListener(onClipboardChange); + + var testString2 = "test string 2"; + ClipboardUtil.setClipboard(testString2); + + var clipboardString2 = ClipboardUtil.getClipboard(); + Assert.areEqual(testString2, clipboardString2); + + Assert.areEqual(1, count); + } + + var count:Int = 0; + + function onClipboardChange() + { + count += 1; + } +} diff --git a/tests/unit/source/funkin/util/DateUtilTest.hx b/tests/unit/source/funkin/util/DateUtilTest.hx new file mode 100644 index 000000000..c8adb3824 --- /dev/null +++ b/tests/unit/source/funkin/util/DateUtilTest.hx @@ -0,0 +1,35 @@ +package funkin.util; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.DateUtil; + +@:access(funkin.util.DateUtil) +class DateUtilTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testGenerateTimestamp() + { + var date:Date = new Date(2020, 10 - 1, 31, 3, 0, 0); + var timestamp:String = DateUtil.generateTimestamp(date); + Assert.areEqual("2020-10-31-03-00-00", timestamp); + } +} diff --git a/tests/unit/source/funkin/util/SerializerUtilTest.hx b/tests/unit/source/funkin/util/SerializerUtilTest.hx new file mode 100644 index 000000000..d2adc3350 --- /dev/null +++ b/tests/unit/source/funkin/util/SerializerUtilTest.hx @@ -0,0 +1,87 @@ +package funkin.util; + +import haxe.io.Bytes; +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.SerializerUtil; + +typedef FooBar = +{ + a:Int, + b:Int, + c:Int +}; + +@:access(funkin.util.SerializerUtil) +class SerializerUtilTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testToJSON() + { + var object = {a: 1, b: 2, c: 3}; + var json = SerializerUtil.toJSON(object); + Assert.areEqual('{' + '\n\t"a": 1,' + '\n\t"b": 2,' + '\n\t"c": 3' + '\n}', json); + } + + @Test + public function testFromJSON() + { + var json = '{' + '\n\t"a": 1,' + '\n\t"b": 2,' + '\n\t"c": 3' + '\n}'; + var object = SerializerUtil.fromJSON(json); + Assert.areEqual(1, object.a); + Assert.areEqual(2, object.b); + Assert.areEqual(3, object.c); + } + + @Test + public function testFromJSONBytes() + { + var json = '{' + '\n\t"a": 1,' + '\n\t"b": 2,' + '\n\t"c": 3' + '\n}'; + var bytes = Bytes.ofString(json); + + var object = SerializerUtil.fromJSONBytes(bytes); + Assert.areEqual(1, object.a); + Assert.areEqual(2, object.b); + Assert.areEqual(3, object.c); + } + + @Test + public function testReplacer() + { + var version:thx.semver.Version = '1.0.0-beta'; + + Assert.areEqual(1, version.major); + Assert.areEqual(0, version.minor); + Assert.areEqual(0, version.patch); + Assert.areEqual(true, version.hasPre); + Assert.areEqual('beta', version.pre); + // Assert.areEqual(false, version.hasBuild); + Assert.areEqual('', version.build); + + var formatted = SerializerUtil.replacer('version', version); + + Assert.areEqual('1.0.0-beta', formatted); + + var test2 = SerializerUtil.toJSON({version: version}); + + Assert.areEqual('{' + '\n\t"version": "1.0.0-beta"' + '\n}', test2); + } +} diff --git a/tests/unit/source/funkin/util/SortUtilTest.hx b/tests/unit/source/funkin/util/SortUtilTest.hx new file mode 100644 index 000000000..4720c3da6 --- /dev/null +++ b/tests/unit/source/funkin/util/SortUtilTest.hx @@ -0,0 +1,63 @@ +package funkin.util; + +import flixel.FlxObject; +import flixel.FlxSprite; +import flixel.util.FlxSort; +import funkin.play.song.SongData.SongNoteData; +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.SortUtil; + +@:access(funkin.util.SortUtil) +class SortUtilTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testAlphabetically() + { + var arr:Array = ["b", "a", "c"]; + + arr.sort(SortUtil.alphabetically); + + Assert.areEqual(["a", "b", "c"], arr); + } + + @Test + public function testByZIndex() + { + var arr:Array = [new FlxSprite(), new FlxObject(), new FlxSprite()]; + + arr[0].zIndex = 2000; + arr[1].zIndex = 1000; + arr[2].zIndex = 3000; + + arr.sort(SortUtil.byZIndex.bind(FlxSort.ASCENDING)); + + Assert.areEqual(1000, arr[0].zIndex); + Assert.areEqual(2000, arr[1].zIndex); + Assert.areEqual(3000, arr[2].zIndex); + + arr.sort(SortUtil.byZIndex.bind(FlxSort.DESCENDING)); + + Assert.areEqual(3000, arr[0].zIndex); + Assert.areEqual(2000, arr[1].zIndex); + Assert.areEqual(1000, arr[2].zIndex); + } +} diff --git a/tests/unit/source/funkin/util/VersionUtilTest.hx b/tests/unit/source/funkin/util/VersionUtilTest.hx new file mode 100644 index 000000000..55848955a --- /dev/null +++ b/tests/unit/source/funkin/util/VersionUtilTest.hx @@ -0,0 +1,64 @@ +package funkin.util; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.VersionUtil; + +@:access(funkin.util.VersionUtil) +class VersionUtilTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testValidateVersionStr() + { + Assert.areEqual(true, VersionUtil.validateVersionStr("1.0.0", "1.0.0")); + + Assert.areEqual(false, VersionUtil.validateVersionStr("ehe", "test")); + } + + @Test + public function testValidateVersion() + { + var version:thx.semver.Version = "1.0.0"; // implicit cast + var versionRule:thx.semver.VersionRule = "1.0.0"; // implicit cast + + Assert.areEqual(true, VersionUtil.validateVersion(version, versionRule)); + + var versionRule2:thx.semver.VersionRule = ">=3.1.0"; // implicit cast + + var version1:thx.semver.Version = "3.0.0"; + var version2:thx.semver.Version = "3.1.1"; + var version3:thx.semver.Version = "4.2.0"; + + Assert.areEqual(false, VersionUtil.validateVersion(version1, versionRule2)); + Assert.areEqual(true, VersionUtil.validateVersion(version2, versionRule2)); + Assert.areEqual(true, VersionUtil.validateVersion(version3, versionRule2)); + } + + @Test + public function testGetVersionFromJSON() + { + var jsonStr:String = "{ \"version\": \"3.1.0\" }"; + + var version:thx.semver.Version = VersionUtil.getVersionFromJSON(jsonStr); + + Assert.areEqual("3.1.0", version.toString()); + } +} diff --git a/tests/unit/source/funkin/util/assets/DataAssetsTest.hx b/tests/unit/source/funkin/util/assets/DataAssetsTest.hx new file mode 100644 index 000000000..7612d4706 --- /dev/null +++ b/tests/unit/source/funkin/util/assets/DataAssetsTest.hx @@ -0,0 +1,42 @@ +package funkin.util.assets; + +import openfl.utils.Assets; +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.assets.DataAssets; + +@:access(funkin.util.assets.DataAssets) +class DataAssetsTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testBuildDataPath() + { + Assert.areEqual('assets/data/test.json', DataAssets.buildDataPath('test.json')); + } + + @Test + public function listDataFilesInPath() + { + var expected = ['blablabla', 'test1', 'test2']; + + Assert.areEqual(expected, DataAssets.listDataFilesInPath('test/')); + } +} diff --git a/tests/unit/source/funkin/util/assets/FlxAnimationUtilTest.hx b/tests/unit/source/funkin/util/assets/FlxAnimationUtilTest.hx new file mode 100644 index 000000000..990d998f2 --- /dev/null +++ b/tests/unit/source/funkin/util/assets/FlxAnimationUtilTest.hx @@ -0,0 +1,118 @@ +package funkin.util.assets; + +import funkin.util.assets.FlxAnimationUtil; +import flixel.animation.FlxAnimationController; +import funkin.data.animation.AnimationData; +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.DateUtil; +import flixel.FlxSprite; + +@:access(funkin.util.assets.FlxAnimationUtil) +class FlxAnimationUtilTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testAddAtlasAnimation() + { + // Build a mock child class of FlxSprite + var mockSprite = mock(FlxSprite); + var mockAnim = mock(FlxAnimationController); + mockSprite.animation = mockAnim; + + var animData:AnimationData = + { + name: "testAnim", + prefix: "blablabla" + }; + + FlxAnimationUtil.addAtlasAnimation(mockSprite, animData); + + // Verify that the method was called once. + // If not, a VerificationException will be thrown and the test will fail. + mockAnim.addByPrefix("testAnim", "blablabla", 24, false, false, false).verify(times(1)); + + // Verify there were no other functions called. + mockAnim.verifyZeroInteractions(); + mockSprite.verifyZeroInteractions(); + + var animData2:AnimationData = + { + name: "testAnim2", + prefix: "blablabla2", + frameIndices: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + frameRate: 12, + flipX: true, + flipY: true, + looped: true + }; + + FlxAnimationUtil.addAtlasAnimation(mockSprite, animData2); + + try + { + mockAnim.addByIndices("testAnim2", "blablabla2", cast anyIterator, "", 12, true, true, true).verify(times(1)); + } + catch (e) + { + trace('CAUGHT EXCEPTION'); + trace(e); + } + + mockAnim.verifyZeroInteractions(); + mockSprite.verifyZeroInteractions(); + } + + @Test + public function testAddAtlasAnimations() + { + // Build a mock child class of FlxSprite + var mockSprite = mock(FlxSprite); + var mockAnim = mock(FlxAnimationController); + mockSprite.animation = mockAnim; + + var animData:Array = [ + { + name: "testAnim", + prefix: "blablabla" + }, + { + name: "testAnim2", + prefix: "blablabla2" + }, + { + name: "testAnim3", + prefix: "blablabla3" + } + ]; + + FlxAnimationUtil.addAtlasAnimations(mockSprite, animData); + + // Verify that the method was called once. + // If not, a VerificationException will be thrown and the test will fail. + mockAnim.addByPrefix("testAnim", "blablabla", 24, false, false, false).verify(times(1)); + mockAnim.addByPrefix("testAnim2", "blablabla2", 24, false, false, false).verify(times(1)); + mockAnim.addByPrefix("testAnim3", "blablabla3", 24, false, false, false).verify(times(1)); + + // Verify there were no other functions called. + mockAnim.verifyZeroInteractions(); + mockSprite.verifyZeroInteractions(); + } +} diff --git a/tests/unit/source/funkin/util/tools/ArraySortToolsTest.hx b/tests/unit/source/funkin/util/tools/ArraySortToolsTest.hx new file mode 100644 index 000000000..0bcef00b5 --- /dev/null +++ b/tests/unit/source/funkin/util/tools/ArraySortToolsTest.hx @@ -0,0 +1,165 @@ +package funkin.util.tools; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.tools.ArrayTools; + +@:access(funkin.util.tools.ArrayTools) +class ArraySortToolsTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testMergeSort() + { + var testArray:Array = [5, 4, 3, 2, 1]; + + function compare(a:Int, b:Int) + { + return a - b; + } + + ArraySortTools.mergeSort(testArray, compare); + + Assert.areEqual(testArray[0], 1); + Assert.areEqual(testArray[1], 2); + Assert.areEqual(testArray[2], 3); + Assert.areEqual(testArray[3], 4); + Assert.areEqual(testArray[4], 5); + + var testArray2:Array = [9, 6, 3, 12]; + + ArraySortTools.mergeSort(testArray2, compare); + + Assert.areEqual(testArray2[0], 3); + Assert.areEqual(testArray2[1], 6); + Assert.areEqual(testArray2[2], 9); + Assert.areEqual(testArray2[3], 12); + + // Just make sure these don't crash. + ArraySortTools.mergeSort([], compare); + ArraySortTools.mergeSort(null, compare); + ArraySortTools.mergeSort([], null); + ArraySortTools.mergeSort(null, null); + + // Make sure these throw an exception. + try + { + ArraySortTools.mergeSort(testArray, null); + + Assert.fail("Function should have thrown an exception."); + } + catch (e) + { + Assert.areEqual("No comparison function provided.", e); + } + } + + @Test + public function testQuickSort() + { + var testArray:Array = [5, 4, 3, 2, 1]; + + function compare(a:Int, b:Int) + { + return a - b; + } + + ArraySortTools.quickSort(testArray, compare); + + Assert.areEqual(testArray[0], 1); + Assert.areEqual(testArray[1], 2); + Assert.areEqual(testArray[2], 3); + Assert.areEqual(testArray[3], 4); + Assert.areEqual(testArray[4], 5); + + var testArray2:Array = [9, 6, 3, 12]; + + ArraySortTools.quickSort(testArray2, compare); + + Assert.areEqual(testArray2[0], 3); + Assert.areEqual(testArray2[1], 6); + Assert.areEqual(testArray2[2], 9); + Assert.areEqual(testArray2[3], 12); + + // Just make sure these don't crash. + ArraySortTools.quickSort([], compare); + ArraySortTools.quickSort(null, compare); + ArraySortTools.quickSort([], null); + ArraySortTools.quickSort(null, null); + + // Make sure these throw an exception. + try + { + ArraySortTools.quickSort(testArray, null); + + Assert.fail("Function should have thrown an exception."); + } + catch (e) + { + Assert.areEqual("No comparison function provided.", e); + } + } + + @Test + public function testInsertionSort() + { + var testArray:Array = [5, 4, 3, 2, 1]; + + function compare(a:Int, b:Int) + { + return a - b; + } + + ArraySortTools.insertionSort(testArray, compare); + + Assert.areEqual(testArray[0], 1); + Assert.areEqual(testArray[1], 2); + Assert.areEqual(testArray[2], 3); + Assert.areEqual(testArray[3], 4); + Assert.areEqual(testArray[4], 5); + + var testArray2:Array = [9, 6, 3, 12]; + + ArraySortTools.insertionSort(testArray2, compare); + + Assert.areEqual(testArray2[0], 3); + Assert.areEqual(testArray2[1], 6); + Assert.areEqual(testArray2[2], 9); + Assert.areEqual(testArray2[3], 12); + + // Just make sure these don't crash. + ArraySortTools.insertionSort([], compare); + ArraySortTools.insertionSort(null, compare); + ArraySortTools.insertionSort([], null); + ArraySortTools.insertionSort(null, null); + + // Make sure these throw an exception. + try + { + ArraySortTools.insertionSort(testArray, null); + + Assert.fail("Function should have thrown an exception."); + } + catch (e) + { + Assert.areEqual("No comparison function provided.", e); + } + } +} diff --git a/tests/unit/source/funkin/util/tools/ArrayToolsTest.hx b/tests/unit/source/funkin/util/tools/ArrayToolsTest.hx new file mode 100644 index 000000000..68adb833b --- /dev/null +++ b/tests/unit/source/funkin/util/tools/ArrayToolsTest.hx @@ -0,0 +1,65 @@ +package funkin.util.tools; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.tools.ArrayTools; + +@:access(funkin.util.tools.ArrayTools) +class ArrayToolsTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testUnique() + { + var testArray:Array = [1, 2, 3, 4, 5, 6, 10, 7, 8, 9, 3, 4, 5, 6, 11, 7, 8]; + + var uniqueArray:Array = ArrayTools.unique(testArray); + + Assert.areEqual(uniqueArray.length, 11); + + // Array order doesn't change + Assert.areEqual(uniqueArray[0], 1); + Assert.areEqual(uniqueArray[1], 2); + Assert.areEqual(uniqueArray[2], 3); + Assert.areEqual(uniqueArray[3], 4); + Assert.areEqual(uniqueArray[4], 5); + Assert.areEqual(uniqueArray[5], 6); + Assert.areEqual(uniqueArray[6], 10); + Assert.areEqual(uniqueArray[7], 7); + Assert.areEqual(uniqueArray[8], 8); + Assert.areEqual(uniqueArray[9], 9); + Assert.areEqual(uniqueArray[10], 11); + } + + @Test + public function testFind() + { + function predicate(a:String):Bool + { + return a.startsWith("Hello"); + } + + var testArray:Array = ["Foo", "Bar", "HelloWorld", "Baz", "HelloTest"]; + + var result = ArrayTools.find(testArray, predicate); + + Assert.areEqual(result, "HelloWorld"); + } +} diff --git a/tests/unit/source/funkin/util/tools/IteratorToolsTest.hx b/tests/unit/source/funkin/util/tools/IteratorToolsTest.hx new file mode 100644 index 000000000..deaea352b --- /dev/null +++ b/tests/unit/source/funkin/util/tools/IteratorToolsTest.hx @@ -0,0 +1,59 @@ +package funkin.util.tools; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.tools.IteratorTools; + +@:access(funkin.util.tools.IteratorTools) +class IteratorToolsTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testArray() + { + var iter = new MyStringIterator("HelloWorld"); + + var arr = IteratorTools.array(iter); + + Assert.areEqual(["H", "e", "l", "l", "o", "W", "o", "r", "l", "d"], arr); + } +} + +class MyStringIterator +{ + var s:String; + var i:Int; + + public function new(s:String) + { + this.s = s; + i = 0; + } + + public function hasNext() + { + return i < s.length; + } + + public function next() + { + return s.charAt(i++); + } +} diff --git a/tests/unit/source/funkin/util/tools/MapToolsTest.hx b/tests/unit/source/funkin/util/tools/MapToolsTest.hx new file mode 100644 index 000000000..c3fe34461 --- /dev/null +++ b/tests/unit/source/funkin/util/tools/MapToolsTest.hx @@ -0,0 +1,55 @@ +package funkin.util.tools; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.tools.MapTools; + +@:access(funkin.util.tools.MapTools) +class MapToolsTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testSize() + { + var testMap:Map = ["key1" => "value1", "key2" => "value2", "key3" => "value3"]; + + Assert.areEqual(3, MapTools.size(testMap)); + } + + @Test + public function testValues() + { + var testMap:Map = ["key1" => "value1", "key2" => "value2", "key3" => "value3"]; + + var result:Array = MapTools.values(testMap); + result.sort(SortUtil.alphabetically); + Assert.areEqual(["value1", "value2", "value3"], result); + } + + @Test + public function testKeyValues() + { + var testMap:Map = ["key1" => "value1", "key2" => "value2", "key3" => "value3"]; + + var result:Array = MapTools.keyValues(testMap); + result.sort(SortUtil.alphabetically); + Assert.areEqual(["key1", "key2", "key3"], result); + } +} diff --git a/tests/unit/source/funkin/util/tools/StringToolsTest.hx b/tests/unit/source/funkin/util/tools/StringToolsTest.hx new file mode 100644 index 000000000..215b5e402 --- /dev/null +++ b/tests/unit/source/funkin/util/tools/StringToolsTest.hx @@ -0,0 +1,59 @@ +package funkin.util.tools; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import funkin.util.tools.StringTools; + +@:access(funkin.util.tools.StringTools) +class StringToolsTest extends FunkinTest +{ + public function new() + { + super(); + } + + @BeforeClass + public function beforeClass() {} + + @AfterClass + public function afterClass() {} + + @Before + public function setup() {} + + @After + public function tearDown() {} + + @Test + public function testToTitleCase() + { + var input = "hello world"; + + Assert.areEqual("Hello World", StringTools.toTitleCase(input)); + } + + @Test + public function testToLowerKebabCase() + { + var input = "hello world"; + + Assert.areEqual("hello-world", StringTools.toLowerKebabCase(input)); + } + + @Test + public function testToUpperKebabCase() + { + var input = "hello world"; + + Assert.areEqual("HELLO-WORLD", StringTools.toUpperKebabCase(input)); + } + + @Test + public function testParseJSON() + { + var input = "{ \"hello\": \"world\" }"; + + Assert.areEqual({hello: "world"}, StringTools.parseJSON(input)); + } +} diff --git a/tests/unit/source/import.hx b/tests/unit/source/import.hx new file mode 100644 index 000000000..89264c0c9 --- /dev/null +++ b/tests/unit/source/import.hx @@ -0,0 +1,21 @@ +#if !macro +// Only import these when we aren't in a macro. +import funkin.util.Constants; +import funkin.Paths; +import flixel.FlxG; // This one in particular causes a compile error if you're using macros. + +// These are great. +using Lambda; +using StringTools; +using funkin.util.tools.ArrayTools; +using funkin.util.tools.ArraySortTools; +using funkin.util.tools.IteratorTools; +using funkin.util.tools.MapTools; +using funkin.util.tools.StringTools; +#end + +// Testing-specific +// Mocking +import mockatoo.Mockatoo.*; + +using mockatoo.Mockatoo; diff --git a/tests/unit/start-mac-native.sh b/tests/unit/start-mac-native.sh new file mode 100755 index 000000000..fb6c812bd --- /dev/null +++ b/tests/unit/start-mac-native.sh @@ -0,0 +1,3 @@ +#!/bin/zsh + +haxe test-cpp.hxml diff --git a/tests/unit/start-mac-web.sh b/tests/unit/start-mac-web.sh new file mode 100755 index 000000000..66af469f7 --- /dev/null +++ b/tests/unit/start-mac-web.sh @@ -0,0 +1,3 @@ +#!/bin/zsh + +haxe test-web.hxml diff --git a/tests/unit/start-win-native.bat b/tests/unit/start-win-native.bat new file mode 100644 index 000000000..7678a86ea --- /dev/null +++ b/tests/unit/start-win-native.bat @@ -0,0 +1,3 @@ +REM Launches the unit tests for the native target on Windows. + +haxe test-cpp.hxml diff --git a/tests/unit/test-cpp.hxml b/tests/unit/test-cpp.hxml new file mode 100644 index 000000000..9379f841d --- /dev/null +++ b/tests/unit/test-cpp.hxml @@ -0,0 +1,11 @@ +# Updates TestSuite.hx to include all tests +#-cmd haxelib run munit gen +# Actually performs the tests +#-cmd haxelib run munit test -debug -coverage +# -debug may or may not be needed +# -coverage adds code coverage reporting + +# Legacy style. Doesn't give detailed coverage reports, +# but it works without crashing. +-cmd haxelib run munit gen +-cmd haxelib run lime test cpp diff --git a/tests/unit/test-web.hxml b/tests/unit/test-web.hxml new file mode 100644 index 000000000..c7c2ab444 --- /dev/null +++ b/tests/unit/test-web.hxml @@ -0,0 +1,5 @@ +# Update the test runner classes +# TODO: This just opens the browser and doesn't do anything? +-cmd haxelib run munit gen +-cmd haxelib run lime build html5 +-cmd haxelib run lime test html5 diff --git a/tests/unit/test.hxml b/tests/unit/test.hxml new file mode 100644 index 000000000..cece0c43a --- /dev/null +++ b/tests/unit/test.hxml @@ -0,0 +1,32 @@ +## CPP +--next +-main TestMain +-cpp build/cpp_test +# Funkin' deps +-lib lime +-lib openfl +-lib flixel +-lib flixel-addons +-lib flixel-ui +-lib hscript +-lib polymod +-lib haxeui-core +-lib haxeui-flixel +-lib flxanimate +-lib hxCodec +-lib thx.semver +-lib json2object +-lib tink_json +# Test deps +-lib munit +-lib hamcrest +-lib mcover +-lib mockatoo +# Class paths +-cp source +-cp ../../source +# Flixel macros +--remap flash:openfl +--macro flixel.system.macros.FlxDefines.run() +# Funkin' macros +--macro addMetadata('@:build(funkin.util.macro.FlxMacro.buildFlxBasic())', 'flixel.FlxBasic') diff --git a/tests/unit/test.hxml-old b/tests/unit/test.hxml-old new file mode 100644 index 000000000..d86661fc8 --- /dev/null +++ b/tests/unit/test.hxml-old @@ -0,0 +1,24 @@ +## JavaScript HTML5 +--next +-js build/js_test.js +# Funkin' deps +-lib lime +-lib openfl +-lib flixel +-lib flixel-addons +-lib hscript +-lib flixel-ui +-lib haxeui-core +-lib haxeui-flixel +-lib polymod +-lib flxanimate +-lib hxCodec +-lib thx.semver +-lib json2object +-lib tink_json +# Test deps +-lib munit +-lib hamcrest +# Class paths +-cp source +-cp ../../source