-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue #101 unit test and fosnola's fix #441
Conversation
Well, it failed, but not in the way you want… I think? |
That's right. The test scenarios need to get copied over to the output by Xcode, so that one failed. And the scons builds need to actually run the tests. and copy over the test scenarios. Which I think should happen for every debug build but not release builds, so I'm gonna change ci.yml to call scons with debug=true as well. |
Actually these scenarios should just go in the test files folder. Much easier that way. And then the tests won't fail for scons release builds. |
It says the macos-scons build passed even though it has the same segfault as the macos-xcode build. That seems bad. As for win-scons and linux, it looks like they didn't even run the tests. Is that intentional? |
I think when I changed the scons build to have all the partial flags, I made test default to false. So, I tried passing I don't understand why macos-xcode is giving a segfault -- other unit tests access the |
Now that I think of it, I've only reproduced the bug in a Mac build. So it's possible that Windows and Linux are running the tests, and passing the tests, because the conversion already worked properly on those targets. I'm gonna go check. |
I saw the segfault on one of the Windows builds too. |
I got the segfaults to show as test failures, at least. |
There was no output from the unit tests on linux? That's a bit weird… but it did clearly terminate scons, at least… |
Frankly I don't know why the platforms that are showing the test output, are. Since it's a subprocess. (Is piping subprocess output the Python default? Maybe it is on some platforms, but not others?) I desperately wish I could spend more time on real problems than on build/test problems. 🤦♀️ |
if(pop_paths){ | ||
fs::path graphics_path = ResMgr::graphics.popPath(); | ||
for(auto p : graphics_path) { | ||
if(p.string() == "data") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect this check is intended to solve the issue that you added pop_paths
for, but I'm not sure… do you know what "data" is? Is that related to the install path of a scons build?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
build/Blades of Exile/data
is the output folder for all platforms where the assets are stored. So I think that check is determining if the path on top of the stack is a final output path, and if it is, leaving it. That said, I haven't looked at the Resource Manager code at all, so I don't know why it has a push/pop abstraction in it to begin with. So I'm just guessing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intent is to not pop the core path to the assets distributed with the game. When loading a scenario, if it has graphics or sounds inside it, those paths are pushed. When the scenario is unloaded, the paths specific to that scenario must be popped, but they might not have been pushed in the first place, so what this does is pop the top path, check if it's the core game asset path, and push it back on if it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…does that make sense? It sounds rather convoluted…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that does make sense. I forgot that there would be contextual paths for scenarios--so the pop is to remove the context of whatever scenario the player was in before.
So is it okay that I added the non-pop option? Seems cleaner than the other alternative I considered, putting the files in a data folder even though they're not being packaged for output. Or doing something more convoluted to detect whether the top-level path is for the tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it could just only pop if there are more than one, maybe? idk. I think pop_path is a fine solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm… I guess another option would be to put the test path underneath the main data path, though that seems potentially a bit stupid (it might mean the main data path is on the stack twice?).
I'm not sure what's best here. I guess the variable isn't terrible, but I'd definitely prefer if it wasn't necessary.
Perhaps the best way would be for the scenario to record whether or not it pushed paths…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's at least add a TODO comment or open an issue about this, because I really don't like the use of an extra parameter here. We should find something better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about this -- push_path() takes a bool argument, temporary
or somesuch, and there's a stack of bools corresponding to the stack of paths, marking which ones are temporary and should pop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm… I'm not too fond of that idea either, but… it might be slightly less bad than the extra parameter in the scenario loading functions.
I already mentioned what I think the best approach probably is.
So, the version of the check that uses the newer scenario format is passing, which we expected it to because it's not converting rectangles at all. But the legacy Windows and Mac scenarios, we want to fail because 3 != 5 and 5 != 3, not because 0 != 5 and 0 != 3 This must be because the "town record" failed to read, which is something I have to figure out what it means, unless you have an idea @CelticMinstrel |
Oh the universal one isn't passing the test, I have it commented out.... |
Ok, interesting--the width and height are reported as 6 and 4 despite the rectangle only containing 5x3 squares the party can inhabit. But that's a weird quirk of That's from getting the universal case to work. I still don't know how to fix the legacy ones. |
It's kinda like the way ranges work in the STL – the rectangle covers all spaces in x range [left, right) and all spaces in y range [top, bottom). This is probably like that because Quickdraw / WinAPI already did things that way, but I don't remember. (It probably makes more sense when you realize that the structure was originally intended to address pixels, not tiles.) |
This will avoid future repeats of the situation where it took way too long to figure out why a unit test wasn't working
I started looking again at the 2nd commit that fosnola said is part of this fix. I know that this first commit fixes the bug when going into a scenario with a brand-new save file, but going over the 2nd commit it does appear to me now to be related, like we might want to cherry-pick it, but I don't know enough about file loading to know if it's correct: |
…ing a Windows scenario note: this may be succeptible to break the loading of some legacy save, but there are already broken....
I'm equally not sure. I suspect changing the There are ultimately two concerns when loading a legacy file:
A legacy Mac scenario (or saved game) is big-endian with TLBR rectangles, and a legacy Windows scenario is little-endian with LTRB rectangles. The current version of the game only uses TLBR rectangles. The host could either be little-endian or big-endian. (In practice, it will usually be little-endian, but there is absolutely no guarantee of that, and the game needs to run correctly on a big-endian machine.) So I think that gives four possible cases that all need to work correctly when loading a legacy scenario (or saved game), as shown by this table:
I have a suspicion that the commit in question makes the little-endian cases work correctly but might break the big-endian cases. It's pretty hard to actually test the big-endian cases (unless you have access to an old PPC computer that you can install Linux on, or maybe something like a jailbroken Wii or Xbox360 that can run arbitrary code), but we should at least try to make sure it will theoretically work. |
If I'm being honest I haven't fully reasoned through understanding the first commit here--all I know for sure is it makes the unit test pass and the boundaries work as expected when testing manually ingame on Mac. This legacy conversion and endianness stuff is really pushing the boundaries of what I understand, can properly test, etc. I wonder if there's a Github Actions runner that is big-endian? I also wonder, how irresponsible would it be to leave the legacy conversion case of this bug un-fixed, just to see if no one ever comes forward with a legacy save that happens to be in a rectangular town and is affected by this bug. Perhaps so long after the game's heyday, no one still possesses such a legacy save who would be in the audience of a BoE 2.0 release. This is lazy thinking, but we do need to triage a lot more aggressively in general. |
I think it's fairly unlikely. I'm not sure how widely-used the PPC or M68k series are these days. Some processors (like ARM, which is admittedly quite commonly used) are bi-endian and can thus be run either in little-endian or big-endian mode, but I don't know how common it is to run them in big-endian mode. More to the point, most consumer CPUs are little-endian nowadays, so the GitHub runners would probably be skewed towards that because it's what most people need to test. Though I think I remember something about being able to host your own runners, but that's probably more than we can manage.
It's definitely higher priority to ensure that legacy scenarios work, rather than legacy saves. I think it's probably worth merging this even without reasoning through whether the other commit helps or what happens in the big-endian cases. Anyway, looking at the code for the current commit, it does look like it potentially handles all 4 cases correctly, but I haven't analyzed it in detail to make sure. We can leave the other commit for saved games until another time when one of us (or someone else) has time to analyze the code more thoroughly. |
This unit test for issue #101 compiles but I can't run it locally because of, of all things, rpath problems with the unit tests built through mac scons. So hopefully the github actions show that this test fails as expected.