diff --git a/network/wsPeer_test.go b/network/wsPeer_test.go index 4e031c7d52..ceb2121aa4 100644 --- a/network/wsPeer_test.go +++ b/network/wsPeer_test.go @@ -259,11 +259,14 @@ func getProtocolTags(t *testing.T) []string { // look for const declarations in protocol/tags.go var declaredTags []string + // Iterate through the declarations in the file for _, d := range f.Decls { genDecl, ok := d.(*ast.GenDecl) + // Check if the declaration is a constant and if not, continue if !ok || genDecl.Tok != token.CONST { continue } + // Iterate through the specs (specifications) in the declaration for _, spec := range genDecl.Specs { if valueSpec, ok := spec.(*ast.ValueSpec); ok { for _, n := range valueSpec.Names { diff --git a/protocol/hash_test.go b/protocol/hash_test.go new file mode 100644 index 0000000000..e490987c1c --- /dev/null +++ b/protocol/hash_test.go @@ -0,0 +1,41 @@ +// Copyright (C) 2019-2023 Algorand, Inc. +// This file is part of go-algorand +// +// go-algorand is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// go-algorand is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with go-algorand. If not, see . + +package protocol + +import ( + "strings" + "testing" + + "github.com/algorand/go-algorand/test/partitiontest" + "github.com/stretchr/testify/assert" +) + +// TestHashIDPrefix checks if any HashID const declared in hash.go is a prefix of another. +func TestHashIDPrefix(t *testing.T) { + t.Parallel() + partitiontest.PartitionTest(t) + + values := getConstValues(t, "hash.go", "HashID") + for i, v1 := range values { + for j, v2 := range values { + if i == j { + continue + } + assert.False(t, strings.HasPrefix(v1, v2), "HashID %s is a prefix of %s", v2, v1) + } + } +} diff --git a/protocol/tags_test.go b/protocol/tags_test.go index d6789373ab..087e32a82d 100644 --- a/protocol/tags_test.go +++ b/protocol/tags_test.go @@ -27,48 +27,69 @@ import ( "github.com/stretchr/testify/require" ) -// TestTagList checks that the TagList global variable contains -// all the constant Tag variables declared in tags.go. -func TestTagList(t *testing.T) { - t.Parallel() - partitiontest.PartitionTest(t) - +// getConstValues uses the AST to get a list of the values of declared const +// variables of the provided typeName in a specified fileName. +func getConstValues(t *testing.T, fileName string, typeName string) []string { fset := token.NewFileSet() - f, err := parser.ParseFile(fset, "tags.go", nil, 0) + f, err := parser.ParseFile(fset, fileName, nil, 0) require.NoError(t, err) - var constTags []Tag + var ret []string + + // Iterate through the declarations in the file for _, d := range f.Decls { gen, ok := d.(*ast.GenDecl) + // Check if the declaration is a constant if !ok || gen.Tok != token.CONST { continue } - + // Iterate through the specifications in the declaration for _, spec := range gen.Specs { + // Check if the spec is a value spec v, ok := spec.(*ast.ValueSpec) if !ok { continue } + // Check if the typeName specified is being declared + if v.Type == nil || v.Type.(*ast.Ident).Name != typeName { + continue + } + // Iterate through the expressions in the value spec for _, expr := range v.Values { val, ok := expr.(*ast.BasicLit) + // Check if the expression is a basic literal and if not, continue if !ok { continue } + // Unquote the value of the basic literal to remove the quotes tagVal, err := strconv.Unquote(val.Value) require.NoError(t, err) - constTags = append(constTags, Tag(tagVal)) + ret = append(ret, tagVal) } } } + return ret +} + +// TestTagList checks that the TagList global variable contains +// all the constant Tag variables declared in tags.go. +func TestTagList(t *testing.T) { + t.Parallel() + partitiontest.PartitionTest(t) + + constTags := getConstValues(t, "tags.go", "Tag") + + // Verify that TagList is not empty and has the same length as constTags require.NotEmpty(t, TagList) require.Len(t, TagList, len(constTags), "TagList is not complete") tagListMap := make(map[Tag]bool) for _, tag := range TagList { tagListMap[tag] = true } + // Iterate through constTags and check that each element exists in tagListMap for _, constTag := range constTags { - if tagListMap[constTag] { - delete(tagListMap, constTag) // check off as seen + if tagListMap[Tag(constTag)] { + delete(tagListMap, Tag(constTag)) // check off as seen } else { require.Fail(t, "const Tag %s is not in TagList", constTag) }