package minecraft import ( "fmt" "reflect" "testing" "github.com/influxdata/telegraf/testutil" ) // TestParsePlayerName tests different Minecraft RCON inputs for players func TestParsePlayerName(t *testing.T) { // Test a valid input string to ensure player is extracted input := "1 tracked objective(s) for divislight:- jumps: 178 (jumps)" got, err := ParsePlayerName(input) want := "divislight" if err != nil { t.Fatalf("player returned error. Error: %s\n", err) } if got != want { t.Errorf("got %s\nwant %s\n", got, want) } // Test an invalid input string to ensure error is returned input = "" got, err = ParsePlayerName(input) want = "" if err == nil { t.Fatal("Expected error when player not present. No error found.") } if got != want { t.Errorf("got %s\n want %s\n", got, want) } // Test an invalid input string to ensure error is returned input = "1 tracked objective(s) for 😂:- jumps: 178 (jumps)" got, err = ParsePlayerName(input) want = "😂" if err != nil { t.Fatalf("player returned error. Error: %s\n", err) } if got != want { t.Errorf("got %s\n want %s\n", got, want) } } // TestParseScoreboard tests different Minecraft RCON inputs for scoreboard stats. func TestParseScoreboard(t *testing.T) { // test a valid input string to ensure stats are parsed correctly. input := `1 tracked objective(s) for divislight:- jumps: 178 (jumps)- sword: 5 (sword)` got, err := ParseScoreboard(input) if err != nil { t.Fatal("Unexpected error") } want := []Score{ { Name: "jumps", Value: 178, }, { Name: "sword", Value: 5, }, } if !reflect.DeepEqual(got, want) { t.Errorf("Got: \n%#v\nWant: %#v", got, want) } // Tests a partial input string. input = `1 tracked objective(s) for divislight:- jumps: (jumps)- sword: 5 (sword)` got, err = ParseScoreboard(input) if err != nil { t.Fatal("Unexpected error") } want = []Score{ { Name: "sword", Value: 5, }, } if !reflect.DeepEqual(got, want) { t.Errorf("Got: \n%#v\nWant:\n%#v", got, want) } // Tests an empty string. input = `` _, err = ParseScoreboard(input) if err == nil { t.Fatal("Expected input error, but error was nil") } // Tests when a number isn't an integer. input = `1 tracked objective(s) for divislight:- jumps: 178.5 (jumps)- sword: 5 (sword)` got, err = ParseScoreboard(input) if err != nil { t.Fatal("Unexpected error") } want = []Score{ { Name: "sword", Value: 5, }, } if !reflect.DeepEqual(got, want) { t.Errorf("Got: \n%#v\nWant: %#v", got, want) } //Testing a real life data scenario with unicode characters input = `7 tracked objective(s) for mauxlaim:- total_kills: 39 (total_kills)- "howdy doody": 37 (dalevel)- howdy: 37 (lvl)- jumps: 1290 (jumps)- iron_pickaxe: 284 (iron_pickaxe)- cow_kills: 1 (cow_kills)- "asdf": 37 (😂)` got, err = ParseScoreboard(input) if err != nil { t.Fatal("Unexpected error") } want = []Score{ { Name: "total_kills", Value: 39, }, { Name: "dalevel", Value: 37, }, { Name: "lvl", Value: 37, }, { Name: "jumps", Value: 1290, }, { Name: "iron_pickaxe", Value: 284, }, { Name: "cow_kills", Value: 1, }, { Name: "😂", Value: 37, }, } if !reflect.DeepEqual(got, want) { t.Errorf("Got: \n%#v\nWant: %#v", got, want) } } type MockClient struct { Result []string Err error } func (m *MockClient) Gather(d RCONClientProducer) ([]string, error) { return m.Result, m.Err } func TestGather(t *testing.T) { var acc testutil.Accumulator testConfig := Minecraft{ Server: "biffsgang.net", Port: "25575", client: &MockClient{ Result: []string{ `1 tracked objective(s) for divislight:- jumps: 178 (jumps)`, `7 tracked objective(s) for mauxlaim:- total_kills: 39 (total_kills)- "howdy doody": 37 (dalevel)- howdy: 37 (lvl)- jumps: 1290 (jumps)- iron_pickaxe: 284 (iron_pickaxe)- cow_kills: 1 (cow_kills)- "asdf": 37 (😂)`, `5 tracked objective(s) for torham:- total_kills: 29 (total_kills)- "howdy doody": 33 (dalevel)- howdy: 33 (lvl)- jumps: 263 (jumps)- "asdf": 33 (😂)`, }, Err: nil, }, clientSet: true, } err := testConfig.Gather(&acc) if err != nil { t.Fatalf("gather returned error. Error: %s\n", err) } if !testConfig.clientSet { t.Fatalf("clientSet should be true, client should be set") } tags := map[string]string{ "player": "divislight", "server": "biffsgang.net:25575", } assertContainsTaggedStat(t, &acc, "minecraft", "jumps", 178, tags) tags["player"] = "mauxlaim" assertContainsTaggedStat(t, &acc, "minecraft", "cow_kills", 1, tags) tags["player"] = "torham" assertContainsTaggedStat(t, &acc, "minecraft", "total_kills", 29, tags) } func assertContainsTaggedStat( t *testing.T, acc *testutil.Accumulator, measurement string, field string, expectedValue int, tags map[string]string, ) { var actualValue int for _, pt := range acc.Metrics { if pt.Measurement == measurement && reflect.DeepEqual(pt.Tags, tags) { for fieldname, value := range pt.Fields { if fieldname == field { actualValue = value.(int) if value == expectedValue { return } t.Errorf("Expected value %d\n got value %d\n", expectedValue, value) } } } } msg := fmt.Sprintf( "Could not find measurement \"%s\" with requested tags within %s, Actual: %d", measurement, field, actualValue) t.Fatal(msg) }