Scenario: Blindness Cure cures Blindness
Given I use the "minimal" database
And I add player and character "TestBlind01"
And I give the character a "blind" effect of "1" for "999" turns
And the server is started
And I log on as "TestBlind01"
And I enter the game
And I saw a message "You are blind!"
And I exit the game
And I exit the chat
And I log out
When I give the character a "blindness_cure" effect of "1" for "1" turns
And I log on as "TestBlind01"
And I enter the game
Then I did not see a message "You are blind!"
Scenario: Blindness Cure gives appropriate output on curing blindness while offline
Given I use the "minimal" database
And I add player and character "TestBlind01"
And I give the character a "blind" effect of "1" for "999" turns
And the server is started
And I log on as "TestBlind01"
And I enter the game
And I saw a message "You are blind!"
And I exit the game
And I exit the chat
And I log out
When I give the character a "blindness_cure" effect of "1" for "1" turns
And I log on as "TestBlind01"
And I enter the game
Then within "1" turns I see the message "Your blindness has been cured!"
Scenario: Blindness Cure gives appropriate output on curing blindness while online
Given I use the "minimal" database
And I add player and character "TestBlind01"
And I give the character a "blind" effect of "1" for "999" turns
And I put a blindness cure in the the character's left hand
And the server is started
And I log on as "TestBlind01"
And I enter the game
And I saw a message "You are blind!"
When I open "bottle"
And I drink "bottle"
Then within "1" turns I see the message "Your blindness has been cured!"
Which one do you think passes, and which one fails?
If you said the one where I cure the character’s blindness while they’re offline (which could never
actually happen) fails, you get a point. I believe it’s because the effect text is being written to
the client before it’s ready, but that’s not the lesson here.
I’ve been too quick to just tweak something in the database, instead of making it happen in the
game itself. True, this can make the tests faster and/or more repeatable in some cases, but it
leads to very artificial results. I marked the first test case as a bug, but is it? We’re testing
a scenario which cannot naturally occur.
When I decided to write the second test case, I was surprised at how easy it was. Grab the
appropriate potion from the production database into the minimal one, add a few steps (mostly
using code we already had), and viola!
Going forward, I’ll try to favor a natural in-world way to get to a test scenario instead of
relying completely on database tweaking.
Recently while working on a post, rendering the blog became unusably slow, even with just the one
post isolated. So I narrowed down what was taking all the time:
Line 61, where the markup is matched against the CaptionUrlTitle, was always the current line
being executed when I would get impatient and abort the build. Throwing a little debug around it
shed some light:
Checking features/player_effects.feature https://gitlab.com/LiBiPlJoe/seitan-spin/blob/master/features/player_effects.feature#L183 against (?i-mx:(\S[\S\s]*)\s+(https?:\/\/\S+|\/\S+)\s*(.+)?)...
...that took 0.001 seconds.
Checking features/player_effects.feature https://gitlab.com/LiBiPlJoe/seitan-spin/blob/master/features/player_effects.feature#L201 against (?i-mx:(\S[\S\s]*)\s+(https?:\/\/\S+|\/\S+)\s*(.+)?)...
...that took 0.0 seconds.
Checking Assets/Managers/NpcManager.cs <a href="https://gitlab.com/LiBiPlJoe/ste-reez-muvi/blob/de2a511228e36fc59020c48311acf6eff1364129/Assets/Managers/NpcManager.cs#L116">https://gitlab.com/LiBiPlJoe/ste-reez-muvi/blob/de2a511228e36fc59020c48311acf6eff1364129/Assets/Managers/NpcManager.cs#L116</a> against (?i-mx:(\S[\S\s]*)\s+(https?:\/\/\S+|\/\S+)\s*(.+)?)...
...that took 2.321133 seconds.
Checking Assets/DragonsSpine/DAL/DBNPC.cs <a href="https://gitlab.com/LiBiPlJoe/ste-reez-muvi/blob/de2a511228e36fc59020c48311acf6eff1364129/Assets/DragonsSpine/DAL/DBNPC.cs#L136">https://gitlab.com/LiBiPlJoe/ste-reez-muvi/blob/de2a511228e36fc59020c48311acf6eff1364129/Assets/DragonsSpine/DAL/DBNPC.cs#L136</a> against (?i-mx:(\S[\S\s]*)\s+(https?:\/\/\S+|\/\S+)\s*(.+)?)...
...that took 19.158096 seconds.
Not only the text we expect, but also the already-processed text is being pushed through the
plugin. And when it’s the already-processed text, not only does it not match the regex, but it
takes a huge amount of time.
Regenerating the whole blog?
...done in 1093.42754 seconds.
Let’s try something simple like
skipping the regex
if we see there’s already a link in the markup:
Regular expressions are a powerful tool, but it doesn’t come for free. There’s always a worst-case
string, and it may take some real time to churn through it. In this case it’s worth doing some
filtering of the incoming text before it gets to the complex regex (just take care that the
filtering is not just as expensive).
# bug - There are two special values, 'normal' and 'old-kesmai' that should not be allowed.@bugScenario: APP_PROTOCOL set to invalid value - normal
Given I use the "minimal" database as-is
And I set "APP_PROTOCOL" in the config file to "normal"
When the server is started
Then the log shows a fatal error "Invalid APP_PROTOCOL"
# bug - There are two special values, 'normal' and 'old-kesmai' that should not be allowed.@bugScenario: APP_PROTOCOL set to invalid value - old-kesmai
Given I use the "minimal" database as-is
And I set "APP_PROTOCOL" in the config file to "old-kesmai"
When the server is started
Then the log shows a fatal error "Invalid APP_PROTOCOL"
Not a serious bug, to be sure, as long as the config file doesn’t use one of the two magic strings
in the code as the value for APP_PROTOCOL. Easy to guard against, though:
#regionBadConfig// Don't let APP_PROTOCOL be set to either of the predefined protocol identifiers.if(APP_PROTOCOL=="normal"||APP_PROTOCOL=="old-kesmai"){Utils.Log("Invalid APP_PROTOCOL.",Utils.LogType.SystemFatalError);return-1;}#endregion
# bug - Restocking stored procedure, [prApp_Stores_Restock], returns zero despite rows# having been changed.@bugScenario: ClearStores True, RestockStores True causes stores to be restocked on server startup
Given I use the "minimal" database
And I add a vendor "TestVend01"
And I give vendor "TestVend01" the following items:
| itemID | notes | original | stocked | restock | | 30480 | Small Rock | false | 1 | 0 | | 33020 | Red Berries| true | 7 | 33 |And I set "ClearStores" in the config file to "True"
And I set "RestockStores" in the config file to "True"
When the server executable is started
And I allow time for the server to complete startup
And the log shows "1" items restocked in stores
Believing my comment, I dig into the SQL for the stored procedure.
/****** Object: StoredProcedure [dbo].[prApp_Stores_Restock] ******/SETANSI_NULLSONGOSETQUOTED_IDENTIFIERONGO----------------------------------------------------------------------------
-- Restock items in the Stores table
----------------------------------------------------------------------------
CREATEPROC[dbo].[prApp_Stores_Restock]ASUPDATEStoresSETstocked=restockWHERE(original=1)ANDstocked<>restockGO
Seems like it should work fine, and return the number of rows that were updated. But sure enough,
the log shows I was getting 0.
I did a web search, and the whole internet screams “NOCOUNT!”. I must have NOCOUNT enabled, on
the connection or in the procedure or somewhere, and that must be my problem.
Except adding a SET NOCOUNT OFF to the procedure had no effect. And when I run the procedure in
SQL Server Management Studio, and look at the messages tab, I am getting a notification of how
many rows were changed.
So I turn to the server code, initially to add some more debug output.