1// Copyright (C) MongoDB, Inc. 2014-present. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); you may 4// not use this file except in compliance with the License. You may obtain 5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 6 7package mongostat 8 9import ( 10 "io/ioutil" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/mongodb/mongo-tools-common/testtype" 16 "github.com/mongodb/mongo-tools/mongostat/stat_consumer/line" 17 "github.com/mongodb/mongo-tools/mongostat/status" 18 . "github.com/smartystreets/goconvey/convey" 19 "gopkg.in/mgo.v2/bson" 20) 21 22func readBSONFile(file string, t *testing.T) (stat *status.ServerStatus) { 23 stat = &status.ServerStatus{} 24 ssBSON, err := ioutil.ReadFile(file) 25 if err == nil { 26 err = bson.Unmarshal(ssBSON, stat) 27 } 28 if err != nil { 29 t.Logf("Could not load new ServerStatus BSON: %s", err) 30 t.FailNow() 31 } 32 return 33} 34 35func TestStatLine(t *testing.T) { 36 testtype.SkipUnlessTestType(t, testtype.UnitTestType) 37 38 defaultHeaders := make([]string, len(line.CondHeaders)) 39 for i, h := range line.CondHeaders { 40 defaultHeaders[i] = h.Key 41 } 42 defaultConfig := &status.ReaderConfig{ 43 HumanReadable: true, 44 } 45 46 serverStatusOld := readBSONFile("test_data/server_status_old.bson", t) 47 serverStatusNew := readBSONFile("test_data/server_status_new.bson", t) 48 serverStatusNew.ShardCursorType = nil 49 serverStatusOld.ShardCursorType = nil 50 51 Convey("StatsLine should accurately calculate opcounter diffs", t, func() { 52 statsLine := line.NewStatLine(serverStatusOld, serverStatusNew, defaultHeaders, defaultConfig) 53 So(statsLine.Fields["insert"], ShouldEqual, "10") 54 So(statsLine.Fields["query"], ShouldEqual, "5") 55 So(statsLine.Fields["update"], ShouldEqual, "7") 56 So(statsLine.Fields["delete"], ShouldEqual, "2") 57 So(statsLine.Fields["getmore"], ShouldEqual, "3") 58 command := strings.Split(statsLine.Fields["command"], "|")[0] 59 So(command, ShouldEqual, "669") 60 So(statsLine.Fields["faults"], ShouldEqual, "5") 61 62 locked := strings.Split(statsLine.Fields["locked_db"], ":") 63 So(locked[0], ShouldEqual, "test") 64 So(locked[1], ShouldEqual, "50.0%") 65 qrw := strings.Split(statsLine.Fields["qrw"], "|") 66 So(qrw[0], ShouldEqual, "3") 67 So(qrw[1], ShouldEqual, "2") 68 arw := strings.Split(statsLine.Fields["arw"], "|") 69 So(arw[0], ShouldEqual, "4") 70 So(arw[1], ShouldEqual, "6") 71 So(statsLine.Fields["net_in"], ShouldEqual, "2.00k") 72 So(statsLine.Fields["net_out"], ShouldEqual, "3.00k") 73 So(statsLine.Fields["conn"], ShouldEqual, "5") 74 }) 75 76 serverStatusNew.SampleTime, _ = time.Parse("2006 Jan 02 15:04:05", "2015 Nov 30 4:25:33") 77 Convey("StatsLine with non-default interval should calculate average diffs", t, func() { 78 statsLine := line.NewStatLine(serverStatusOld, serverStatusNew, defaultHeaders, defaultConfig) 79 // Opcounters and faults are averaged over sample period 80 So(statsLine.Fields["insert"], ShouldEqual, "3") 81 So(statsLine.Fields["query"], ShouldEqual, "1") 82 So(statsLine.Fields["update"], ShouldEqual, "2") 83 delete := strings.TrimPrefix(statsLine.Fields["delete"], "*") 84 So(delete, ShouldEqual, "0") 85 So(statsLine.Fields["getmore"], ShouldEqual, "1") 86 command := strings.Split(statsLine.Fields["command"], "|")[0] 87 So(command, ShouldEqual, "223") 88 So(statsLine.Fields["faults"], ShouldEqual, "1") 89 90 locked := strings.Split(statsLine.Fields["locked_db"], ":") 91 So(locked[0], ShouldEqual, "test") 92 So(locked[1], ShouldEqual, "50.0%") 93 qrw := strings.Split(statsLine.Fields["qrw"], "|") 94 So(qrw[0], ShouldEqual, "3") 95 So(qrw[1], ShouldEqual, "2") 96 arw := strings.Split(statsLine.Fields["arw"], "|") 97 So(arw[0], ShouldEqual, "4") 98 So(arw[1], ShouldEqual, "6") 99 So(statsLine.Fields["net_in"], ShouldEqual, "666b") 100 So(statsLine.Fields["net_out"], ShouldEqual, "1.00k") 101 So(statsLine.Fields["conn"], ShouldEqual, "5") 102 }) 103} 104 105func TestIsMongos(t *testing.T) { 106 testtype.SkipUnlessTestType(t, testtype.UnitTestType) 107 108 runCheck := func(process string) bool { 109 return status.IsMongos(&status.ServerStatus{ 110 Process: process, 111 }) 112 } 113 114 Convey("should accept reasonable process names", t, func() { 115 So(runCheck("/mongos-prod.exe"), ShouldBeTrue) 116 So(runCheck("/mongos.exe"), ShouldBeTrue) 117 So(runCheck("mongos"), ShouldBeTrue) 118 So(runCheck("mongodb/bin/mongos"), ShouldBeTrue) 119 So(runCheck(`C:\data\mci\48de1dc1ec3c2be5dcd6a53739578de4\src\mongos.exe`), ShouldBeTrue) 120 }) 121 Convey("should accept reasonable process names", t, func() { 122 So(runCheck("mongosx/mongod"), ShouldBeFalse) 123 So(runCheck("mongostat"), ShouldBeFalse) 124 So(runCheck("mongos_stuff/mongod"), ShouldBeFalse) 125 So(runCheck("mongos.stuff/mongod"), ShouldBeFalse) 126 So(runCheck("mongodb/bin/mongod"), ShouldBeFalse) 127 }) 128} 129