diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 4623382..57012f0 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -2,27 +2,22 @@ name: Go on: push: - branches: [ "main" ] paths: - '**.go' + - '.github/workflows/go.yml' pull_request: - branches: [ "main" ] paths: - '**.go' + - '.github/workflows/go.yml' jobs: - build: + test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up Go uses: actions/setup-go@v4 with: go-version: '1.20' - - - name: Build - run: go build ./... - - # - name: Test - # run: go test ./... + - name: Test + run: go test ./... diff --git a/go.mod b/go.mod index 7a403fb..2b9a77f 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-sqlite3 v1.14.17 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.52.0 // indirect @@ -43,4 +44,5 @@ require ( golang.org/x/net v0.24.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.19.0 // indirect + gorm.io/driver/sqlite v1.5.5 // indirect ) diff --git a/go.sum b/go.sum index bc956f8..b7ea83d 100644 --- a/go.sum +++ b/go.sum @@ -53,6 +53,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= +github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -88,5 +90,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E= +gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE= gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8= gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= diff --git a/orm/database.go b/orm/database.go index 7ca778d..cc2f0d0 100644 --- a/orm/database.go +++ b/orm/database.go @@ -9,6 +9,7 @@ import ( "github.com/ggmolly/belfast/logger" "google.golang.org/protobuf/proto" "gorm.io/driver/postgres" + "gorm.io/driver/sqlite" "gorm.io/gorm" ) @@ -21,6 +22,8 @@ const ( RootPacketDir = "protobuf" ) +type openFuncType func(dsn string) gorm.Dialector + func InitDatabase() bool { dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable TimeZone=Europe/Paris", os.Getenv("POSTGRES_HOST"), @@ -30,7 +33,14 @@ func InitDatabase() bool { os.Getenv("POSTGRES_DB"), ) var err error - GormDB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{ + var openFunc openFuncType + if os.Getenv("MODE") == "test" { + openFunc = sqlite.Open + dsn = "file::memory:?cache=shared" + } else { + openFunc = postgres.Open + } + GormDB, err = gorm.Open(openFunc(dsn), &gorm.Config{ PrepareStmt: true, }) if err != nil { @@ -72,6 +82,10 @@ func InitDatabase() bool { if err != nil { panic("failed to migrate database " + err.Error()) } + if os.Getenv("MODE") == "test" { + logger.LogEvent("ORM", "Init", "Skipping database seeding in test mode", logger.LOG_LEVEL_INFO) + return true + } // Pre-populate debug names table, user will be able to rename them later var count int64 GormDB.Model(&DebugName{}).Count(&count) diff --git a/tests/commander_test.go b/tests/commander_test.go new file mode 100644 index 0000000..4cfe8f0 --- /dev/null +++ b/tests/commander_test.go @@ -0,0 +1,287 @@ +package tests + +import ( + "os" + "testing" + + "github.com/ggmolly/belfast/orm" +) + +var fakeCommander orm.Commander + +var ( + fakeResources []orm.Resource + fakeItems []orm.Item +) + +func seedDb() { + tx := orm.GormDB.Begin() + for _, r := range fakeResources { + tx.Save(&r) + } + for _, i := range fakeItems { + tx.Save(&i) + } + if err := tx.Commit().Error; err != nil { + panic(err) + } +} + +func init() { + fakeCommander.AccountID = 1 + fakeCommander.CommanderID = 1 + fakeCommander.Name = "Fake Commander" + fakeResources = []orm.Resource{ + {ID: 1, Name: "Gold"}, + {ID: 2, Name: "Fake resource"}, + } + fakeItems = []orm.Item{ + {ID: 20001, Name: "Wisdom Cube"}, + {ID: 45, Name: "Fake Item"}, + {ID: 60, Name: "Fake Item 2"}, + } + + // Init the database + os.Setenv("MODE", "test") + orm.InitDatabase() + seedDb() + + fakeCommander.OwnedResourcesMap = make(map[uint32]*orm.OwnedResource) + fakeCommander.CommanderItemsMap = make(map[uint32]*orm.CommanderItem) + + tx := orm.GormDB.Begin() + // Fake resources + fakeResourcesCnt := []uint32{100, 30} + for i := 0; i < len(fakeResources); i++ { + resource := orm.OwnedResource{ + ResourceID: fakeResources[i].ID, + Amount: fakeResourcesCnt[i], + CommanderID: fakeCommander.CommanderID, + } + tx.Create(&resource) + fakeCommander.OwnedResources = append(fakeCommander.OwnedResources, resource) + fakeCommander.OwnedResourcesMap[fakeResources[i].ID] = &fakeCommander.OwnedResources[i] + } + + // Fake items + fakeItemsCnt := []uint32{5, 50, 3} + for i := 0; i < len(fakeItems); i++ { + item := orm.CommanderItem{ + ItemID: fakeItems[i].ID, + Count: fakeItemsCnt[i], + CommanderID: fakeCommander.CommanderID, + } + tx.Create(&item) + fakeCommander.Items = append(fakeCommander.Items, item) + fakeCommander.CommanderItemsMap[fakeItems[i].ID] = &fakeCommander.Items[i] + } + + tx.Create(&fakeCommander) + if err := tx.Commit().Error; err != nil { + panic(err) + } +} + +// Tests the behavior of orm.Commander.HasEnoughGold +func TestEnoughGold(t *testing.T) { + if !fakeCommander.HasEnoughGold(100) { + t.Errorf("Expected enough gold, has %d, need %d", fakeCommander.OwnedResourcesMap[1].Amount, 100) + } + if !fakeCommander.HasEnoughGold(50) { + t.Errorf("Expected enough gold, has %d, need %d", fakeCommander.OwnedResourcesMap[1].Amount, 50) + } + if !fakeCommander.HasEnoughGold(0) { + t.Errorf("Expected enough gold, has %d, need %d", fakeCommander.OwnedResourcesMap[1].Amount, 0) + } + if fakeCommander.HasEnoughGold(1000) { + t.Errorf("Expected not enough gold, has %d, need %d", fakeCommander.OwnedResourcesMap[1].Amount, 1000) + } +} + +// Tests the behavior of orm.Commander.HasEnoughCube +func TestEnoughCube(t *testing.T) { + if fakeCommander.HasEnoughCube(10) { + t.Errorf("Expected not enough cube, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 10) + } + if !fakeCommander.HasEnoughCube(5) { + t.Errorf("Expected enough cube, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 5) + } + if !fakeCommander.HasEnoughCube(0) { + t.Errorf("Expected enough cube, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 0) + } + if fakeCommander.HasEnoughCube(1000) { + t.Errorf("Expected not enough cube, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 1000) + } +} + +// Tests the behavior of orm.Commander.HasEnoughResource +func TestEnoughResource(t *testing.T) { + if !fakeCommander.HasEnoughResource(2, 1) { + t.Errorf("Expected enough resource, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 1) + } + if !fakeCommander.HasEnoughResource(2, 30) { + t.Errorf("Expected enough resource, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 30) + } + if !fakeCommander.HasEnoughResource(2, 0) { + t.Errorf("Expected enough resource, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 0) + } + if fakeCommander.HasEnoughResource(2, 1000) { + t.Errorf("Expected not enough resource, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 1000) + } + if fakeCommander.HasEnoughResource(3, 1) { // Resource not owned + t.Errorf("Expected not enough resource, has -, need %d", 1) + } +} + +// Tests the behavior of orm.Commander.HasEnoughItem +func TestEnoughItem(t *testing.T) { + if !fakeCommander.HasEnoughItem(20001, 5) { + t.Errorf("Expected enough item, has %d, need %d", fakeCommander.CommanderItemsMap[20001].Count, 5) + } + if !fakeCommander.HasEnoughItem(20001, 0) { + t.Errorf("Expected enough item, has %d, need %d", fakeCommander.CommanderItemsMap[20001].Count, 0) + } + if fakeCommander.HasEnoughItem(20001, 6) { + t.Errorf("Expected not enough item, has %d, need %d", fakeCommander.CommanderItemsMap[20001].Count, 6) + } + if fakeCommander.HasEnoughItem(20002, 1) { // Item not owned + t.Errorf("Expected not enough item, has -, need %d", 1) + } +} + +// Tests the behavior of ConsumeItem +func TestConsumeItem(t *testing.T) { + seedDb() + if err := fakeCommander.ConsumeItem(20001, 5); err != nil { + t.Errorf("Expected consume item, has %d, need %d", fakeCommander.CommanderItemsMap[20001].Count, 5) + } + if err := fakeCommander.ConsumeItem(20001, 0); err != nil { + t.Errorf("Expected not consume item, has %d, need %d", fakeCommander.CommanderItemsMap[20001].Count, 0) + } + if err := fakeCommander.ConsumeItem(20001, 1); err == nil { + t.Errorf("Expected not consume item, has -, need %d", 1) + } + if err := fakeCommander.ConsumeItem(20002, 1); err == nil { + t.Errorf("Expected not consume item, has -, need %d", 1) + } + if err := fakeCommander.ConsumeItem(20001, 400); err == nil { + t.Errorf("Expected not consume item, has %d, need %d", fakeCommander.CommanderItemsMap[20001].Count, 400) + } +} + +// Tests the behavior of ConsumeResource +func TestConsumeResource(t *testing.T) { + seedDb() + if err := fakeCommander.ConsumeResource(2, 5); err != nil { + t.Errorf("Expected consume resource, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 5) + } + if err := fakeCommander.ConsumeResource(2, 0); err != nil { + t.Errorf("Expected consume resource, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 0) + } + if err := fakeCommander.ConsumeResource(2, 1); err != nil { + t.Errorf("Expected consume resource, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 1) + } + if err := fakeCommander.ConsumeResource(3, 1); err == nil { + t.Errorf("Expected not consume resource, has -, need %d", 1) + } + if err := fakeCommander.ConsumeResource(2, 1000); err == nil { + t.Errorf("Expected not consume resource, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 1000) + } +} + +// Tests the behavior of AddItem +func TestAddItem(t *testing.T) { + seedDb() + base := fakeCommander.CommanderItemsMap[20001].Count + if err := fakeCommander.AddItem(20001, 5); err != nil { + t.Errorf("Attempt to add %d items (id: %d) failed", 5, 20001) + } + if fakeCommander.CommanderItemsMap[20001].Count != base+5 { + t.Errorf("Count mismatch, has %d, need %d", fakeCommander.CommanderItemsMap[20001].Count, base+5) + } else { + base += 5 + } + if err := fakeCommander.AddItem(20001, 0); err != nil { + t.Errorf("Attempt to add %d items (id: %d) failed", 0, 20001) + } + if fakeCommander.CommanderItemsMap[20001].Count != base { + t.Errorf("Count mismatch, has %d, need %d", fakeCommander.CommanderItemsMap[20001].Count, base) + } + if err := fakeCommander.AddItem(20002, 1); err != nil { + t.Errorf("Attempt to add %d items (id: %d) failed", 1, 20002) + } +} + +// Tests the behavior of AddResource +func TestAddResource(t *testing.T) { + seedDb() + base := fakeCommander.OwnedResourcesMap[2].Amount + if err := fakeCommander.AddResource(2, 5); err != nil { + t.Errorf("Attempt to add %d resources (id: %d) failed", 5, 2) + } + if fakeCommander.OwnedResourcesMap[2].Amount != base+5 { + t.Errorf("Count mismatch, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, base+5) + } else { + base += 5 + } + if err := fakeCommander.AddResource(2, 0); err != nil { + t.Errorf("Attempt to add %d resources (id: %d) failed", 0, 2) + } + if fakeCommander.OwnedResourcesMap[2].Amount != base { + t.Errorf("Count mismatch, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, base) + } + if err := fakeCommander.AddResource(3, 1); err != nil { + t.Errorf("Attempt to add %d resources (id: %d) failed", 1, 3) + } +} + +// Test set resource +func TestSetResource(t *testing.T) { + seedDb() + if err := fakeCommander.SetResource(2, 10); err != nil { + t.Errorf("Attempt to set resource failed") + } + if fakeCommander.OwnedResourcesMap[2].Amount != 10 { + t.Errorf("Count mismatch, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 10) + } + if err := fakeCommander.SetResource(2, 0); err != nil { + t.Errorf("Attempt to set resource failed") + } + if fakeCommander.OwnedResourcesMap[2].Amount != 0 { + t.Errorf("Count mismatch, has %d, need %d", fakeCommander.OwnedResourcesMap[2].Amount, 0) + } + if err := fakeCommander.SetResource(999, 1); err != nil { + t.Errorf("Attempt to set resource %d failed", 1) + } +} + +// Test set item +func TestSetItem(t *testing.T) { + seedDb() + if err := fakeCommander.SetItem(20001, 10); err != nil { + t.Errorf("Attempt to set item failed") + } + if fakeCommander.CommanderItemsMap[20001].Count != 10 { + t.Errorf("Count mismatch, has %d, need %d", fakeCommander.CommanderItemsMap[20001].Count, 10) + } + if err := fakeCommander.SetItem(20001, 0); err != nil { + t.Errorf("Attempt to set item failed") + } + if fakeCommander.CommanderItemsMap[20001].Count != 0 { + t.Errorf("Count mismatch, has %d, need %d", fakeCommander.CommanderItemsMap[20001].Count, 0) + } + if err := fakeCommander.SetItem(20001, 1); err != nil { + t.Errorf("Attempt to set item %d failed", 20001) + } +} + +// Test the behavior of orm.Commander.GetItemCount +func TestGetItemCount(t *testing.T) { + seedDb() + if fakeCommander.GetItemCount(20001) != 1 { + t.Errorf("Count mismatch, has %d, expected %d", fakeCommander.GetItemCount(20001), 1) + } + if fakeCommander.GetItemCount(8546213) != 0 { + t.Errorf("Count mismatch, has %d, expected %d", fakeCommander.GetItemCount(8546213), 0) + } +}