go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/cmd/statsd-to-tsmon/statsd_test.go (about) 1 // Copyright 2020 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "bytes" 19 "testing" 20 21 . "github.com/smartystreets/goconvey/convey" 22 ) 23 24 func TestParseStatsdMetric(t *testing.T) { 25 t.Parallel() 26 27 Convey("Happy path", t, func() { 28 roundTrip := func(line string) bool { 29 m := &StatsdMetric{} 30 read, err := ParseStatsdMetric([]byte(line), m) 31 So(err, ShouldBeNil) 32 So(read, ShouldEqual, len(line)) 33 34 // There should be no special chars in parsed portions. 35 for _, n := range m.Name { 36 So(n, ShouldNotContain, '.') 37 So(n, ShouldNotContain, ':') 38 So(n, ShouldNotContain, '|') 39 } 40 So(m.Value, ShouldNotContain, '.') 41 So(m.Value, ShouldNotContain, ':') 42 So(m.Value, ShouldNotContain, '|') 43 44 // Reconstruct the original line from parsed components. 45 buf := bytes.Join(m.Name, []byte{'.'}) 46 buf = append(buf, ':') 47 buf = append(buf, m.Value...) 48 buf = append(buf, '|') 49 switch m.Type { 50 case StatsdMetricGauge: 51 buf = append(buf, 'g') 52 case StatsdMetricCounter: 53 buf = append(buf, 'c') 54 case StatsdMetricTimer: 55 buf = append(buf, 'm', 's') 56 } 57 58 return string(buf) == line 59 } 60 61 So(roundTrip("a.bcd.xyz:123|g"), ShouldBeTrue) 62 So(roundTrip("a.b.c:123|c"), ShouldBeTrue) 63 So(roundTrip("a.b.c:123|ms"), ShouldBeTrue) 64 So(roundTrip("a:123|g"), ShouldBeTrue) 65 }) 66 67 Convey("Parses one line only", t, func() { 68 buf := []byte("a:123|g\nstuff") 69 m := &StatsdMetric{} 70 read, err := ParseStatsdMetric(buf, m) 71 So(err, ShouldBeNil) 72 So(buf[read:], ShouldResemble, []byte("stuff")) 73 74 So(m, ShouldResemble, &StatsdMetric{ 75 Name: [][]byte{{'a'}}, 76 Type: StatsdMetricGauge, 77 Value: []byte("123"), 78 }) 79 }) 80 81 Convey("Skips junk", t, func() { 82 buf := []byte("a:123|g|skipped junk\nstuff") 83 m := &StatsdMetric{} 84 read, err := ParseStatsdMetric(buf, m) 85 So(err, ShouldBeNil) 86 So(buf[read:], ShouldResemble, []byte("stuff")) 87 88 So(m, ShouldResemble, &StatsdMetric{ 89 Name: [][]byte{{'a'}}, 90 Type: StatsdMetricGauge, 91 Value: []byte("123"), 92 }) 93 }) 94 95 Convey("ErrMalformedStatsdLine", t, func() { 96 buf := []byte("a:b:c\nstuff") 97 m := &StatsdMetric{} 98 read, err := ParseStatsdMetric(buf, m) 99 So(err, ShouldEqual, ErrMalformedStatsdLine) 100 So(buf[read:], ShouldResemble, []byte("stuff")) 101 }) 102 103 Convey("ErrMalformedStatsdLine on empty line", t, func() { 104 buf := []byte("\nstuff") 105 m := &StatsdMetric{} 106 read, err := ParseStatsdMetric(buf, m) 107 So(err, ShouldEqual, ErrMalformedStatsdLine) 108 So(buf[read:], ShouldResemble, []byte("stuff")) 109 }) 110 111 Convey("ErrMalformedStatsdLine on empty name component", t, func() { 112 call := func(pat string) error { 113 buf := []byte(pat + "\nother stuff") 114 read, err := ParseStatsdMetric(buf, &StatsdMetric{}) 115 So(buf[read:], ShouldResemble, []byte("other stuff")) 116 return err 117 } 118 119 So(call("ab..cd:123|g"), ShouldEqual, ErrMalformedStatsdLine) 120 So(call("a.:123|g"), ShouldEqual, ErrMalformedStatsdLine) 121 So(call(".a:123|g"), ShouldEqual, ErrMalformedStatsdLine) 122 So(call(".:123|g"), ShouldEqual, ErrMalformedStatsdLine) 123 So(call(":|g"), ShouldEqual, ErrMalformedStatsdLine) 124 }) 125 126 Convey("ErrUnsupportedType", t, func() { 127 buf := []byte("a:123|h\nstuff") 128 m := &StatsdMetric{} 129 read, err := ParseStatsdMetric(buf, m) 130 So(err, ShouldEqual, ErrUnsupportedType) 131 So(buf[read:], ShouldResemble, []byte("stuff")) 132 }) 133 }