From 5d64c658983a0e1db2c6eaef0a65c0e68066ac52 Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 09:52:15 -0400 Subject: [PATCH 01/14] fix web100 warnings --- web100/tcpkis.go | 6 +++--- web100/web100.go | 34 +++++++++++++++++----------------- web100/web100_test.go | 13 +++++++------ 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/web100/tcpkis.go b/web100/tcpkis.go index 62f8af838..2ac8cbd07 100644 --- a/web100/tcpkis.go +++ b/web100/tcpkis.go @@ -20,7 +20,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } var buf bytes.Buffer @@ -28,7 +28,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } if clErr != nil { return nil, err @@ -182,6 +182,7 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ "tcp-kis.txt": &bintree{tcpKisTxt, map[string]*bintree{}}, }} @@ -232,4 +233,3 @@ func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } - diff --git a/web100/web100.go b/web100/web100.go index 83fd1a261..a4b9e755e 100644 --- a/web100/web100.go +++ b/web100/web100.go @@ -197,7 +197,7 @@ func NewVariable(s string) (*Variable, error) { // IPFromBytes handles the 17 byte web100 IP address fields. func IPFromBytes(data []byte) (net.IP, error) { if len(data) != 17 { - return net.IP{}, errors.New("Wrong number of bytes") + return net.IP{}, errors.New("wrong number of bytes") } switch addrType(data[16]) { case WEB100_ADDRTYPE_IPV4: @@ -207,7 +207,7 @@ func IPFromBytes(data []byte) (net.IP, error) { case WEB100_ADDRTYPE_UNKNOWN: fallthrough default: - return nil, errors.New("Invalid IP encoding") + return nil, errors.New("invalid IP encoding") } } @@ -271,7 +271,7 @@ func (v *Variable) Save(data []byte, snapValues Saver) error { // TODO - use byte array? snapValues.SetInt64(canonicalName, int64(data[0])) default: - return errors.New("Invalid field type") + return errors.New("invalid field type") } return nil } @@ -363,7 +363,7 @@ func parseFields(buf *bytes.Buffer, preamble string, terminator string) (*fieldS return nil, err } if pre != preamble { - return nil, errors.New("Expected preamble: " + + return nil, errors.New("expected preamble: " + // Strip terminal \n from each string for readability. preamble[:len(preamble)-1] + " != " + pre[:len(pre)-1]) } @@ -373,9 +373,9 @@ func parseFields(buf *bytes.Buffer, preamble string, terminator string) (*fieldS // line length is max var name size, plus 20 bytes for the 3 numeric fields. if err != nil || len(line) > VARNAME_LEN_MAX+20 { if err == io.EOF { - return nil, errors.New("Encountered EOF") + return nil, errors.New("encountered EOF") } - return nil, errors.New("Corrupted header") + return nil, errors.New("corrupted header") } if line == terminator { return fields, nil @@ -385,7 +385,7 @@ func parseFields(buf *bytes.Buffer, preamble string, terminator string) (*fieldS return nil, err } if fields.Length != v.Offset { - return nil, errors.New("Bad offset at " + line[:len(line)-2]) + return nil, errors.New("bad offset at " + line[:len(line)-2]) } fields.FieldMap[v.Name] = len(fields.Fields) fields.Fields = append(fields.Fields, *v) @@ -401,7 +401,7 @@ func parseConnectionSpec(buf *bytes.Buffer) (connectionSpec, error) { raw := make([]byte, 16) n, err := buf.Read(raw) if err != nil || n < 16 { - return connectionSpec{}, errors.New("Too few bytes for connection spec") + return connectionSpec{}, errors.New("too few bytes for connection spec") } // WARNING - the web100 code seemingly depends on a 32 bit architecture. // There is no "packed" directive for the web100_connection_spec, and the @@ -433,7 +433,7 @@ func NewSnapLog(raw []byte) (*SnapLog, error) { } if empty != "\n" { fmt.Printf("%v\n", []byte(empty)) - return nil, errors.New("Expected empty string") + return nil, errors.New("expected empty string") } // TODO - do these header elements always come in this order. @@ -460,7 +460,7 @@ func NewSnapLog(raw []byte) (*SnapLog, error) { t := make([]byte, 4) n, err := buf.Read(t) if err != nil || n < 4 { - return nil, errors.New("Too few bytes for logTime") + return nil, errors.New("too few bytes for logTime") } logTime := binary.LittleEndian.Uint32(t) @@ -472,13 +472,13 @@ func NewSnapLog(raw []byte) (*SnapLog, error) { gn := make([]byte, GROUPNAME_LEN_MAX) n, err = buf.Read(gn) if err != nil || n != GROUPNAME_LEN_MAX { - return nil, errors.New("Too few bytes for groupName") + return nil, errors.New("too few bytes for groupName") } // The groupname is a C char*, terminated with a null character. groupName := strings.SplitN(string(gn), "\000", 2)[0] if groupName != "read" { fmt.Println(groupName) - return nil, errors.New("Only 'read' group is supported") + return nil, errors.New("only 'read' group is supported") } connSpecOffset := len(raw) - buf.Len() @@ -556,7 +556,7 @@ func (snap *Snapshot) reset(data []byte, fields *fieldSet) { // SnapshotValues writes all values into the provided Saver. func (snap *Snapshot) SnapshotValues(snapValues Saver) error { if snap.raw == nil { - return errors.New("Empty/Invalid Snaplog") + return errors.New("empty/invalid Snaplog") } var field Variable for _, field = range snap.fields.Fields { @@ -569,7 +569,7 @@ func (snap *Snapshot) SnapshotValues(snapValues Saver) error { // SnapshotDeltas writes changed values into the provided Saver. func (snap *Snapshot) SnapshotDeltas(other *Snapshot, snapValues Saver) error { if snap.raw == nil { - return errors.New("Empty/Invalid Snaplog") + return errors.New("empty/invalid Snaplog") } if other.raw == nil { // If other is empty, return full snapshot @@ -579,7 +579,7 @@ func (snap *Snapshot) SnapshotDeltas(other *Snapshot, snapValues Saver) error { for _, field = range snap.fields.Fields { a := other.raw[field.Offset : field.Offset+field.Size] b := snap.raw[field.Offset : field.Offset+field.Size] - if bytes.Compare(a, b) != 0 { + if !bytes.Equal(a, b) { // Interpret and save the web100 field value. field.Save(b, snapValues) } @@ -593,7 +593,7 @@ func (sl *SnapLog) ChangeIndices(fieldName string) ([]int, error) { result := make([]int, 0, 100) field := sl.read.find(fieldName) if field == nil { - return nil, errors.New("Field not found") + return nil, errors.New("field not found") } last := make([]byte, field.Size) var s Snapshot // This saves about 2 usec, compared with creating new Snapshot for each row. @@ -607,7 +607,7 @@ func (sl *SnapLog) ChangeIndices(fieldName string) ([]int, error) { s.reset(sl.raw[offset+len(BEGIN_SNAP_DATA):offset+sl.read.Length], &sl.read) data := s.raw[field.Offset : field.Offset+field.Size] - if bytes.Compare(data, last) != 0 { + if !bytes.Equal(data, last) { result = append(result, i) } last = data diff --git a/web100/web100_test.go b/web100/web100_test.go index 59a4801a3..fad49f55a 100644 --- a/web100/web100_test.go +++ b/web100/web100_test.go @@ -93,7 +93,7 @@ func TestSnapshotContent(t *testing.T) { var old SimpleSaver json.Unmarshal([]byte(old1), &old) - snapshot, err := slog.Snapshot(1) + snapshot, _ := slog.Snapshot(1) snapshot.SnapshotValues(&saver) if !reflect.DeepEqual(old, saver) { t.Error("Does not match old output") @@ -103,7 +103,7 @@ func TestSnapshotContent(t *testing.T) { } json.Unmarshal([]byte(old1000), &old) - snapshot, err = slog.Snapshot(1000) + snapshot, _ = slog.Snapshot(1000) snapshot.SnapshotValues(&saver) if !reflect.DeepEqual(old, saver) { t.Error("Does not match old output") @@ -113,7 +113,7 @@ func TestSnapshotContent(t *testing.T) { } json.Unmarshal([]byte(old2000), &old) - snapshot, err = slog.Snapshot(2000) + snapshot, _ = slog.Snapshot(2000) snapshot.SnapshotValues(&saver) if !reflect.DeepEqual(old, saver) { t.Error("Does not match old output") @@ -151,7 +151,8 @@ func OneSnapshot(t *testing.T, name string, n int) { } // These files are in a different format, so don't try to parse them. -func xTestSnapshot200903(t *testing.T) { +func TestSnapshot200903(t *testing.T) { + t.Skip("Different format - skip test") OneSnapshot(t, "20090301T22:29:43.653205000Z-78.61.75.41:33538.s2c_snaplog", 2000) OneSnapshot(t, "20090301T22:29:43.653205000Z_78.61.75.41:46267.c2s_snaplog", 2000) } @@ -207,7 +208,7 @@ func TestChangeIndices(t *testing.T) { t.Fatalf(err.Error()) } - slog, err := web100.NewSnapLog(c2sData) + slog, _ := web100.NewSnapLog(c2sData) x, err := slog.ChangeIndices("CongestionSignals") if err != nil { @@ -225,7 +226,7 @@ func BenchmarkChangeIndices(b *testing.B) { b.Fatalf(err.Error()) } - slog, err := web100.NewSnapLog(data) + slog, _ := web100.NewSnapLog(data) b.StartTimer() for i := 0; i < b.N; i++ { From 413371b2ee0633cf2aeb6e34454f3034a48353ca Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 10:04:21 -0400 Subject: [PATCH 02/14] fix pt.go warnings --- parser/pt.go | 30 ++++++++++++++---------------- parser/pt_test.go | 24 ++++++++++++------------ 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/parser/pt.go b/parser/pt.go index f54883ba6..ed0789104 100644 --- a/parser/pt.go +++ b/parser/pt.go @@ -203,7 +203,7 @@ func ParseJSONL(testName string, rawContent []byte, tableName string, taskFilena if len(jsonStrings) != 5 { log.Println("Invalid test", taskFilename, " ", testName) log.Println(len(jsonStrings)) - return schema.PTTest{}, errors.New("Invalid test") + return schema.PTTest{}, errors.New("invalid test") } // Parse the first line for meta info. @@ -247,7 +247,7 @@ func ParseJSONL(testName string, rawContent []byte, tableName string, taskFilena return schema.PTTest{}, err } } - for i, _ := range tracelb.Nodes { + for i := range tracelb.Nodes { oneNode := &tracelb.Nodes[i] var links []schema.HopLink if len(oneNode.Links) == 0 { @@ -438,20 +438,20 @@ func ParseFirstLine(oneLine string) (protocol string, destIP string, serverIP st if index == 0 { segments := strings.Split(part, " ") if len(segments) != 4 { - return "", "", "", errors.New("corrupted first line.") + return "", "", "", errors.New("corrupted first line") } if len(segments[1]) <= 2 || !strings.HasPrefix(segments[1], "[(") || len(segments[3]) <= 2 || !strings.HasPrefix(segments[3], "(") { - return "", "", "", errors.New("Invalid data format in the first line.") + return "", "", "", errors.New("invalid data format in the first line") } serverIPIndex := strings.LastIndex(segments[1], ":") destIPIndex := strings.LastIndex(segments[3], ":") if serverIPIndex < 3 || destIPIndex < 2 { - return "", "", "", errors.New("Invalid data format in the first line.") + return "", "", "", errors.New("invalid data format in the first line") } serverIP = segments[1][2:serverIPIndex] destIP = segments[3][1:destIPIndex] if net.ParseIP(serverIP) == nil || net.ParseIP(destIP) == nil { - return "", "", "", errors.New("Invalid IP address in the first line.") + return "", "", "", errors.New("invalid IP address in the first line") } continue } @@ -465,7 +465,7 @@ func ParseFirstLine(oneLine string) (protocol string, destIP string, serverIP st if mm[0] == "protocol" { if mm[1] != "icmp" && mm[1] != "udp" && mm[1] != "tcp" { log.Printf("Unknown protocol") - return "", "", "", errors.New("Unknown protocol") + return "", "", "", errors.New("unknown protocol") } else { protocol = mm[1] } @@ -555,13 +555,11 @@ func (pt *PTParser) IsParsable(testName string, data []byte) (string, bool) { func (pt *PTParser) ParseAndInsert(meta map[string]bigquery.Value, testName string, rawContent []byte) error { metrics.WorkerState.WithLabelValues(pt.TableName(), "pt").Inc() defer metrics.WorkerState.WithLabelValues(pt.TableName(), "pt").Dec() - testId := filepath.Base(testName) - if meta["filename"] != nil { - testId = CreateTestId(meta["filename"].(string), filepath.Base(testName)) - pt.taskFileName = meta["filename"].(string) - } else { + if meta["filename"] == nil { return errors.New("empty filename") } + testId := CreateTestId(meta["filename"].(string), filepath.Base(testName)) + pt.taskFileName = meta["filename"].(string) // Process json output from traceroute-caller if strings.HasSuffix(testName, ".json") { @@ -669,7 +667,7 @@ func ProcessOneTuple(parts []string, protocol string, currentLeaves []Node, allN return errors.New("corrupted input") } if parts[3] != "ms" { - return errors.New("Malformed line. Expected 'ms'") + return errors.New("malformed line. Expected 'ms'") } var rtt []float64 //TODO: to use regexp here. @@ -688,7 +686,7 @@ func ProcessOneTuple(parts []string, protocol string, currentLeaves []Node, allN case protocol == "icmp": nums := strings.Split(parts[2], "/") if len(nums) != 4 { - return errors.New("Failed to parse rtts for icmp test. 4 numbers expected") + return errors.New("failed to parse rtts for icmp test. 4 numbers expected") } for _, num := range nums { oneRtt, err := strconv.ParseFloat(num, 64) @@ -765,7 +763,7 @@ func ProcessOneTuple(parts []string, protocol string, currentLeaves []Node, allN } } default: - return errors.New("Wrong format for IP address.") + return errors.New("wrong format for IP address") } return nil } @@ -859,7 +857,7 @@ func Parse(meta map[string]bigquery.Value, testName string, testId string, rawCo if len(allNodes) == 0 { // Empty test, stop here. - return cachedPTData{}, errors.New("Empty test") + return cachedPTData{}, errors.New("empty test") } // Check whether the last hop is the destIP fileName := "" diff --git a/parser/pt_test.go b/parser/pt_test.go index e4f194b8e..27449431c 100644 --- a/parser/pt_test.go +++ b/parser/pt_test.go @@ -169,16 +169,16 @@ func TestParseJSONLComplex(t *testing.T) { Source: schema.HopIP{IP: "2001:550:1b01:1::1", ASN: 0}, Linkc: 1, Links: []schema.HopLink{ - schema.HopLink{ + { HopDstIP: "2001:550:3::1ca", TTL: 2, Probes: []schema.HopProbe{ - schema.HopProbe{Flowid: 1, Rtt: []float64{36.803}}, - schema.HopProbe{Flowid: 2, Rtt: []float64{0.332}}, - schema.HopProbe{Flowid: 3, Rtt: []float64{0.329}}, - schema.HopProbe{Flowid: 4, Rtt: []float64{0.567}}, - schema.HopProbe{Flowid: 5, Rtt: []float64{0.329}}, - schema.HopProbe{Flowid: 6, Rtt: []float64{1.237}}, + {Flowid: 1, Rtt: []float64{36.803}}, + {Flowid: 2, Rtt: []float64{0.332}}, + {Flowid: 3, Rtt: []float64{0.329}}, + {Flowid: 4, Rtt: []float64{0.567}}, + {Flowid: 5, Rtt: []float64{0.329}}, + {Flowid: 6, Rtt: []float64{1.237}}, }, }, }, @@ -204,14 +204,14 @@ func TestParseFirstLine(t *testing.T) { } line = "Exception : [ERROR](Probe.cc, 109)Can't send the probe : Invalid argument" - protocol, dest_ip, server_ip, err = parser.ParseFirstLine(line) + _, _, _, err = parser.ParseFirstLine(line) if err == nil { t.Errorf("Should return error for err message on the first line!\n") return } line = "traceroute to 35.243.216.203 (35.243.216.203), 30 hops max, 30 bytes packets" - protocol, dest_ip, server_ip, err = parser.ParseFirstLine(line) + _, _, _, err = parser.ParseFirstLine(line) if err == nil { t.Errorf("Should return error for unknown first line format!\n") return @@ -268,7 +268,7 @@ func TestParseJSONL(t *testing.T) { } func TestParse(t *testing.T) { - rawData, err := ioutil.ReadFile("testdata/PT/20170320T23:53:10Z-172.17.94.34-33456-74.125.224.100-33457.paris") + rawData, _ := ioutil.ReadFile("testdata/PT/20170320T23:53:10Z-172.17.94.34-33456-74.125.224.100-33457.paris") cachedTest, err := parser.Parse(nil, "testdata/PT/20170320T23:53:10Z-172.17.94.34-33456-74.125.224.100-33457.paris", "", rawData, "pt-daily") if err != nil { t.Fatalf(err.Error()) @@ -295,11 +295,11 @@ func TestParse(t *testing.T) { }, Linkc: 0, Links: []schema.HopLink{ - schema.HopLink{ + { HopDstIP: "74.125.224.100", TTL: 0, Probes: []schema.HopProbe{ - schema.HopProbe{ + { Flowid: 0, Rtt: []float64{0.895}, }, From 142688fce9d65d11e8e5b7d169cb61a45afc71f1 Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 10:09:06 -0400 Subject: [PATCH 03/14] misc warning fixes --- parser/annotation.go | 2 +- parser/base.go | 4 ++-- parser/base_test.go | 3 ++- parser/disco_test.go | 3 ++- parser/ss.go | 6 +++--- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/parser/annotation.go b/parser/annotation.go index 86b52d8ee..31256cdda 100644 --- a/parser/annotation.go +++ b/parser/annotation.go @@ -33,7 +33,7 @@ type AnnotationParser struct { type nullAnnotator struct{} func (ann *nullAnnotator) GetAnnotations(ctx context.Context, date time.Time, ips []string, info ...string) (*v2as.Response, error) { - return &v2as.Response{AnnotatorDate: time.Now(), Annotations: make(map[string]*api.Annotations, 0)}, nil + return &v2as.Response{AnnotatorDate: time.Now(), Annotations: make(map[string]*api.Annotations)}, nil } // NewAnnotationParser creates a new parser for annotation data. diff --git a/parser/base.go b/parser/base.go index fc60a5d81..73c67cff6 100644 --- a/parser/base.go +++ b/parser/base.go @@ -21,9 +21,9 @@ import ( // Errors that may be returned by BaseRowBuffer functions. var ( - ErrAnnotationError = errors.New("Annotation error") + ErrAnnotationError = errors.New("annotation error") ErrNotAnnotatable = errors.New("object does not implement Annotatable") - ErrRowNotPointer = errors.New("Row should be a pointer type") + ErrRowNotPointer = errors.New("row should be a pointer type") ) // RowBuffer provides all basic functionality generally needed for buffering, annotating, and inserting diff --git a/parser/base_test.go b/parser/base_test.go index 4e29b9ccd..80f014691 100644 --- a/parser/base_test.go +++ b/parser/base_test.go @@ -48,7 +48,8 @@ func (row *Row) GetLogTime() time.Time { return time.Now() } -func assertTestRowAnnotatable(r *Row) { +// AssertTestRowAnnotatable isn't called anywhere, but confirms interface at compile time. +func AssertTestRowAnnotatable(r *Row) { func(row.Annotatable) {}(r) } diff --git a/parser/disco_test.go b/parser/disco_test.go index b2f5a54bc..7e7650016 100644 --- a/parser/disco_test.go +++ b/parser/disco_test.go @@ -126,7 +126,8 @@ func TestJSONParsing(t *testing.T) { // DISABLED // This tests insertion into a test table in the cloud. Should not normally be executed. -func xTestRealBackend(t *testing.T) { +func TestRealBackend(t *testing.T) { + t.Skip("Disabled") ins, err := bq.NewInserter(etl.SW, time.Now()) var parser etl.Parser = parser.NewDiscoParser(ins) diff --git a/parser/ss.go b/parser/ss.go index 205a5c147..acc729e4a 100644 --- a/parser/ss.go +++ b/parser/ss.go @@ -48,7 +48,7 @@ func ExtractLogtimeFromFilename(fileName string) (time.Time, error) { testName := filepath.Base(fileName) if len(testName) < 19 || !strings.Contains(testName, ".web100") { log.Println(testName) - return time.Time{}, errors.New("Invalid sidestream filename") + return time.Time{}, errors.New("invalid sidestream filename") } t, err := time.Parse("20060102T15:04:05.999999999Z_", testName[0:17]+".000000000Z_") @@ -64,7 +64,7 @@ func ParseKHeader(header string) ([]string, error) { var varNames []string web100Vars := strings.Split(header, " ") if web100Vars[0] != "K:" { - return varNames, errors.New("Corrupted header") + return varNames, errors.New("corrupted header") } data, err := web100.Asset("tcp-kis.txt") @@ -148,7 +148,7 @@ func ParseOneLine(snapshot string, varNames []string) (map[string]string, error) ssValue := make(map[string]string) if value[0] != "C:" || len(value) != len(varNames)+1 { log.Printf("corrupted content:") - log.Printf(snapshot) + log.Println(snapshot) return ssValue, errors.New("corrupted content") } From 416a1da3ed7d441c9eed20d7670f2c5976fd487c Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 10:15:21 -0400 Subject: [PATCH 04/14] misc warning fixes --- parser/ndt_meta_test.go | 2 +- parser/ndt_test.go | 12 +++--------- parser/tcpinfo_test.go | 3 ++- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/parser/ndt_meta_test.go b/parser/ndt_meta_test.go index 822b4b693..e26a91128 100644 --- a/parser/ndt_meta_test.go +++ b/parser/ndt_meta_test.go @@ -21,7 +21,7 @@ func TestMetaParser(t *testing.T) { meta := parser.ProcessMetaFile("ndt", "suffix", metaName, metaData) if meta == nil { - t.Error("metaFile has not been populated.") + t.Fatal("metaFile has not been populated.") } timestamp, _ := time.Parse("20060102T15:04:05.999999999Z", "20170509T13:45:13.59021Z") if meta.DateTime != timestamp { diff --git a/parser/ndt_test.go b/parser/ndt_test.go index 5702115c7..9cf6fc4bb 100644 --- a/parser/ndt_test.go +++ b/parser/ndt_test.go @@ -20,10 +20,12 @@ import ( "github.com/m-lab/etl/schema" ) +// unused, but performs compile time validation func assertNDTTestIsAnnotatable(r parser.NDTTest) { func(row.Annotatable) {}(r) } +// unused, but performs compile time validation func assertNDTTestIsValueSaver(r parser.NDTTest) { func(bigquery.ValueSaver) {}(r) } @@ -289,6 +291,7 @@ func compare(t *testing.T, actual schema.Web100ValueMap, expected schema.Web100V return match } +// assertInserter does a compile time check. func assertInserter(in etl.Inserter) { func(in etl.Inserter) {}(&inMemoryInserter{}) } @@ -307,15 +310,6 @@ func newInMemoryInserter() *inMemoryInserter { return &inMemoryInserter{data, 0, 0, token} } -// acquire and release handle the single token that protects the FlushSlice and -// access to the metrics. -func (in *inMemoryInserter) acquire() { - <-in.token -} -func (in *inMemoryInserter) release() { - in.token <- struct{}{} // return the token. -} - func (in *inMemoryInserter) Commit(data []interface{}, label string) error { return in.Put(data) } diff --git a/parser/tcpinfo_test.go b/parser/tcpinfo_test.go index 0e622bf49..15a6db6e6 100644 --- a/parser/tcpinfo_test.go +++ b/parser/tcpinfo_test.go @@ -24,6 +24,7 @@ import ( "github.com/m-lab/etl/task" ) +// unused, but performs compile time validation func assertTCPInfoParser(in *parser.TCPInfoParser) { func(p etl.Parser) {}(in) } @@ -60,7 +61,7 @@ func fileSource(fn string) (etl.TestSource, error) { type fakeAnnotator struct{} func (ann *fakeAnnotator) GetAnnotations(ctx context.Context, date time.Time, ips []string, info ...string) (*v2.Response, error) { - return &v2.Response{AnnotatorDate: time.Now(), Annotations: make(map[string]*api.Annotations, 0)}, nil + return &v2.Response{AnnotatorDate: time.Now(), Annotations: make(map[string]*api.Annotations)}, nil } type inMemorySink struct { From a2079b1f11b63f87ab1cf4b8aab5b2b3552dc662 Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 10:32:55 -0400 Subject: [PATCH 05/14] assorted warning fixes in parser and schema --- parser/ndt_test.go | 5 +++++ parser/tcpinfo_test.go | 1 + schema/ndt5_result.go | 4 ++-- schema/pt_schema.go | 22 +++++++++++----------- schema/tcpinfo.go | 4 ---- schema/tcpinfo_test.go | 39 +++------------------------------------ schema/web100.go | 9 +++------ web100/web100_test.go | 3 ++- 8 files changed, 27 insertions(+), 60 deletions(-) diff --git a/parser/ndt_test.go b/parser/ndt_test.go index 9cf6fc4bb..81c27dec4 100644 --- a/parser/ndt_test.go +++ b/parser/ndt_test.go @@ -20,6 +20,11 @@ import ( "github.com/m-lab/etl/schema" ) +// unused, but performs a compile time validation +func assertSaver(ms schema.Web100ValueMap) { + func(bigquery.ValueSaver) {}(ms) +} + // unused, but performs compile time validation func assertNDTTestIsAnnotatable(r parser.NDTTest) { func(row.Annotatable) {}(r) diff --git a/parser/tcpinfo_test.go b/parser/tcpinfo_test.go index 15a6db6e6..98e6d7191 100644 --- a/parser/tcpinfo_test.go +++ b/parser/tcpinfo_test.go @@ -29,6 +29,7 @@ func assertTCPInfoParser(in *parser.TCPInfoParser) { func(p etl.Parser) {}(in) } +// TODO - move this to storage for general use. func fileSource(fn string) (etl.TestSource, error) { if !(strings.HasSuffix(fn, ".tgz") || strings.HasSuffix(fn, ".tar") || strings.HasSuffix(fn, ".tar.gz")) { diff --git a/schema/ndt5_result.go b/schema/ndt5_result.go index 9334a717f..0ac13f953 100644 --- a/schema/ndt5_result.go +++ b/schema/ndt5_result.go @@ -17,8 +17,8 @@ import ( // Deprecated - use V1 for Gardener 2.0 type NDT5ResultRow struct { ParseInfo *ParseInfoV0 - TestID string `json:"test_id,string" bigquery:"test_id"` - LogTime int64 `json:"log_time,int64" bigquery:"log_time"` + TestID string `json:"test_id" bigquery:"test_id"` + LogTime int64 `json:"log_time" bigquery:"log_time"` Result data.NDT5Result `json:"result" bigquery:"result"` // NOT part of struct schema. Included only to provide a fake annotator interface. diff --git a/schema/pt_schema.go b/schema/pt_schema.go index a3ba5a409..e804a7254 100644 --- a/schema/pt_schema.go +++ b/schema/pt_schema.go @@ -17,23 +17,23 @@ type HopIP struct { City string `json:"city"` CountryCode string `json:"country_code"` Hostname string `json:"hostname"` - ASN uint32 `json:"asn,uint32"` + ASN uint32 `json:"asn"` } type HopProbe struct { - Flowid int64 `json:"flowid,int64"` + Flowid int64 `json:"flowid"` Rtt []float64 `json:"rtt"` } type HopLink struct { HopDstIP string `json:"hop_dst_ip"` - TTL int64 `json:"ttl,int64"` + TTL int64 `json:"ttl"` Probes []HopProbe `json:"probes"` } type ScamperHop struct { Source HopIP `json:"source"` - Linkc int64 `json:"linkc,int64"` + Linkc int64 `json:"linkc"` Links []HopLink `json:"link"` } @@ -41,16 +41,16 @@ type PTTest struct { UUID string `json:"uuid" bigquery:"uuid"` TestTime time.Time `json:"testtime"` Parseinfo ParseInfoV0 `json:"parseinfo"` - StartTime int64 `json:"start_time,int64" bigquery:"start_time"` - StopTime int64 `json:"stop_time,int64" bigquery:"stop_time"` + StartTime int64 `json:"start_time" bigquery:"start_time"` + StopTime int64 `json:"stop_time" bigquery:"stop_time"` ScamperVersion string `json:"scamper_version" bigquery:"scamper_version"` Source ServerInfo `json:"source"` Destination ClientInfo `json:"destination"` - ProbeSize int64 `json:"probe_size,int64"` - ProbeC int64 `json:"probec,int64"` + ProbeSize int64 `json:"probe_size"` + ProbeC int64 `json:"probec"` Hop []ScamperHop `json:"hop"` ExpVersion string `json:"exp_version" bigquery:"exp_version"` - CachedResult bool `json:"cached_result,bool" bigquery:"cached_result"` + CachedResult bool `json:"cached_result" bigquery:"cached_result"` } // Schema returns the Bigquery schema for PTTest. @@ -82,7 +82,7 @@ func (row *PTTest) GetClientIPs() []string { requestIPs[hop.Source.IP] = true } batchRequest := make([]string, 0, len(requestIPs)) - for key, _ := range requestIPs { + for key := range requestIPs { batchRequest = append(batchRequest, key) } return batchRequest @@ -94,7 +94,7 @@ func (row *PTTest) GetServerIP() string { } func (row *PTTest) AnnotateHops(annMap map[string]*api.Annotations) error { - for index, _ := range row.Hop { + for index := range row.Hop { ann, ok := annMap[row.Hop[index].Source.IP] if !ok { metrics.AnnotationMissingCount.WithLabelValues("No annotation for PT hop").Inc() diff --git a/schema/tcpinfo.go b/schema/tcpinfo.go index 4a288b3b0..54f357ccb 100644 --- a/schema/tcpinfo.go +++ b/schema/tcpinfo.go @@ -68,10 +68,6 @@ func (row *TCPRow) CopySocketInfo() { row.Client = &ClientInfo{IP: row.SockID.DstIP, Port: row.SockID.DPort} } -func assertTCPRowIsValueSaver(r *TCPRow) { - func(bigquery.ValueSaver) {}(r) -} - func init() { var err error tcpSchema, err = (&TCPRow{}).Schema() diff --git a/schema/tcpinfo_test.go b/schema/tcpinfo_test.go index 06a62e57a..9ced89d2f 100644 --- a/schema/tcpinfo_test.go +++ b/schema/tcpinfo_test.go @@ -1,54 +1,21 @@ package schema_test import ( - "archive/tar" - "compress/gzip" - "errors" - "io" - "os" "reflect" - "strings" "testing" - "time" "cloud.google.com/go/bigquery" "github.com/m-lab/tcp-info/inetdiag" "github.com/davecgh/go-spew/spew" - "github.com/m-lab/etl/etl" "github.com/m-lab/etl/schema" - "github.com/m-lab/etl/storage" "github.com/m-lab/tcp-info/snapshot" ) -// TODO - move this to storage for general use. -func fileSource(fn string) (etl.TestSource, error) { - if !(strings.HasSuffix(fn, ".tgz") || strings.HasSuffix(fn, ".tar") || - strings.HasSuffix(fn, ".tar.gz")) { - return nil, errors.New("not tar or tgz: " + fn) - } - - var rdr io.ReadCloser - var raw io.ReadCloser - raw, err := os.Open(fn) - if err != nil { - return nil, err - } - // Handle .tar.gz, .tgz files. - if strings.HasSuffix(strings.ToLower(fn), "gz") { - rdr, err = gzip.NewReader(raw) - if err != nil { - raw.Close() - return nil, err - } - } else { - rdr = raw - } - tarReader := tar.NewReader(rdr) - - timeout := 16 * time.Millisecond - return &storage.GCSSource{TarReader: tarReader, Closer: raw, RetryBaseTime: timeout, TableBase: "test"}, nil +// unused, but performs compile time validation +func assertTCPRowIsValueSaver(r *schema.TCPRow) { + func(bigquery.ValueSaver) {}(r) } func TestBQSaver(t *testing.T) { diff --git a/schema/web100.go b/schema/web100.go index c43083054..3f9d2eef2 100644 --- a/schema/web100.go +++ b/schema/web100.go @@ -19,10 +19,6 @@ func (s Web100ValueMap) Save() (row map[string]bigquery.Value, insertID string, return s, "", nil } -func assertSaver(ms Web100ValueMap) { - func(bigquery.ValueSaver) {}(ms) -} - // Get returns the contained map, or nil if it doesn't exist. // This works for either Web100ValueMap or map[string]bigquery.Value func (vm Web100ValueMap) Get(name string) Web100ValueMap { @@ -30,10 +26,11 @@ func (vm Web100ValueMap) Get(name string) Web100ValueMap { if !ok { return nil } - switch wl.(type) { + switch typed_wl := wl.(type) { case map[string]bigquery.Value: - return Web100ValueMap(wl.(map[string]bigquery.Value)) + return Web100ValueMap(typed_wl) // ok to cast - same underlying type default: + // Could this cause a runtime exception? return wl.(Web100ValueMap) } } diff --git a/web100/web100_test.go b/web100/web100_test.go index fad49f55a..a612b13d0 100644 --- a/web100/web100_test.go +++ b/web100/web100_test.go @@ -9,8 +9,9 @@ import ( "reflect" "testing" - "github.com/m-lab/etl/web100" pipe "gopkg.in/m-lab/pipe.v3" + + "github.com/m-lab/etl/web100" ) func init() { From b4622619b3695ff4cf49051cefb81e1b73b33e40 Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 10:39:32 -0400 Subject: [PATCH 06/14] fix warnings in row package --- row/row.go | 6 +++--- row/row_test.go | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/row/row.go b/row/row.go index 47db8af66..b01bcf159 100644 --- a/row/row.go +++ b/row/row.go @@ -22,10 +22,10 @@ import ( // Errors that may be returned by Buffer functions. var ( - ErrAnnotationError = errors.New("Annotation error") + ErrAnnotationError = errors.New("annotation error") ErrNotAnnotatable = errors.New("object does not implement Annotatable") - ErrBufferFull = errors.New("Buffer full") - ErrInvalidSink = errors.New("Not a valid row.Sink") + ErrBufferFull = errors.New("buffer full") + ErrInvalidSink = errors.New("not a valid row.Sink") ) // Annotatable interface enables integration of annotation into parser.Base. diff --git a/row/row_test.go b/row/row_test.go index e9ffbea94..da8acea45 100644 --- a/row/row_test.go +++ b/row/row_test.go @@ -14,6 +14,20 @@ import ( v2as "github.com/m-lab/annotation-service/api/v2" ) +// unused, but performs compile time validation +func assertTestRowAnnotatable(r *Row) { + func(row.Annotatable) {}(r) +} + +// unused, but performs compile time validation +func assertSink(in row.Sink) { + func(in row.Sink) {}(&inMemorySink{}) +} + +func assertBQInserterIsSink(in row.Sink) { + func(in row.Sink) {}(&bq.BQInserter{}) +} + // Implement parser.Annotatable type Row struct { @@ -23,8 +37,6 @@ type Row struct { serverAnn *api.Annotations } -type BadRow struct{} - func (row *Row) GetClientIPs() []string { return []string{row.client} } @@ -47,14 +59,6 @@ func (row *Row) GetLogTime() time.Time { return time.Now() } -func assertTestRowAnnotatable(r *Row) { - func(row.Annotatable) {}(r) -} - -func assertSink(in row.Sink) { - func(in row.Sink) {}(&inMemorySink{}) -} - type inMemorySink struct { data []interface{} committed int @@ -75,7 +79,7 @@ func (in *inMemorySink) Commit(data []interface{}, label string) (int, error) { func (in *inMemorySink) Close() error { return nil } func TestBase(t *testing.T) { - ins := &inMemorySink{} + ins := newInMemorySink() // Set up fake annotation service r1 := `{"AnnotatorDate":"2018-12-05T00:00:00Z", @@ -129,7 +133,7 @@ func TestBase(t *testing.T) { } func TestAsyncPut(t *testing.T) { - ins := &inMemorySink{} + ins := newInMemorySink() // Set up fake annotation service r1 := `{"AnnotatorDate":"2018-12-05T00:00:00Z", @@ -181,7 +185,3 @@ func TestAsyncPut(t *testing.T) { t.Error("Failed server annotation") } } - -func assertBQInserterIsSink(in row.Sink) { - func(in row.Sink) {}(&bq.BQInserter{}) -} From 7933c64acbe37364a840e4e92bd60335bd8769e9 Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 10:44:32 -0400 Subject: [PATCH 07/14] fix warnings in fake pkg --- fake/fold.go | 5 +---- fake/uploader.go | 19 ------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/fake/fold.go b/fake/fold.go index 144e2b12f..9201d78a0 100644 --- a/fake/fold.go +++ b/fake/fold.go @@ -100,10 +100,7 @@ func equalFoldRight(s, t []byte) bool { t = t[size:] } - if len(t) > 0 { - return false - } - return true + return len(t) >= 0 } // asciiEqualFold is a specialization of bytes.EqualFold for use when diff --git a/fake/uploader.go b/fake/uploader.go index 7a176f59f..8056f3548 100644 --- a/fake/uploader.go +++ b/fake/uploader.go @@ -25,9 +25,6 @@ import ( // Stuff from params.go //--------------------------------------------------------------------------------------- var ( - // See https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#timestamp-type. - timestampFormat = "2006-01-02 15:04:05.999999-07:00" - // See https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#schema.fields.name validFieldName = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]{0,127}$") ) @@ -66,21 +63,6 @@ var ( var typeOfByteSlice = reflect.TypeOf([]byte{}) -var schemaCache Cache - -type cacheVal struct { - schema bigquery.Schema - err error -} - -func inferSchemaReflectCached(t reflect.Type) (bigquery.Schema, error) { - cv := schemaCache.Get(t, func() interface{} { - s, err := inferSchemaReflect(t) - return cacheVal{s, err} - }).(cacheVal) - return cv.schema, cv.err -} - func inferSchemaReflect(t reflect.Type) (bigquery.Schema, error) { rec, err := hasRecursiveType(t, nil) if err != nil { @@ -241,7 +223,6 @@ func hasRecursiveType(t reflect.Type, seen *typeList) (bool, error) { // FakeUploader is a fake for Uploader, for use in debugging, and tests. // See bigquery.Uploader for field info. type FakeUploader struct { - t *bigquery.Table SkipInvalidRows bool IgnoreUnknownValues bool TableTemplateSuffix string From 9349a4962be65659e21636f980928369a810ea6a Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 10:45:12 -0400 Subject: [PATCH 08/14] fix warning in task_test.go --- task/task_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/task/task_test.go b/task/task_test.go index 7e4acbbc2..d59d84942 100644 --- a/task/task_test.go +++ b/task/task_test.go @@ -58,7 +58,7 @@ func MakeTestSource(t *testing.T) etl.TestSource { hdr = tar.Header{Name: "bar", Mode: 0666, Typeflag: tar.TypeReg, Size: int64(11)} tw.WriteHeader(&hdr) - _, err = tw.Write([]byte("butter milk")) + tw.Write([]byte("butter milk")) if err = tw.Close(); err != nil { t.Fatal(err) } @@ -144,7 +144,7 @@ func TestTarFileInput(t *testing.T) { } // Here we expect an oversize file error, with filename = big_file. - fn, bb, err = tt.NextTest(100) + fn, _, err = tt.NextTest(100) if fn != "big_file" { t.Error("Expected big_file: " + fn) } From 1a74a69758f4551b053fc78ae9a2e05f9940d483 Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 10:48:31 -0400 Subject: [PATCH 09/14] fix etl pkg warnings --- etl/globals.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/etl/globals.go b/etl/globals.go index 1f53d2e4a..fb67dd8a2 100644 --- a/etl/globals.go +++ b/etl/globals.go @@ -83,9 +83,6 @@ var ( expNNNNE + // 4,5,6 suffix + `$`) // 7 - dateTimePattern = regexp.MustCompile(dateTime) - sitePattern = regexp.MustCompile(type2 + mlabNSiteNN) - justSitePattern = regexp.MustCompile(`.*` + mlabNSiteNN + `.*`) ) @@ -114,16 +111,16 @@ type DataPath struct { func ValidateTestPath(path string) (DataPath, error) { basic := basicTaskPattern.FindStringSubmatch(path) if basic == nil { - return DataPath{}, errors.New("Path missing date-time string") + return DataPath{}, errors.New("path missing date-time string") } preamble := startPattern.FindStringSubmatch(basic[1]) if preamble == nil { - return DataPath{}, errors.New("Invalid preamble: " + fmt.Sprint(basic)) + return DataPath{}, errors.New("invalid preamble: " + fmt.Sprint(basic)) } post := endPattern.FindStringSubmatch(basic[5]) if post == nil { - return DataPath{}, errors.New("Invalid postamble: " + basic[5]) + return DataPath{}, errors.New("invalid postamble: " + basic[5]) } dp := DataPath{ URI: path, From 9de8705135a74a69ae4d6f9e49fed70d3b5fd677 Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 10:53:23 -0400 Subject: [PATCH 10/14] fix active pkg warnings --- active/active.go | 2 +- active/poller_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/active/active.go b/active/active.go index 67d783b3a..3fb2e3404 100644 --- a/active/active.go +++ b/active/active.go @@ -109,7 +109,7 @@ func NewGCSSource(ctx context.Context, label string, fl FileLister, toRunnable f fileLister: fl, toRunnable: toRunnable, - pendingChan: make(chan Runnable, 0), + pendingChan: make(chan Runnable), label: label, } diff --git a/active/poller_test.go b/active/poller_test.go index 236220a35..526dd1254 100644 --- a/active/poller_test.go +++ b/active/poller_test.go @@ -35,7 +35,7 @@ func (g *fakeGardener) ServeHTTP(w http.ResponseWriter, r *http.Request) { log.Fatal("Should be POST") // Not t.Fatal because this is asynchronous. } g.lock.Lock() - g.lock.Unlock() + defer g.lock.Unlock() switch r.URL.Path { case "/job": if len(g.jobs) < 1 { From 123a0189221e119966e2991c5e18a2087153ffa1 Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 12:55:47 -0400 Subject: [PATCH 11/14] fix storage pkg warnings --- storage/rowwriter.go | 2 +- storage/rowwriter_test.go | 2 +- storage/storage.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/rowwriter.go b/storage/rowwriter.go index 9cc286006..d3951c072 100644 --- a/storage/rowwriter.go +++ b/storage/rowwriter.go @@ -181,7 +181,7 @@ type SinkFactory struct { func pathAndFilename(uri string) (string, error) { parts := strings.SplitN(uri, "/", 4) if len(parts) != 4 || parts[0] != "gs:" || len(parts[3]) == 0 { - return "", errors.New("Bad GCS path") + return "", errors.New("bad GCS path") } return parts[3], nil } diff --git a/storage/rowwriter_test.go b/storage/rowwriter_test.go index 63bf1c209..9dd03d00c 100644 --- a/storage/rowwriter_test.go +++ b/storage/rowwriter_test.go @@ -25,7 +25,7 @@ func TestRowWriter(t *testing.T) { defer server.Stop() bucket := "fake-bucket" - server.CreateBucket(bucket) + server.CreateBucketWithOpts(fgs.CreateBucketOpts{Name: bucket}) c := server.Client() file := "foobar-file" diff --git a/storage/storage.go b/storage/storage.go index 0f449754e..d5ffbf91e 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -31,7 +31,7 @@ import ( ) // ErrOversizeFile is returned when exceptionally large files are skipped. -var ErrOversizeFile = errors.New("Oversize file") +var ErrOversizeFile = errors.New("oversize file") // TarReader provides Next and Read functions. type TarReader interface { From 661b1b8a9680921e1a22531a076fdb5e5ed180fb Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 12:56:00 -0400 Subject: [PATCH 12/14] fix cmd and metrics warnings --- cmd/etl_worker/etl_worker.go | 40 ++++++++++++++++---------------- cmd/generate_schema_docs/main.go | 2 +- cmd/update-schema/update.go | 6 ----- metrics/metrics_test.go | 2 -- 4 files changed, 21 insertions(+), 29 deletions(-) diff --git a/cmd/etl_worker/etl_worker.go b/cmd/etl_worker/etl_worker.go index a41a0dc68..15ab8c197 100644 --- a/cmd/etl_worker/etl_worker.go +++ b/cmd/etl_worker/etl_worker.go @@ -215,7 +215,7 @@ func handleRequest(rwr http.ResponseWriter, rq *http.Request) { rawFileName := rq.FormValue("filename") status, msg := subworker(rawFileName, executionCount, retryCount, age) rwr.WriteHeader(status) - fmt.Fprintf(rwr, msg) + fmt.Fprint(rwr, msg) } func subworker(rawFileName string, executionCount, retryCount int, age time.Duration) (status int, msg string) { @@ -334,25 +334,25 @@ func startServers(ctx context.Context, mux http.Handler) *errgroup.Group { // This publishes the service port for use in unit tests. mainServerAddr <- server.Addr - select { - case <-ctx.Done(): - // This currently only executes when the context is cancelled - // by unit tests. It does not yet execute in production. - log.Println("Shutting down servers") - ctx, cancel := context.WithTimeout(context.Background(), *shutdownTimeout) - defer cancel() - start := time.Now() - eg := errgroup.Group{} - eg.Go(func() error { - return server.Shutdown(ctx) - }) - eg.Go(func() error { - return promServer.Shutdown(ctx) - }) - eg.Wait() - log.Println("Shutdown took", time.Since(start)) - return &eg - } + // Wait for shutdown + <-ctx.Done() + + // This currently only executes when the context is cancelled + // by unit tests. It does not yet execute in production. + log.Println("Shutting down servers") + ctx, cancel := context.WithTimeout(context.Background(), *shutdownTimeout) + defer cancel() + start := time.Now() + eg := errgroup.Group{} + eg.Go(func() error { + return server.Shutdown(ctx) + }) + eg.Go(func() error { + return promServer.Shutdown(ctx) + }) + eg.Wait() + log.Println("Shutdown took", time.Since(start)) + return &eg } func main() { diff --git a/cmd/generate_schema_docs/main.go b/cmd/generate_schema_docs/main.go index 050cec99e..c765f86e4 100644 --- a/cmd/generate_schema_docs/main.go +++ b/cmd/generate_schema_docs/main.go @@ -60,7 +60,7 @@ func init() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s\n", os.Args[0]) - fmt.Fprintf(os.Stderr, usage) + fmt.Fprint(os.Stderr, usage) fmt.Fprintln(os.Stderr, "Flags:") flag.PrintDefaults() } diff --git a/cmd/update-schema/update.go b/cmd/update-schema/update.go index 25cb5ba91..40103ded6 100644 --- a/cmd/update-schema/update.go +++ b/cmd/update-schema/update.go @@ -17,7 +17,6 @@ import ( "time" "cloud.google.com/go/bigquery" - "google.golang.org/api/googleapi" "github.com/m-lab/go/cloud/bqx" "github.com/m-lab/go/flagx" @@ -109,11 +108,6 @@ func CreateOrUpdate(schema bigquery.Schema, project, dataset, table, partField s log.Println("UpdateTable failed:", err) // TODO add specific error handling for incompatible schema change - apiErr, ok := err.(*googleapi.Error) - if !ok || apiErr.Code != 404 { - // TODO - different behavior on specific error types? - } - partitioning := &bigquery.TimePartitioning{ Field: partField, } diff --git a/metrics/metrics_test.go b/metrics/metrics_test.go index 9d3ee094e..7fea68717 100644 --- a/metrics/metrics_test.go +++ b/metrics/metrics_test.go @@ -55,8 +55,6 @@ func rePanic() { }() a := []int{1, 2, 3} log.Println(a[4]) - // This is never reached. - return } func TestCountPanics(t *testing.T) { From 595dee55d4605c0953e1d3f7d8c0bb930d415fab Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 15:44:16 -0400 Subject: [PATCH 13/14] Add linter pragma to ignore assert funcs --- bq/bq_test.go | 7 +++++++ bq/insert.go | 4 ---- cmd/generate_schema_docs/main.go | 18 ------------------ parser/base_test.go | 4 ++-- parser/ndt_test.go | 8 ++++---- parser/tcpinfo_test.go | 2 +- row/row_test.go | 5 +++-- schema/schema_test.go | 1 + schema/tcpinfo_test.go | 2 +- site/site_test.go | 8 -------- storage/rowwriter.go | 12 +++++++----- 11 files changed, 26 insertions(+), 45 deletions(-) diff --git a/bq/bq_test.go b/bq/bq_test.go index 02228d298..88240cbe9 100644 --- a/bq/bq_test.go +++ b/bq/bq_test.go @@ -24,14 +24,21 @@ func init() { log.SetFlags(log.LstdFlags | log.Lshortfile) } +//lint:ignore U1000 compile time assertions func assertInserter(in etl.Inserter) { func(in etl.Inserter) {}(&bq.BQInserter{}) } +//lint:ignore U1000 compile time assertions func assertSinkFactory(f factory.SinkFactory) { func(f factory.SinkFactory) {}(bq.NewSinkFactory()) } +//lint:ignore U1000 compile time assertions +func assertSaver(ms bq.MapSaver) { + func(bigquery.ValueSaver) {}(ms) +} + func TestSinkFactory(t *testing.T) { f := bq.NewSinkFactory() s, err := f.Get(context.Background(), etl.DataPath{}) diff --git a/bq/insert.go b/bq/insert.go index 9334785cb..e4a043eca 100644 --- a/bq/insert.go +++ b/bq/insert.go @@ -164,10 +164,6 @@ func (s MapSaver) Save() (row map[string]bigquery.Value, insertID string, err er return s, "", nil } -func assertSaver(ms MapSaver) { - func(bigquery.ValueSaver) {}(ms) -} - //---------------------------------------------------------------------------- // BQInserter provides an API for inserting rows into a specific BQ Table. diff --git a/cmd/generate_schema_docs/main.go b/cmd/generate_schema_docs/main.go index c765f86e4..6ba7c594c 100644 --- a/cmd/generate_schema_docs/main.go +++ b/cmd/generate_schema_docs/main.go @@ -114,24 +114,6 @@ func generateRichMarkdown(s bigquery.Schema, t schemaGenerator) []byte { return buf.Bytes() } -// TODO: remove this function if it turns out to be replaced by generateRichMarkdown. -func generateMarkdown(schema bigquery.Schema) []byte { - buf := &bytes.Buffer{} - fmt.Fprintln(buf, "| Field name | Type | Description |") - fmt.Fprintln(buf, "| :----------------|:----------:|:---------------|") - bqx.WalkSchema(schema, func(prefix []string, field *bigquery.FieldSchema) error { - var path string - if len(prefix) == 1 { - path = "" - } else { - path = strings.Join(prefix[:len(prefix)-1], ".") + "." - } - fmt.Fprintf(buf, "| %s**%s** | %s | %s |\n", path, prefix[len(prefix)-1], field.Type, field.Description) - return nil - }) - return buf.Bytes() -} - // All record structs define a Schema method. This interface allows us to // process each of them easily. type schemaGenerator interface { diff --git a/parser/base_test.go b/parser/base_test.go index 80f014691..ea9c640d0 100644 --- a/parser/base_test.go +++ b/parser/base_test.go @@ -48,8 +48,8 @@ func (row *Row) GetLogTime() time.Time { return time.Now() } -// AssertTestRowAnnotatable isn't called anywhere, but confirms interface at compile time. -func AssertTestRowAnnotatable(r *Row) { +//lint:ignore U1000 compile time assertions +func assertTestRowAnnotatable(r *Row) { func(row.Annotatable) {}(r) } diff --git a/parser/ndt_test.go b/parser/ndt_test.go index 81c27dec4..8c38e2e8d 100644 --- a/parser/ndt_test.go +++ b/parser/ndt_test.go @@ -20,17 +20,17 @@ import ( "github.com/m-lab/etl/schema" ) -// unused, but performs a compile time validation +//lint:ignore U1000 compile time assertions func assertSaver(ms schema.Web100ValueMap) { func(bigquery.ValueSaver) {}(ms) } -// unused, but performs compile time validation +//lint:ignore U1000 compile time assertions func assertNDTTestIsAnnotatable(r parser.NDTTest) { func(row.Annotatable) {}(r) } -// unused, but performs compile time validation +//lint:ignore U1000 compile time assertions func assertNDTTestIsValueSaver(r parser.NDTTest) { func(bigquery.ValueSaver) {}(r) } @@ -296,7 +296,7 @@ func compare(t *testing.T, actual schema.Web100ValueMap, expected schema.Web100V return match } -// assertInserter does a compile time check. +//lint:ignore U1000 compile time assertions func assertInserter(in etl.Inserter) { func(in etl.Inserter) {}(&inMemoryInserter{}) } diff --git a/parser/tcpinfo_test.go b/parser/tcpinfo_test.go index 98e6d7191..519233fbe 100644 --- a/parser/tcpinfo_test.go +++ b/parser/tcpinfo_test.go @@ -24,7 +24,7 @@ import ( "github.com/m-lab/etl/task" ) -// unused, but performs compile time validation +//lint:ignore U1000 compile time assertions func assertTCPInfoParser(in *parser.TCPInfoParser) { func(p etl.Parser) {}(in) } diff --git a/row/row_test.go b/row/row_test.go index da8acea45..70415c26f 100644 --- a/row/row_test.go +++ b/row/row_test.go @@ -14,16 +14,17 @@ import ( v2as "github.com/m-lab/annotation-service/api/v2" ) -// unused, but performs compile time validation +//lint:ignore U1000 compile time assertions func assertTestRowAnnotatable(r *Row) { func(row.Annotatable) {}(r) } -// unused, but performs compile time validation +//lint:ignore U1000 compile time assertions func assertSink(in row.Sink) { func(in row.Sink) {}(&inMemorySink{}) } +//lint:ignore U1000 compile time assertions func assertBQInserterIsSink(in row.Sink) { func(in row.Sink) {}(&bq.BQInserter{}) } diff --git a/schema/schema_test.go b/schema/schema_test.go index db2520d91..91ee92ed5 100644 --- a/schema/schema_test.go +++ b/schema/schema_test.go @@ -14,6 +14,7 @@ import ( "github.com/m-lab/etl/schema" ) +//lint:ignore U1000 compile time assertions func assertAnnotatable(r *schema.SS) { func(row.Annotatable) {}(r) } diff --git a/schema/tcpinfo_test.go b/schema/tcpinfo_test.go index 9ced89d2f..c32004a85 100644 --- a/schema/tcpinfo_test.go +++ b/schema/tcpinfo_test.go @@ -13,7 +13,7 @@ import ( "github.com/m-lab/tcp-info/snapshot" ) -// unused, but performs compile time validation +//lint:ignore U1000 compile time assertions func assertTCPRowIsValueSaver(r *schema.TCPRow) { func(bigquery.ValueSaver) {}(r) } diff --git a/site/site_test.go b/site/site_test.go index a33ae937c..eb67d6ade 100644 --- a/site/site_test.go +++ b/site/site_test.go @@ -17,14 +17,6 @@ import ( "github.com/m-lab/uuid-annotator/annotator" ) -type badProvider struct { - err error -} - -func (b badProvider) Get(_ context.Context) ([]byte, error) { - return nil, b.err -} - var ( localRawfile content.Provider corruptFile content.Provider diff --git a/storage/rowwriter.go b/storage/rowwriter.go index d3951c072..a3730ffa9 100644 --- a/storage/rowwriter.go +++ b/storage/rowwriter.go @@ -25,6 +25,9 @@ import ( type RowWriter struct { w stiface.Writer o stiface.ObjectHandle + + // this attribute struct can be used to accumulate attributes that + // will be added to the final file on close. a gcs.ObjectAttrsToUpdate rows int @@ -156,16 +159,15 @@ func (rw *RowWriter) Close() error { return err } - oa := gcs.ObjectAttrsToUpdate{} - oa.Metadata = make(map[string]string, 1) - oa.Metadata["rows"] = fmt.Sprint(rw.rows) + rw.a.Metadata = make(map[string]string, 1) + rw.a.Metadata["rows"] = fmt.Sprint(rw.rows) if rw.writeErr != nil { - oa.Metadata["writeError"] = rw.writeErr.Error() + rw.a.Metadata["writeError"] = rw.writeErr.Error() } ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() - attr, err := rw.o.Update(ctx, oa) + attr, err := rw.o.Update(ctx, rw.a) log.Println(attr, err) return err From a279ed754a973c4de5393fc0d9cf67cbb56c7e3c Mon Sep 17 00:00:00 2001 From: Gregory Russell Date: Mon, 19 Apr 2021 15:47:27 -0400 Subject: [PATCH 14/14] lint directive for linefeed --- web100/parse_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/web100/parse_test.go b/web100/parse_test.go index e3836f401..0fcbfdc29 100644 --- a/web100/parse_test.go +++ b/web100/parse_test.go @@ -11,6 +11,7 @@ import ( // shortTcpKisTxt is a snippet from the tcp-kis.txt file. It includes variables with // two legacy names, a single legacy name, and no legacy name. +//lint:ignore ST1018 linefeed is intentional for legibility const shortTcpKisTxt = ` ------------------------------------------------------------------------------ VariableName: StartTimeStamp