Skip to main content
  1. Posts/

Day 58 - Huh.

OldDays seitan-spin cucumber SQL

Super Mario Crossover
Super Mario Crossover

In which it becomes increasingly clear that our database snapshot and our code snapshot are not quite in sync.

APP_NAME
#

So we sit down and write a bunch of tests for APP_NAME. Even more than for APP_VERSION, because it shows up in more places:

features/config_file.feature
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Scenario: APP_NAME reflected in the log
Scenario: APP_NAME reflected in the welcome message
Scenario: APP_NAME used when trying to ignore a staff member
Scenario: APP_NAME used in user list
Scenario: APP_NAME used in conference help
Scenario: APP_NAME reflected in the main menu
Scenario: APP_NAME reflected in the account menu
Scenario: APP_NAME reflected in the character menu
Scenario: APP_NAME reflected in welcome back message
Scenario: APP_NAME used in high score list

(In retrospect, I should probably go back and make the naming more consistent.)

Failure to ignore
#

After writing the support code for these, I still couldn’t get “APP_NAME used when trying to ignore a staff member” to pass. Instead of the expected chastisement:

DragonsSpine/Menus/Conference.cs
580
581
582
if ((Globals.eImpLevel)DAL.DBPlayer.getPlayerField(ignoreID, "ImpLevel", ch.ImpLevel.GetType()) >= Globals.eImpLevel.GM) // cannot ignore staff member
{
    ch.WriteLine("You cannot ignore a " + DragonsSpineMain.APP_NAME + " staff member.", Protocol.TextType.Error);

…we get nothing. Looking in the logs for some insight:

6/25/2016 10:50:05 AM: {SystemFailure} DBPlayer.getPlayerTable(142, ImpLevel)  Field was not found in any player table.

ImpLevel? But in my database it’s actually impLevel, and everywhere else in the code it’s referred to as impLevel. Let’s check the scripts bundled with the server code:

DragonsSpine/SQL Scripts/Player.sql
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
CREATE TABLE [Player] 
(
  [PlayerID]		[int]	IDENTITY NOT NULL PRIMARY KEY NONCLUSTERED ,
  [AccountID]		[int] NOT NULL REFERENCES Account(AccountID) ,
  [Account]		[nvarchar] (20) ,
  [protocol]		[nvarchar] (20) ,
  [Name] 			[nvarchar] (255) , 
  [gender]		[int]	NULL ,
  [Race]			[nvarchar] (20) NULL, 
  [CharClass]		[nvarchar] (2) NULL, 
  [CharClassFull]	[nvarchar] (15) NULL, 
  [ClassID]		[int]	NULL ,
  [Align]			[int]	NULL ,
  [ConfRoom]		[int]	NULL ,
  [ImpLevel]		[int]	NULL ,

Oh, so it’s actually supposed to be ImpLevel. Messed around with SQL Server a bit to make sure I’m being properly case-insensitive, but that doesn’t help much when the server code is grabbing all fields and doing a string compare.

DragonsSpine/DAL/DBPlayer.cs
39
40
41
42
foreach (DataColumn dc in dt.Columns)
{
    if (dc.ColumnName == field) { return tableNames[a]; }
}

So I change the capitalization of the field name and it still fails. Log says:

6/25/2016 11:21:55 PM: {SystemFailure} DBPlayer.getPlayerField(2, ImpLevel, DragonsSpine.Globals+eImpLevel) Unable to find DragonsSpine.Globals+eImpLevel in switch.

There’s no code to handle the type that ImpLevel is in the Character class. Not a DB issue, so it’s time to mark this case @bug and move on.

Hardcoding
#

Two more cases must be marked @bug, because the server code actually hardcodes the server name in the account and character menus.

DragonsSpine/Menus/Menu.cs
1
ch.WriteLine("Dragon's Spine ("+DragonsSpineMain.APP_VERSION+") Character Menu");
DragonsSpine/Menus/Menu.cs
1
ch.WriteLine("Dragon's Spine ("+DragonsSpineMain.APP_VERSION+") Account Menu");

Expect us?
#

config_file/features/config_file.feature
1
2
3
4
5
6
7
8
9
Scenario: APP_NAME used in high score list
  Given I use the "minimal" database as-is
  And I set "APP_NAME" in the config file to "Test HigSco"
  And the server executable is started
  And I allow time for the server to complete startup
  When I log on using a standard account
  And I enter the chat
  And I issue the high scores command
  Then I saw a high score list with application name "Test HigSco"

Doesn’t seem like it should be a problem, right? But the command /scores all is just returning usage info for the scores command. We know well enough to check the logs:

6/25/2016 4:36:21 AM: {SystemFailure} FAILURE: PC.getField(2, anonymous, False, Comments: )

anonymous? That’s not a field in the Player table. At least not in my Player table. I have a bad feeling about this…

DragonsSpine/SQL%20Scripts/Player.sql
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
CREATE TABLE [Player] 
(
  [PlayerID]		[int]	IDENTITY NOT NULL PRIMARY KEY NONCLUSTERED ,
  [AccountID]		[int] NOT NULL REFERENCES Account(AccountID) ,
  [Account]		[nvarchar] (20) ,
  [protocol]		[nvarchar] (20) ,
  [Name] 			[nvarchar] (255) , 
  [gender]		[int]	NULL ,
  [Race]			[nvarchar] (20) NULL, 
  [CharClass]		[nvarchar] (2) NULL, 
  [CharClassFull]	[nvarchar] (15) NULL, 
  [ClassID]		[int]	NULL ,
  [Align]			[int]	NULL ,
  [ConfRoom]		[int]	NULL ,
  [ImpLevel]		[int]	NULL ,
  [ImpImmortal]	[bit]	NOT NULL  DEFAULT (1) ,
  [ShowTitle]		[bit]	NOT NULL  DEFAULT (0) ,
  [Echo]			[bit]   NOT NULL  DEFAULT (0) ,
  [Anonymous]		[bit]	NOT NULL  DEFAULT (0) ,	

Time to take a serious look at how far we are from the expected DB schema. Tomorrow.


Useful Stuff
#

Selecting a SQL Server Collation

Part-time Game Development and Life Balance


More to come
More to come

Day 58 code - tests