diff --git a/authorizer/dns.go b/authorizer/dns.go index 483c882cbfd22990d26130ca47abac021e002541..d7c3ded08014b3ca0647ce556190f0c342c667a9 100644 --- a/authorizer/dns.go +++ b/authorizer/dns.go @@ -16,17 +16,19 @@ const ( // DomainName is the registered domain to be used for calculation of // unique Gateway DNS addresses by authorizer, gateway, and client. DomainName = "xxnode.io" + // Maximum length of DNS name. Determined by third party service. maxLength = 64 + // Maximum number of characters of gateway ID to use. Subtract length of // domain plus the additional period from maxLength. maxGwIdLength = maxLength - len(DomainName) - 1 ) -// GetGatewayDns returns the DNS name for the given marshalled GwId. -// Truncates -func GetGatewayDns(gwId []byte) string { - encoded := hex.EncodeToString(gwId) +// GetGatewayDns returns the DNS name for the given marshalled gateway ID. +// Strips the domain name, if it exists, from the encoded ID. +func GetGatewayDns(gwID []byte) string { + encoded := hex.EncodeToString(gwID) if len(encoded) > maxGwIdLength { encoded = encoded[:maxGwIdLength] } diff --git a/authorizer/dns_test.go b/authorizer/dns_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e763f9c48e0037b15fa69a6bd52b7f03878c3212 --- /dev/null +++ b/authorizer/dns_test.go @@ -0,0 +1,57 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +package authorizer + +import ( + "math/rand" + "testing" +) + +// Consistency test of GetGatewayDns. +func TestGetGatewayDns(t *testing.T) { + prng := rand.New(rand.NewSource(389257)) + + expectedDnsNames := []string{ + "883968c2360cb4.xxnode.io", + "72a1a31943d4282c700b614ab911769b316e064bf001081d3484aa.xxnode.io", + "3f346ab53235279738c9355b97adde74f8703b7f8a55f100617ad0.xxnode.io", + "df75c745cd8f0e3226cb8b48368a7eefac708b63da8b793e747d6e.xxnode.io", + "de5e5e0ddfaa873b04d1a6e38d8b000edb.xxnode.io", + "ebfb75cd082cacc0a24106ff35f818d5e1355a9cf2c57541c8515f.xxnode.io", + "265d6ed02d478816e9455572a0a292d8240d1bdb4db854e508cdef.xxnode.io", + "847d2b5077f2afb1cb519e0297cc8b66d287f29020d68d312853e7.xxnode.io", + "19441cb0394816046e7d76cd410dd75944255f79a37f0677a7b125.xxnode.io", + "b09d84ed9bf54d0e8831e6c11def92bceb25eb3bd4166106ea23de.xxnode.io", + "d81e9c84aa04d9fb848ec5de6333a0b4818735e5f7604b60b848f2.xxnode.io", + "abed7c32d04c12100092856e2f524ed5cb9f2764ece34f1c15f512.xxnode.io", + "936acb388ff7ab670ab83c68bf0fbb6e6abc4121edff348a11ea56.xxnode.io", + "082de3dea0097c7bec94e0f91990a2f1b4f17a973873bd6819c076.xxnode.io", + "5515a6895c3c129fdb7d36925fb164c882d378cd92d672424bec5c.xxnode.io", + "541d092e3000108fbf5f24cdde601c30a04d9014bc070ae5f2c26f.xxnode.io", + "5d244632decacbc4f08d2da5fae3a8f2854865d6e1f0380cd5ae2e.xxnode.io", + "1d2e6ff5023016518c59b7d0b71b77924033fb624cd22a97b2d97c.xxnode.io", + "57a8402f3ac28f1a0901c2d23819356ec6c0c9b38b52484e5e2327.xxnode.io", + "3ece16fbf31224624fd657df55bb9f363048dcbaffa379df2ecd03.xxnode.io", + "2649315e.xxnode.io", + "39f0119b3114b56dd810183063fe1bc92157efb046e5bde0b98673.xxnode.io", + "777e17f50624354acf1cb6527f9dc3e1bc87d2e8162424ddb5d5fa.xxnode.io", + "b95e85de4ea45f6a9e4dacf16a58686d9632764da4043715f51254.xxnode.io", + "43a01ed5093752390e7c4cf17a222d2ee321f38889516c6970ed8a.xxnode.io", + } + + for i, expected := range expectedDnsNames { + gwID := make([]byte, prng.Intn(maxGwIdLength*2)) + prng.Read(gwID) + dnsName := GetGatewayDns(gwID) + + if expected != dnsName { + t.Errorf("Unexpected DNS name for gateway ID %X (%d)."+ + "\nexpected: %q\nreceived: %q", gwID, i, expected, dnsName) + } + } +} diff --git a/current/activity.go b/current/activity.go index 67e620ff79756ad19ba3e2b21a8701932e12b75e..dbeaf23c77dfe99b9a2d22349e1fe77409142ebf 100644 --- a/current/activity.go +++ b/current/activity.go @@ -9,17 +9,19 @@ package current import ( "fmt" + "github.com/pkg/errors" + "gitlab.com/elixxir/primitives/states" ) -//this holds the enum for the activity of the server. It is in primitives so -//other repos such as registration/permissioning can access it +// This holds the enum for the activity of the server. It is in primitives so +// that other repos such as registration/permissioning can access it. -// type which holds activities so they have have an associated stringer +// Activity describes the activity a server has be doing. type Activity uint32 -// List of Activities server can be in +// List of Activities. const ( NOT_STARTED = Activity(iota) WAITING @@ -29,11 +31,11 @@ const ( COMPLETED ERROR CRASH + NUM_STATES ) -const NUM_STATES = CRASH + 1 - -// Stringer to get the name of the activity, primarily for for error prints +// String returns the string representation of the Activity. This functions +// adheres to the fmt.Stringer interface. func (a Activity) String() string { switch a { case NOT_STARTED: @@ -57,7 +59,8 @@ func (a Activity) String() string { } } -// Converts an Activity to a valid Round state, or returns an error if invalid +// ConvertToRoundState converts an Activity to a valid round state or returns an +// error if it is invalid. func (a Activity) ConvertToRoundState() (states.Round, error) { switch a { case WAITING: diff --git a/current/activity_test.go b/current/activity_test.go index 55f3dac253c065a5651f81c3f6492b5c61bdd58e..f4884090a7ce250fc8c061a7d86e7a43993e571c 100644 --- a/current/activity_test.go +++ b/current/activity_test.go @@ -8,89 +8,56 @@ package current import ( - "gitlab.com/elixxir/primitives/states" "testing" + + "github.com/pkg/errors" + + "gitlab.com/elixxir/primitives/states" ) -//tests the test stringer is correct +// Consistency test of Activity.String. func TestActivity_String(t *testing.T) { - //define some activities to check - expectedActivityStringer := []string{"NOT_STARTED", - "WAITING", "PRECOMPUTING", "STANDBY", "REALTIME", "COMPLETED", "ERROR", "CRASH", - "UNKNOWN STATE: 8"} + expected := []string{"NOT_STARTED", "WAITING", "PRECOMPUTING", "STANDBY", + "REALTIME", "COMPLETED", "ERROR", "CRASH", "UNKNOWN STATE: 8"} - //check if states give the correct return for st := NOT_STARTED; st <= NUM_STATES; st++ { - if st.String() != expectedActivityStringer[st] { - t.Errorf("Activity %d did not string correctly: expected: %s,"+ - "received: %s", uint8(st), expectedActivityStringer[st], st.String()) + if st.String() != expected[st] { + t.Errorf("Incorrect string for Activity %d."+ + "\nexpected: %s\nreceived: %s", st, expected[st], st.String()) } } } -// Test proper happy path conversions +// Test proper happy path of Activity.ConvertToRoundState. func TestActivity_ConvertToRoundState(t *testing.T) { - activity := NOT_STARTED - state, err := activity.ConvertToRoundState() - if err == nil { - t.Errorf("Expected error when converting %+v", activity) - } - activity = WAITING - state, err = activity.ConvertToRoundState() - if err != nil { - t.Errorf("Invalid conversion: %+v", err) - } - if state != states.PENDING { - t.Errorf("Attempted to convert %+v. Expected %+v, got %+v", - activity, states.PENDING, state) - } - activity = PRECOMPUTING - state, err = activity.ConvertToRoundState() - if err != nil { - t.Errorf("Invalid conversion: %+v", err) - } - if state != states.PRECOMPUTING { - t.Errorf("Attempted to convert %+v. Expected %+v, got %+v", - activity, states.PRECOMPUTING, state) - } - activity = STANDBY - state, err = activity.ConvertToRoundState() - if err != nil { - t.Errorf("Invalid conversion: %+v", err) + tests := []struct { + activity Activity + state states.Round + err error + }{ + {NOT_STARTED, 99, errors.Errorf("unable to convert activity %s (%d) "+ + "to valid state", NOT_STARTED, NOT_STARTED)}, + {WAITING, states.PENDING, nil}, + {PRECOMPUTING, states.PRECOMPUTING, nil}, + {STANDBY, states.STANDBY, nil}, + {REALTIME, states.REALTIME, nil}, + {COMPLETED, states.COMPLETED, nil}, + {ERROR, states.FAILED, nil}, + {CRASH, 99, errors.Errorf("unable to convert activity %s (%d) to "+ + "a valid state", CRASH, CRASH)}, } - if state != states.STANDBY { - t.Errorf("Attempted to convert %+v. Expected %+v, got %+v", - activity, states.STANDBY, state) - } - activity = REALTIME - state, err = activity.ConvertToRoundState() - if err != nil { - t.Errorf("Invalid conversion: %+v", err) - } - if state != states.REALTIME { - t.Errorf("Expected %+v, got %+v", states.REALTIME, state) - } - activity = COMPLETED - state, err = activity.ConvertToRoundState() - if err != nil { - t.Errorf("Invalid conversion: %+v", err) - } - if state != states.COMPLETED { - t.Errorf("Attempted to convert %+v. Expected %+v, got %+v", - activity, states.COMPLETED, state) - } - activity = ERROR - state, err = activity.ConvertToRoundState() - if err != nil { - t.Errorf("Invalid conversion: %+v", err) - } - if state != states.FAILED { - t.Errorf("Attempted to convert %+v. Expected %+v, got %+v", - activity, states.FAILED, state) - } - activity = CRASH - state, err = activity.ConvertToRoundState() - if err == nil { - t.Errorf("Expected error when converting %+v", activity) + + for i, tt := range tests { + state, err := tt.activity.ConvertToRoundState() + if err != nil && tt.err == nil { + if err.Error() != tt.err.Error() { + t.Errorf( + "Unexpected error for %s (%d).\nexpected: %s\nreceived: %s", + tt.activity, i, tt.err, err) + } + } else if state != tt.state { + t.Errorf("Unexpected conversation of %s (%d)."+ + "\nexpected: %s\nreceived: %s", tt.activity, i, tt.state, state) + } } } diff --git a/excludedRounds/set.go b/excludedRounds/set.go index 72f693202ae54607a61351e0d64285c20abd1f86..48717aaef7de4a2ef764d4c8af2911e5ffaa7237 100644 --- a/excludedRounds/set.go +++ b/excludedRounds/set.go @@ -10,9 +10,11 @@ package excludedRounds import ( + "sync" + "github.com/golang-collections/collections/set" + "gitlab.com/xx_network/primitives/id" - "sync" ) // Set struct contains a set of rounds to be excluded from cmix @@ -22,48 +24,38 @@ type Set struct { } func NewSet() *Set { - return &Set{ - xr: set.New(nil), - RWMutex: sync.RWMutex{}, - } + return &Set{xr: set.New(nil)} } -func (e *Set) Has(rid id.Round) bool { - e.RLock() - defer e.RUnlock() +func (s *Set) Has(rid id.Round) bool { + s.RLock() + defer s.RUnlock() - return e.xr.Has(rid) + return s.xr.Has(rid) } -func (e *Set) Insert(rid id.Round) bool { - e.Lock() - defer e.Unlock() +func (s *Set) Insert(rid id.Round) bool { + s.Lock() + defer s.Unlock() - if e.xr.Has(rid) { + if s.xr.Has(rid) { return false } - e.xr.Insert(rid) + s.xr.Insert(rid) return true } -func (e *Set) Remove(rid id.Round) { - e.Lock() - defer e.Unlock() - - e.xr.Remove(rid) -} - -func (e *Set) Union(other *set.Set) *set.Set { - e.RLock() - defer e.RUnlock() +func (s *Set) Remove(rid id.Round) { + s.Lock() + defer s.Unlock() - return e.xr.Union(other) + s.xr.Remove(rid) } -func (e *Set) Len() int { - e.RLock() - defer e.RUnlock() +func (s *Set) Len() int { + s.RLock() + defer s.RUnlock() - return e.xr.Len() + return s.xr.Len() } diff --git a/excludedRounds/set_test.go b/excludedRounds/set_test.go index 5ad7c8dc8f7c2985b938650fda987ee182dedd06..a007f843202dc6d612325a5fbb10e5fd0ea7af50 100644 --- a/excludedRounds/set_test.go +++ b/excludedRounds/set_test.go @@ -8,18 +8,37 @@ package excludedRounds import ( - "gitlab.com/xx_network/primitives/id" "testing" + + "gitlab.com/xx_network/primitives/id" ) -func Test_NewSet(t *testing.T) { - xr := NewSet() +func TestSet(t *testing.T) { + s := NewSet() + if s.Len() != 1 { + t.Errorf("Unexpected length.\nexpected: %d\nreceived: %d", 1, s.Len()) + } rid1 := id.Round(400) - if xr.Has(rid1) { + if s.Has(rid1) { t.Errorf("NewSet excluded rounds set should not have anything in it") } - xr.Insert(rid1) - if !xr.Has(rid1) { + if !s.Insert(rid1) { + t.Errorf("Insert failed.") + } + if s.Insert(rid1) { + t.Errorf("Insert did not fail for already inserted item.") + } + if !s.Has(rid1) { t.Errorf("Should have found inserted round in excluded round set") } + if s.Len() != 2 { + t.Errorf("Unexpected length.\nexpected: %d\nreceived: %d", 2, s.Len()) + } + s.Remove(rid1) + if s.Has(rid1) { + t.Errorf("Should not have found round in excluded round set") + } + if s.Len() != 1 { + t.Errorf("Unexpected length.\nexpected: %d\nreceived: %d", 1, s.Len()) + } } diff --git a/fact/fact.go b/fact/fact.go index c775356ee1aceb20344c425383f1798578bb3625..d8e5a117f6ba9920434a33129637bcec81ec354f 100644 --- a/fact/fact.go +++ b/fact/fact.go @@ -8,24 +8,30 @@ package fact import ( - "fmt" + "strings" + "github.com/badoux/checkmail" "github.com/pkg/errors" "github.com/ttacon/libphonenumber" - "strings" ) -// maxFactCharacterLimit is the maximum character length of a fact. -const maxFactCharacterLimit = 64 +const ( + // The maximum character length of a fact. + maxFactLen = 64 + + // The minimum character length of a nickname. + minNicknameLen = 3 +) // Fact represents a piece of user-identifying information. This structure can // be JSON marshalled and unmarshalled. // // JSON example: -// { -// "Fact": "john@example.com", -// "T": 1 -// } +// +// { +// "Fact": "john@example.com", +// "T": 1 +// } type Fact struct { Fact string `json:"Fact"` T FactType `json:"T"` @@ -35,10 +41,9 @@ type Fact struct { // fact type. If so, it returns a new fact object. If not, it returns a // validation error. func NewFact(ft FactType, fact string) (Fact, error) { - - if len(fact) > maxFactCharacterLimit { + if len(fact) > maxFactLen { return Fact{}, errors.Errorf("Fact (%s) exceeds maximum character limit"+ - "for a fact (%d characters)", fact, maxFactCharacterLimit) + "for a fact (%d characters)", fact, maxFactLen) } f := Fact{ @@ -52,42 +57,45 @@ func NewFact(ft FactType, fact string) (Fact, error) { return f, nil } -// marshal is for transmission for UDB, not a part of the fact interface +// Stringify marshals the Fact for transmission for UDB. It is not a part of the +// fact interface. func (f Fact) Stringify() string { return f.T.Stringify() + f.Fact } -func (f Fact) Normalized() string { - return strings.ToUpper(f.Fact) -} - +// UnstringifyFact unmarshalls the stringified fact into a Fact. func UnstringifyFact(s string) (Fact, error) { if len(s) < 1 { return Fact{}, errors.New("stringified facts must at least " + "have a type at the start") } - if len(s) > maxFactCharacterLimit { + if len(s) > maxFactLen { return Fact{}, errors.Errorf("Fact (%s) exceeds maximum character limit"+ - "for a fact (%d characters)", s, maxFactCharacterLimit) + "for a fact (%d characters)", s, maxFactLen) } T := s[:1] fact := s[1:] if len(fact) == 0 { - return Fact{}, errors.New("stringified facts must be at " + - "least 1 character long") + return Fact{}, errors.New( + "stringified facts must be at least 1 character long") } ft, err := UnstringifyFactType(T) if err != nil { - return Fact{}, errors.WithMessagef(err, "Failed to unstringify fact type for %q", s) + return Fact{}, errors.WithMessagef(err, + "Failed to unstringify fact type for %q", s) } return NewFact(ft, fact) } -// Take the fact passed in and checks the input to see if it -// valid based on the type of fact it is +// Normalized returns the fact in all uppercase letters. +func (f Fact) Normalized() string { + return strings.ToUpper(f.Fact) +} + +// ValidateFact checks the fact to see if it valid based on its type. func ValidateFact(fact Fact) error { switch fact.T { case Username: @@ -107,7 +115,7 @@ func ValidateFact(fact Fact) error { } } -// Numbers are assumed to have the 2 letter country code appended +// Numbers are assumed to have the 2-letter country code appended // to the fact, with the rest of the information being a phone number // Example: 6502530000US is a valid US number with the country code // that would be the fact information for a phone number @@ -122,7 +130,8 @@ func extractNumberInfo(fact string) (number, countryCode string) { func validateEmail(email string) error { // Check that the input is validly formatted if err := checkmail.ValidateFormat(email); err != nil { - return errors.Errorf("Could not validate format for email [%s]: %v", email, err) + return errors.Errorf( + "Could not validate format for email [%s]: %v", email, err) } return nil @@ -158,8 +167,9 @@ func validateNumber(number, countryCode string) error { } func validateNickname(nickname string) error { - if len(nickname) < 3 { - return errors.New(fmt.Sprintf("Could not validate nickname %s: too short (< 3 characters)", nickname)) + if len(nickname) < minNicknameLen { + return errors.Errorf("Could not validate nickname %s: "+ + "too short (< %d characters)", nickname, minNicknameLen) } return nil } diff --git a/fact/factList.go b/fact/factList.go index d434ee641e5b16fadceee2ad5e228cd07d305e02..897a255b0601ee2efc0105e25cd7a4a8feeeb33a 100644 --- a/fact/factList.go +++ b/fact/factList.go @@ -8,18 +8,20 @@ package fact import ( + "strings" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "strings" ) -// FactList is a list of Fact. This type can be JSON marshalled and +// FactList is a list of Fact objects. This type can be JSON marshalled and // unmarshalled. type FactList []Fact const factDelimiter = "," const factBreak = ";" +// Stringify marshals the FactList into a portable string. func (fl FactList) Stringify() string { stringList := make([]string, len(fl)) for index, f := range fl { @@ -29,8 +31,8 @@ func (fl FactList) Stringify() string { return strings.Join(stringList, factDelimiter) + factBreak } -// unstrignifys facts followed by a facts break and with arbatrary data -// atttached at the end +// UnstringifyFactList unmarshalls the stringified FactList, which consists of +// the fact list and optional arbitrary data, delimited by the factBreak. func UnstringifyFactList(s string) (FactList, string, error) { parts := strings.SplitN(s, factBreak, 2) if len(parts) != 2 { @@ -42,8 +44,7 @@ func UnstringifyFactList(s string) (FactList, string, error) { for _, fString := range factStrings { fact, err := UnstringifyFact(fString) if err != nil { - jww.WARN.Printf("Fact failed to unstringify, dropped: %s", - err) + jww.WARN.Printf("Fact failed to unstringify, dropped: %s", err) } else { factList = append(factList, fact) } diff --git a/fact/factList_test.go b/fact/factList_test.go index ec521075a135c8f4ad840609fbc826ec9d6e4131..9c4897c695fe706d45f3e1667f3b369e1e849da0 100644 --- a/fact/factList_test.go +++ b/fact/factList_test.go @@ -13,52 +13,59 @@ import ( "testing" ) -func TestFactList_StringifyUnstringify(t *testing.T) { - expected := FactList{} - expected = append(expected, Fact{ - Fact: "vivian@elixxir.io", - T: Email, - }) - expected = append(expected, Fact{ - Fact: "(270) 301-5797US", - T: Phone, - }) - - FlString := expected.Stringify() - // Manually check and verify that the string version is as expected - t.Log(FlString) +// Tests that a FactList marshalled by FactList.Stringify and unmarshalled by +// UnstringifyFactList matches the original. +func TestFactList_Stringify_UnstringifyFactList(t *testing.T) { + expected := FactList{ + Fact{"vivian@elixxir.io", Email}, + Fact{"(270) 301-5797US", Phone}, + Fact{"invalidFact", Phone}, + } - actual, _, err := UnstringifyFactList(FlString) + flString := expected.Stringify() + factList, _, err := UnstringifyFactList(flString) if err != nil { - t.Fatal(err) + t.Fatalf("Failed to unstringify %q: %+v", flString, err) + } + + expected = expected[:2] + if !reflect.DeepEqual(factList, expected) { + t.Errorf("Unexpected unstringified FactList."+ + "\nexpected: %v\nreceived: %v", expected, factList) } - if !reflect.DeepEqual(actual, expected) { - t.Error("fact lists weren't equal") +} + +// Error path: Tests that UnstringifyFactList returns an error for a malformed +// stringified FactList. +func Test_UnstringifyFactList_MissingFactBreakError(t *testing.T) { + _, _, err := UnstringifyFactList("hi") + if err == nil { + t.Errorf("Expected error for invalid stringified list.") } } -// Tests that a FactList can be JSON marshalled and unmarshalled. -func TestFactList_JSON(t *testing.T) { - fl := FactList{ +// Tests that a FactList JSON marshalled and unmarshalled matches the original. +func TestFactList_JsonMarshalUnmarshal(t *testing.T) { + expected := FactList{ {"devUsername", Username}, {"devinputvalidation@elixxir.io", Email}, {"6502530000US", Phone}, {"name", Nickname}, } - out, err := json.Marshal(fl) + data, err := json.Marshal(expected) if err != nil { - t.Errorf("Failed to marshal FactList: %+v", err) + t.Fatalf("Failed to JSON marshal FactList: %+v", err) } - var newFactList FactList - err = json.Unmarshal(out, &newFactList) + var factList FactList + err = json.Unmarshal(data, &factList) if err != nil { - t.Errorf("Failed to unmarshal FactList: %+v", err) + t.Errorf("Failed to JSON unmarshal FactList: %+v", err) } - if !reflect.DeepEqual(fl, newFactList) { + if !reflect.DeepEqual(expected, factList) { t.Errorf("Marshalled and unmarshalled FactList does not match original."+ - "\nexpected: %+v\nreceived: %+v", fl, newFactList) + "\nexpected: %+v\nreceived: %+v", expected, factList) } } diff --git a/fact/fact_test.go b/fact/fact_test.go index 32483d50890c1f597e8e49f3d0a04da18ec0e24f..449261b199bfb32f43215bdb45ef181545542024 100644 --- a/fact/fact_test.go +++ b/fact/fact_test.go @@ -9,170 +9,255 @@ package fact import ( "encoding/json" + "fmt" "reflect" + "strings" "testing" ) -// Test NewFact() function returns a correctly formatted Fact +// Tests that NewFact returns a correctly formatted Fact. func TestNewFact(t *testing.T) { - // Expected result - e := Fact{ - Fact: "devinputvalidation@elixxir.io", - T: 1, + tests := []struct { + ft FactType + fact string + expected Fact + }{ + {Username, "myUsername", Fact{"myUsername", Username}}, + {Email, "email@example.com", Fact{"email@example.com", Email}}, + {Phone, "8005559486US", Fact{"8005559486US", Phone}}, + {Nickname, "myNickname", Fact{"myNickname", Nickname}}, } - g, err := NewFact(Email, "devinputvalidation@elixxir.io") - if err != nil { - t.Error(err) + for i, tt := range tests { + fact, err := NewFact(tt.ft, tt.fact) + if err != nil { + t.Errorf("Failed to make new fact (%d): %+v", i, err) + } else if !reflect.DeepEqual(tt.expected, fact) { + t.Errorf("Unexpected new Fact (%d).\nexpected: %s\nreceived: %s", + i, tt.expected, fact) + } } +} - if !reflect.DeepEqual(e, g) { - t.Errorf("The returned Fact did not match the expected Fact") +// Error path: Tests that NewFact returns error when a fact exceeds the +// maxFactLen. +func TestNewFact_ExceedMaxFactError(t *testing.T) { + _, err := NewFact(Email, + "devinputvalidation_devinputvalidation_devinputvalidation@elixxir.io") + if err == nil { + t.Fatal("Expected error when the fact is longer than the maximum " + + "character length.") } + } -// Test NewFact() returns error when a fact exceeds the maxFactCharacterLimit. -func TestNewFact_ExceedMaxFactError(t *testing.T) { - // Expected error case - _, err := NewFact(Email, "devinputvalidation_devinputvalidation_devinputvalidation@elixxir.io") +// Error path: Tests that NewFact returns error when the fact is not valid. +func TestNewFact_InvalidFactError(t *testing.T) { + _, err := NewFact(Nickname, "hi") if err == nil { - t.Fatalf("NewFact expected to fail due to the fact exceeding maximum character length") + t.Fatal("Expected error when the fact is invalid.") + } +} + +// Tests that a Fact marshalled by Fact.Stringify and unmarshalled by +// UnstringifyFact matches the original. +func TestFact_Stringify_UnstringifyFact(t *testing.T) { + facts := []Fact{ + {"myUsername", Username}, + {"email@example.com", Email}, + {"8005559486US", Phone}, + {"myNickname", Nickname}, } + for i, expected := range facts { + factString := expected.Stringify() + fact, err := UnstringifyFact(factString) + if err != nil { + t.Errorf( + "Failed to unstringify fact %s (%d): %+v", expected, i, err) + } else if !reflect.DeepEqual(expected, fact) { + t.Errorf("Unexpected unstringified Fact %s (%d)."+ + "\nexpected: %s\nreceived: %s", + factString, i, expected, fact) + } + } } -// Test Stringify() creates a string of the Fact -// The output is verified to work in the test below +// Consistency test of Fact.Stringify. func TestFact_Stringify(t *testing.T) { - f := Fact{ - Fact: "devinputvalidation@elixxir.io", - T: 1, + tests := []struct { + fact Fact + expected string + }{ + {Fact{"myUsername", Username}, "UmyUsername"}, + {Fact{"email@example.com", Email}, "Eemail@example.com"}, + {Fact{"8005559486US", Phone}, "P8005559486US"}, + {Fact{"myNickname", Nickname}, "NmyNickname"}, } - expected := "Edevinputvalidation@elixxir.io" - got := f.Stringify() - t.Log(got) + for i, tt := range tests { + factString := tt.fact.Stringify() - if got != expected { - t.Errorf("Marshalled object from Got did not match Expected.\n\tGot: %v\n\tExpected: %v", got, expected) + if factString != tt.expected { + t.Errorf("Unexpected strified Fact %s (%d)."+ + "\nexpected: %s\nreceived: %s", + tt.fact, i, tt.expected, factString) + } } } -// Test the UnstringifyFact function creates a Fact from a string -// NOTE: this test does not pass, with error "Unknown Fact FactType: Etesting" -func TestFact_UnstringifyFact(t *testing.T) { - // Expected fact from above test - e := Fact{ - Fact: "devinputvalidation@elixxir.io", - T: Email, +// Consistency test of UnstringifyFact +func TestUnstringifyFact(t *testing.T) { + tests := []struct { + factString string + expected Fact + }{ + {"UmyUsername", Fact{"myUsername", Username}}, + {"Eemail@example.com", Fact{"email@example.com", Email}}, + {"P8005559486US", Fact{"8005559486US", Phone}}, + {"NmyNickname", Fact{"myNickname", Nickname}}, } - // Stringify-ed Fact from above test - m := "Edevinputvalidation@elixxir.io" - f, err := UnstringifyFact(m) - if err != nil { - t.Error(err) + for i, tt := range tests { + fact, err := UnstringifyFact(tt.factString) + if err != nil { + t.Errorf( + "Failed to unstringify fact %s (%d): %+v", tt.factString, i, err) + } else if !reflect.DeepEqual(tt.expected, fact) { + t.Errorf("Unexpected unstringified Fact %s (%d)."+ + "\nexpected: %s\nreceived: %s", + tt.factString, i, tt.expected, fact) + } } +} - t.Log(f.Fact) - t.Log(f.T) +// Error path: Tests all error paths of UnstringifyFact. +func TestUnstringifyFact_Error(t *testing.T) { + longFact := strings.Repeat("A", maxFactLen+1) + tests := []struct { + factString string + expectedErr string + }{ + {"", "stringified facts must at least have a type at the start"}, + {longFact, fmt.Sprintf("Fact (%s) exceeds maximum character limitfor "+ + "a fact (%d characters)", longFact, maxFactLen)}, + {"P", "stringified facts must be at least 1 character long"}, + {"QA", `Failed to unstringify fact type for "QA"`}, + } - if !reflect.DeepEqual(e, f) { - t.Errorf("The returned Fact did not match the expected Fact") + for i, tt := range tests { + _, err := UnstringifyFact(tt.factString) + if err == nil || !strings.Contains(err.Error(), tt.expectedErr) { + t.Errorf("Unexpected error when Unstringifying fact %q (%d)."+ + "\nexpected: %s\nreceived: %+v", + tt.factString, i, tt.expectedErr, err) + } } } -// Unit test for input validation of emails -// NOTE: Tests for here might fail on goland due to bad internet connections -// it is likely this will pass remotely -func TestValidateFact_Email(t *testing.T) { - // Valid Fact - validFact := Fact{ - Fact: "devinputvalidation@elixxir.io", - T: Email, +// Consistency test of Fact.Normalized. +func TestFact_Normalized(t *testing.T) { + tests := []struct { + fact Fact + expected string + }{ + {Fact{"myUsername", Username}, "MYUSERNAME"}, + {Fact{"email@example.com", Email}, "EMAIL@EXAMPLE.COM"}, + {Fact{"8005559486US", Phone}, "8005559486US"}, + {Fact{"myNickname", Nickname}, "MYNICKNAME"}, } - // Happy path with valid email and host - err := ValidateFact(validFact) - if err != nil { - t.Errorf("Unexpected error in happy path: %v", err) + for i, tt := range tests { + normal := tt.fact.Normalized() + if normal != tt.expected { + t.Errorf("Unexpected new normalized Fact %v (%d)."+ + "\nexpected: %q\nreceived: %q", tt.fact, i, tt.expected, normal) + } } +} - // Invalid Fact Host - invalidEmail := Fact{ - Fact: "test@gmail@gmail.com", - T: Email, +// Tests that ValidateFact correctly validates various facts. +func TestValidateFact(t *testing.T) { + facts := []Fact{ + {"myUsername", Username}, + {"email@example.com", Email}, + {"8005559486US", Phone}, + {"myNickname", Nickname}, } - // Should not be able to verify user - err = ValidateFact(invalidEmail) - if err == nil { - t.Errorf("Expected error in error path: should not be able to verify %s", invalidEmail.Fact) + for i, fact := range facts { + err := ValidateFact(fact) + if err != nil { + t.Errorf( + "Failed to validate fact %s (%d): %+v", fact, i, err) + } } } -// Unit test for input validation of emails -func TestValidateFact_PhoneNumber(t *testing.T) { - USCountryCode := "US" - // UKCountryCode := "UK" - // InvalidNumber := "020 8743 8000135" - USNumber := "6502530000" - - // Valid Fact - USFact := Fact{ - Fact: USNumber + USCountryCode, - T: Phone, - } - - // Check US valid fact combination - err := ValidateFact(USFact) - if err != nil { - t.Errorf("Unexpected error in happy path: %v", err) - } - - // Phone number validation disabled - // InvalidFact := Fact{ - // Fact: USNumber + UKCountryCode, - // T: Phone, - // } - // - // // Invalid number and country code combination - // err = ValidateFact(InvalidFact) - // if err == nil { - // t.Errorf("Expected error path: should not be able to validate US number with UK country code") - // } - // - // InvalidFact = Fact{ - // Fact: InvalidNumber, - // T: Phone, - // } - // // Pass in an invalid number with a valid country code - // err = ValidateFact(InvalidFact) - // if err == nil { - // t.Errorf("Expected error path: should not be able to validate US number with UK country code") - // } +// Error path: Tests that ValidateFact does not validate invalid facts +func TestValidateFact_InvalidFactsError(t *testing.T) { + facts := []Fact{ + {"test@gmail@gmail.com", Email}, + {"US8005559486", Phone}, + {"020 8743 8000135UK", Phone}, + {"me", Nickname}, + {"me", 99}, + } + + for i, fact := range facts { + err := ValidateFact(fact) + if err == nil { + t.Errorf("Did not error on invalid fact %s (%d)", fact, i) + } + } } -// Tests that a Fact can be JSON marshalled and unmarshalled. -func TestFact_JSON(t *testing.T) { - f := Fact{ - Fact: "devinputvalidation@elixxir.io", - T: Email, +// Error path: Tests all error paths of validateNumber. +func Test_validateNumber_Error(t *testing.T) { + tests := []struct { + number, countryCode string + expectedErr string + }{ + {"5", "", "Number or input are of length 0"}, + {"", "US", "Number or input are of length 0"}, + // {"020 8743 8000135", "UK", `Could not parse number "020 8743 8000135"`}, + {"8005559486", "UK", `Could not parse number [8005559486]`}, + {"+343511234567", "ES", `Could not validate number [+343511234567]`}, } - out, err := json.Marshal(f) - if err != nil { - t.Errorf("Failed to marshal Fact: %+v", err) + for i, tt := range tests { + err := validateNumber(tt.number, tt.countryCode) + if err == nil || !strings.Contains(err.Error(), tt.expectedErr) { + t.Errorf("Unexpected error when validating number %q with country "+ + "code %q (%d).\nexpected: %s\nreceived: %+v", + tt.number, tt.countryCode, i, tt.expectedErr, err) + } } +} - var newFact Fact - err = json.Unmarshal(out, &newFact) - if err != nil { - t.Errorf("Failed to unmarshal Fact: %+v", err) +// Tests that a Fact JSON marshalled and unmarshalled matches the original. +func TestFact_JsonMarshalUnmarshal(t *testing.T) { + facts := []Fact{ + {"myUsername", Username}, + {"email@example.com", Email}, + {"8005559486US", Phone}, + {"myNickname", Nickname}, } - if f != newFact { - t.Errorf("Marshalled and unmarshalled fact does not match original."+ - "\nexpected: %+v\nreceived: %+v", f, newFact) + for i, expected := range facts { + data, err := json.Marshal(expected) + if err != nil { + t.Errorf("Failed to JSON marshal %s (%d): %+v", expected, i, err) + } + + var fact Fact + if err = json.Unmarshal(data, &fact); err != nil { + t.Errorf("Failed to JSON unmarshal %s (%d): %+v", expected, i, err) + } + + if !reflect.DeepEqual(expected, fact) { + t.Errorf("Unexpected unmarshalled fact (%d)."+ + "\nexpected: %+v\nreceived: %+v", i, expected, fact) + } } } diff --git a/fact/type.go b/fact/type.go index 779ea7cb81075db8ce4e183a886319a4067e92db..1ba30054e09cf17c5bb1ff7090e86f4521377fb0 100644 --- a/fact/type.go +++ b/fact/type.go @@ -9,6 +9,7 @@ package fact import ( "fmt" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" ) @@ -22,6 +23,8 @@ const ( Nickname FactType = 3 ) +// String returns the string representation of the FactType. This functions +// adheres to the fmt.Stringer interface. func (t FactType) String() string { switch t { case Username: @@ -37,6 +40,7 @@ func (t FactType) String() string { } } +// Stringify marshals the FactType into a portable string. func (t FactType) Stringify() string { switch t { case Username: @@ -52,6 +56,7 @@ func (t FactType) Stringify() string { return "error" } +// UnstringifyFactType unmarshalls the stringified FactType. func UnstringifyFactType(s string) (FactType, error) { switch s { case "U": @@ -66,6 +71,7 @@ func UnstringifyFactType(s string) (FactType, error) { return 3, errors.Errorf("Unknown Fact FactType: %s", s) } +// IsValid determines if the FactType is one of the defined types. func (t FactType) IsValid() bool { return t == Username || t == Email || t == Phone || t == Nickname } diff --git a/fact/type_test.go b/fact/type_test.go index f3577d9417dddf94ee417cfc6c578157f358fa8b..5465510922893742d4b3886cd43e51459c92e6ea 100644 --- a/fact/type_test.go +++ b/fact/type_test.go @@ -11,57 +11,82 @@ import ( "testing" ) +// Consistency test of FactType.String. func TestFactType_String(t *testing.T) { - // FactTypes and expected strings for them - FTs := []FactType{Username, Email, Phone, FactType(200)} - Strs := []string{"Username", "Email", "Phone", "Unknown Fact FactType: 200"} - for i, ft := range FTs { - if FactType.String(ft) != Strs[i] { - t.Errorf("Got unexpected string for FactType.\n\tGot: %s\n\tExpected: %s", FactType.String(ft), Strs[i]) - } + tests := map[FactType]string{ + Username: "Username", + Email: "Email", + Phone: "Phone", + Nickname: "Nickname", + FactType(200): "Unknown Fact FactType: 200", } -} -func TestFactType_Stringify(t *testing.T) { - // FactTypes and expected strings for them - FTs := []FactType{Username, Email, Phone} - Strs := []string{"U", "E", "P"} - for i, ft := range FTs { - if FactType.Stringify(ft) != Strs[i] { - t.Errorf("Got unexpected string for FactType.\n\tGot: %s\n\tExpected: %s", FactType.Stringify(ft), Strs[i]) + for ft, expected := range tests { + str := ft.String() + if expected != str { + t.Errorf("Unexpected FactType string.\nexpected: %q\nreceived: %q", + expected, str) } } } -func TestFactType_Unstringify(t *testing.T) { - // FactTypes and expected strings for them - FTs := []FactType{Username, Email, Phone} - Strs := []string{"U", "E", "P"} - for i, ft := range FTs { - gotft, err := UnstringifyFactType(Strs[i]) +// Tests that a FactType marshalled by FactType.Stringify and unmarshalled by +// UnstringifyFactType matches the original. +func TestFactType_Stringify_UnstringifyFactType(t *testing.T) { + factTypes := []FactType{ + Username, + Email, + Phone, + Nickname, + } + + for _, expected := range factTypes { + str := expected.Stringify() + + ft, err := UnstringifyFactType(str) if err != nil { - t.Error(err) + t.Fatalf("Failed to unstringify fact type %q: %+v", str, err) } - if gotft != ft { - t.Errorf("Got unexpected string for FactType.\n\tGot: %s\n\tExpected: %s", FactType.Stringify(ft), Strs[i]) + if expected != ft { + t.Errorf("Unexpected unstringified FactType."+ + "\nexpected: %s\nreceived: %s", expected, str) } } +} - _, err := UnstringifyFactType("x") +// Panic path: Tests that FactType.Stringify panics for an invalid FactType +func TestFactType_Stringify_InvalidFactTypePanic(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("Failed to panic for invalid FactType") + } + }() + + FactType(99).Stringify() +} + +// Error path: Tests that FactType.UnstringifyFactType returns an error for an +// invalid FactType. +func TestFactType_Unstringify_UnknownFactTypeError(t *testing.T) { + _, err := UnstringifyFactType("invalid") if err == nil { - t.Errorf("UnstringifyFactType did not return an error on an invalid type") + t.Errorf("Failed to get error for invalid FactType.") } } func TestFactType_IsValid(t *testing.T) { - if !FactType.IsValid(Username) || - !FactType.IsValid(Email) || - !FactType.IsValid(Phone) { - - t.Errorf("FactType.IsValid did not report a FactType as valid") + tests := map[FactType]bool{ + Username: true, + Email: true, + Phone: true, + Nickname: true, + 99: false, } - if FactType.IsValid(FactType(200)) { - t.Errorf("FactType.IsValid reported a non-valid FactType value as valid") + for ft, expected := range tests { + if ft.IsValid() != expected { + t.Errorf("Unexpected IsValid result for %s."+ + "\nexpected: %t\nreceived: %t", ft, expected, ft.IsValid()) + } } } diff --git a/format/fingerprint_test.go b/format/fingerprint_test.go index c99ba414ecd3b122b75eb2958f58e59d610e8b3e..1e10e80ac808d82872fbc6c96a21ac678754a107 100644 --- a/format/fingerprint_test.go +++ b/format/fingerprint_test.go @@ -22,14 +22,14 @@ func TestNewFingerprint(t *testing.T) { fp := NewFingerprint(fpBytes) if !bytes.Equal(fpBytes, fp[:]) { - t.Errorf("NewFingerprint() failed to copy the correct bytes into the "+ + t.Errorf("NewFingerprint failed to copy the correct bytes into the "+ "Fingerprint.\nexpected: %+v\nreceived: %+v", fpBytes, fp) } // Ensure that the data is copied fpBytes[2]++ if fp[2] == fpBytes[2] { - t.Errorf("NewFingerprint() failed to create a copy of the data.") + t.Errorf("NewFingerprint failed to create a copy of the data.") } } @@ -42,14 +42,14 @@ func TestFingerprint_Bytes(t *testing.T) { fp := NewFingerprint(fpBytes) testFpBytes := fp.Bytes() if !bytes.Equal(fpBytes, testFpBytes) { - t.Errorf("Bytes() failed to return the expected bytes."+ + t.Errorf("Bytes failed to return the expected bytes."+ "\nexpected: %+v\nreceived: %+v", fpBytes, testFpBytes) } // Ensure that the data is copied testFpBytes[2]++ if fp[2] == testFpBytes[2] { - t.Errorf("Bytes() failed to create a copy of the data.") + t.Errorf("Bytes failed to create a copy of the data.") } } @@ -62,7 +62,7 @@ func TestFingerprint_String(t *testing.T) { expectedString := base64.StdEncoding.EncodeToString(fpBytes) if expectedString != fp.String() { - t.Errorf("String() failed to return the expected string."+ + t.Errorf("String failed to return the expected string."+ "\nexpected: %s\nreceived: %s", expectedString, fp.String()) } } diff --git a/format/message.go b/format/message.go index 854a7de6386a6bb72dbdb10eccc510eb091d50ea..5e4adf05bca6c663cf39e24fbc1a25ec022d2a86 100644 --- a/format/message.go +++ b/format/message.go @@ -11,9 +11,10 @@ import ( "encoding/base64" "encoding/binary" "fmt" - "golang.org/x/crypto/blake2b" "strconv" + "golang.org/x/crypto/blake2b" + jww "github.com/spf13/jwalterweatherman" ) @@ -47,10 +48,10 @@ const ( | 2*primeSize - recipientID bits | +------------------------------------------------------------------------+ -* size: size in bits of the data which is stored -* Contents1 size = primeSize - grpBitASize - KeyFPLen - sizeSize - 1 -* Contents2 size = primeSize - grpBitBSize - MacLen - RecipientIDLen - timestampSize -* the size of the data in the two contents fields is stored within the "size" field + - size: size in bits of the data which is stored + - Contents1 size = primeSize - grpBitASize - KeyFPLen - sizeSize - 1 + - Contents2 size = primeSize - grpBitBSize - MacLen - RecipientIDLen - timestampSize + - the size of the data in the two contents fields is stored within the "size" field /////Adherence to the group///////////////////////////////////////////////////// The first bits of keyFingerprint and MAC are enforced to be 0, thus ensuring @@ -118,7 +119,7 @@ func (m *Message) Marshal() []byte { // MarshalImmutable marshals the message into a byte slice. Note that the // Ephemeral ID and the SIH both change every time a message is // sent. This function 0's those fields to guarantee that the same -// message will be byte idendical with itself when Marshalled. +// message will be byte identical with itself when Marshalled. func (m *Message) MarshalImmutable() []byte { newM := m.Copy() newM.SetEphemeralRID(make([]byte, EphemeralRIDLen)) diff --git a/format/message_test.go b/format/message_test.go index a07028d20d57602fda92da1a0bc72f94ed542f7e..e0d31e2aab4c51535f744641c56414b17076237e 100644 --- a/format/message_test.go +++ b/format/message_test.go @@ -16,7 +16,7 @@ import ( "time" ) -func TestMessage_Version(t *testing.T) { +func TestMessage_VersionDetection(t *testing.T) { msg := NewMessage(MinimumPrimeSize) // Generate message parts @@ -106,17 +106,17 @@ func TestNewMessage(t *testing.T) { msg := NewMessage(MinimumPrimeSize) if !reflect.DeepEqual(expectedMsg, msg) { - t.Errorf("NewMessage() did not return the expected Message."+ + t.Errorf("NewMessage did not return the expected Message."+ "\nexpected: %+v\nreceived: %+v", expectedMsg, msg) } } // Error path: panics if provided prime size is too small. func TestNewMessage_NumPrimeBytesError(t *testing.T) { - // Defer to an error when NewMessage() does not panic + // Defer to an error when NewMessage does not panic defer func() { if r := recover(); r == nil { - t.Error("NewMessage() did not panic when the minimum prime size " + + t.Error("NewMessage did not panic when the minimum prime size " + "is too small.") } }() @@ -143,7 +143,7 @@ func TestMessage_Marshal_Unmarshal(t *testing.T) { } if !reflect.DeepEqual(m, newMsg) { - t.Errorf("Failed to Marshal() and Unmarshal() message."+ + t.Errorf("Failed to Marshal and Unmarshal message."+ "\nexpected: %#v\nreceived: %#v", m, newMsg) } } @@ -178,6 +178,23 @@ func TestMessage_Marshal_UnmarshalImmutable(t *testing.T) { } } +// Happy path. +func TestMessage_Version(t *testing.T) { + msg := NewMessage(MinimumPrimeSize) + + if msg.Version() != 0 { + t.Errorf("Unexpected version for new Message."+ + "\nexpected: %d\nreceived: %d", 0, msg.Version()) + } + + copy(msg.version, []byte{123}) + + if msg.Version() != 123 { + t.Errorf("Unexpected version."+ + "\nexpected: %d\nreceived: %d", 123, msg.Version()) + } +} + // Happy path. func TestMessage_Copy(t *testing.T) { msg := NewMessage(MinimumPrimeSize) @@ -189,7 +206,7 @@ func TestMessage_Copy(t *testing.T) { msgCopy.SetContents(contents) if bytes.Equal(msg.GetContents(), contents) { - t.Errorf("Copy() failed to make a copy of the message; modifications " + + t.Errorf("Copy failed to make a copy of the message; modifications " + "to copy reflected in original.") } } @@ -200,7 +217,7 @@ func TestMessage_GetPrimeByteLen(t *testing.T) { m := NewMessage(primeSize) if m.GetPrimeByteLen() != primeSize { - t.Errorf("GetPrimeByteLen() returned incorrect prime size."+ + t.Errorf("GetPrimeByteLen returned incorrect prime size."+ "\nexpected: %d\nreceived: %d", primeSize, m.GetPrimeByteLen()) } } @@ -213,14 +230,14 @@ func TestMessage_GetPayloadA(t *testing.T) { copy(msg.payloadA, testData) payload := msg.GetPayloadA() if !bytes.Equal(testData, payload[:len(testData)]) { - t.Errorf("GetPayloadA() did not properly retrieve payload A."+ + t.Errorf("GetPayloadA did not properly retrieve payload A."+ "\nexpected: %s\nreceived: %s", testData, payload[:len(testData)]) } // Ensure that the data is copied payload[14] = 'x' if msg.payloadA[14] == payload[14] { - t.Error("GetPayloadA() did not make a copy; modifications to copy " + + t.Error("GetPayloadA did not make a copy; modifications to copy " + "reflected in original.") } } @@ -233,7 +250,7 @@ func TestMessage_SetPayloadA(t *testing.T) { msg.SetPayloadA(payload) if !bytes.Equal(payload, msg.payloadA) { - t.Errorf("SetPayloadA() failed to set payload A correctly."+ + t.Errorf("SetPayloadA failed to set payload A correctly."+ "\nexpected: %s\nreceived: %s", payload, msg.payloadA) } } @@ -244,7 +261,7 @@ func TestMessage_SetPayloadA_LengthError(t *testing.T) { msg := NewMessage(MinimumPrimeSize) defer func() { if r := recover(); r == nil { - t.Errorf("SetPayloadA() failed to panic when the length of the "+ + t.Errorf("SetPayloadA failed to panic when the length of the "+ "provided payload (%d) is not the same as the message payload "+ "length (%d).", len(payload), len(msg.GetPayloadA())) } @@ -261,14 +278,14 @@ func TestMessage_GetPayloadB(t *testing.T) { copy(msg.payloadB, testData) payload := msg.GetPayloadB() if !bytes.Equal(testData, payload[:len(testData)]) { - t.Errorf("GetPayloadB() did not properly retrieve payload B."+ + t.Errorf("GetPayloadB did not properly retrieve payload B."+ "\nexpected: %s\nreceived: %s", testData, payload[:len(testData)]) } // Ensure that the data is copied payload[14] = 'x' if msg.payloadB[14] == payload[14] { - t.Error("GetPayloadB() did not make a copy; modifications to copy " + + t.Error("GetPayloadB did not make a copy; modifications to copy " + "reflected in original.") } } @@ -281,7 +298,7 @@ func TestMessage_SetPayloadB(t *testing.T) { msg.SetPayloadB(payload) if !bytes.Equal(payload, msg.payloadB) { - t.Errorf("SetPayloadB() failed to set payload B correctly."+ + t.Errorf("SetPayloadB failed to set payload B correctly."+ "\nexpected: %s\nreceived: %s", payload, msg.payloadB) } } @@ -292,7 +309,7 @@ func TestMessage_SetPayloadB_LengthError(t *testing.T) { msg := NewMessage(MinimumPrimeSize) defer func() { if r := recover(); r == nil { - t.Errorf("SetPayloadB() failed to panic when the length of the "+ + t.Errorf("SetPayloadB failed to panic when the length of the "+ "provided payload (%d) is not the same as the message payload "+ "length (%d).", len(payload), len(msg.GetPayloadB())) } @@ -306,7 +323,7 @@ func TestMessage_ContentsSize(t *testing.T) { msg := NewMessage(MinimumPrimeSize) if msg.ContentsSize() != MinimumPrimeSize*2-AssociatedDataSize-1 { - t.Errorf("ContentsSize() returned the wrong content size."+ + t.Errorf("ContentsSize returned the wrong content size."+ "\nexpected: %d\nreceived: %d", MinimumPrimeSize*2-AssociatedDataSize-1, msg.ContentsSize()) } @@ -323,7 +340,7 @@ func TestMessage_GetContents(t *testing.T) { retrieved := msg.GetContents() if !bytes.Equal(retrieved, contents) { - t.Errorf("GetContents() did not return the expected contents."+ + t.Errorf("GetContents did not return the expected contents."+ "\nexpected: %s\nreceived: %s", contents, retrieved) } } @@ -336,13 +353,13 @@ func TestMessage_SetContents(t *testing.T) { msg.SetContents(contents) if !bytes.Equal(msg.contents1, contents[:len(msg.contents1)]) { - t.Errorf("SetContents() did not set contents1 correctly."+ + t.Errorf("SetContents did not set contents1 correctly."+ "\nexpected: %s\nreceived: %s", contents[:len(msg.contents1)], msg.contents1) } if !bytes.Equal(msg.contents2, contents[len(msg.contents1):]) { - t.Errorf("SetContents() did not set contents2 correctly."+ + t.Errorf("SetContents did not set contents2 correctly."+ "\nexpected: %s\nreceived: %s", contents[len(msg.contents1):], msg.contents2) } @@ -356,14 +373,15 @@ func TestMessage_SetContents_ShortContents(t *testing.T) { msg.SetContents(contents) if !bytes.Equal(msg.contents1, contents[:len(msg.contents1)]) { - t.Errorf("SetContents() did not set contents1 correctly."+ + t.Errorf("SetContents did not set contents1 correctly."+ "\nexpected: %s\nreceived: %s", contents[:len(msg.contents1)], msg.contents1) } - expectedContents2 := make([]byte, MinimumPrimeSize-MacLen-EphemeralRIDLen-SIHLen) + expectedContents2 := + make([]byte, MinimumPrimeSize-MacLen-EphemeralRIDLen-SIHLen) if !bytes.Equal(msg.contents2, expectedContents2) { - t.Errorf("SetContents() did not set contents2 correctly."+ + t.Errorf("SetContents did not set contents2 correctly."+ "\nexpected: %+v\nreceived: %+v", expectedContents2, msg.contents2) } } @@ -375,7 +393,7 @@ func TestMessage_SetContents_ContentsTooLargeError(t *testing.T) { defer func() { if r := recover(); r == nil { - t.Errorf("SetContents() failed to panic when the length of the "+ + t.Errorf("SetContents failed to panic when the length of the "+ "provided contents (%d) is larger than the max content length "+ "(%d).", len(contents), len(msg.contents1)+len(msg.contents2)) } @@ -391,7 +409,7 @@ func TestMessage_GetRawContentsSize(t *testing.T) { expectedLen := (2 * MinimumPrimeSize) - RecipientIDLen if msg.GetRawContentsSize() != expectedLen { - t.Errorf("GetRawContentsSize() did not return the expected size."+ + t.Errorf("GetRawContentsSize did not return the expected size."+ "\nexpected: %d\nreceived: %d", expectedLen, msg.GetRawContentsSize()) } } @@ -419,13 +437,13 @@ func TestMessage_GetRawContents(t *testing.T) { copy(msg.contents1, contents1) copy(msg.contents2, contents2) - //make sure the 1st and middle+1 bits are 1 + // Make sure the 1st and middle+1 bits are 1 msg.payloadA[0] |= 0b10000000 msg.payloadB[0] |= 0b10000000 rawContents := msg.GetRawContents() if !bytes.Equal(expectedRawContents, rawContents) { - t.Errorf("GetRawContents() did not return the expected raw contents."+ + t.Errorf("GetRawContents did not return the expected raw contents."+ "\nexpected: %s\nreceived: %s", expectedRawContents, rawContents) } @@ -460,28 +478,36 @@ func TestMessage_SetRawContents(t *testing.T) { msg.SetRawContents(sp) - if bytes.Contains(msg.keyFP, []byte("a")) || bytes.Contains(msg.keyFP, []byte("b")) || - bytes.Contains(msg.keyFP, []byte("m")) || !bytes.Contains(msg.keyFP, []byte("f")) { + if bytes.Contains(msg.keyFP, []byte("a")) || + bytes.Contains(msg.keyFP, []byte("b")) || + bytes.Contains(msg.keyFP, []byte("m")) || + !bytes.Contains(msg.keyFP, []byte("f")) { t.Errorf("Setting raw payload failed, key fingerprint contains "+ "wrong data: %s", msg.keyFP) } - if bytes.Contains(msg.mac, []byte("a")) || bytes.Contains(msg.mac, []byte("b")) || - !bytes.Contains(msg.mac, []byte("m")) || bytes.Contains(msg.mac, []byte("f")) { - t.Errorf("Setting raw payload failed, mac contains "+ - "wrong data: %s", msg.mac) + if bytes.Contains(msg.mac, []byte("a")) || + bytes.Contains(msg.mac, []byte("b")) || + !bytes.Contains(msg.mac, []byte("m")) || + bytes.Contains(msg.mac, []byte("f")) { + t.Errorf( + "Setting raw payload failed, mac contains wrong data: %s", msg.mac) } - if !bytes.Contains(msg.contents1, []byte("a")) || bytes.Contains(msg.contents1, []byte("b")) || - bytes.Contains(msg.contents1, []byte("m")) || bytes.Contains(msg.contents1, []byte("f")) { - t.Errorf("Setting raw payload failed, contents1 contains "+ - "wrong data: %s", msg.contents1) + if !bytes.Contains(msg.contents1, []byte("a")) || + bytes.Contains(msg.contents1, []byte("b")) || + bytes.Contains(msg.contents1, []byte("m")) || + bytes.Contains(msg.contents1, []byte("f")) { + t.Errorf("Setting raw payload failed, contents1 contains wrong data: %s", + msg.contents1) } - if bytes.Contains(msg.contents2, []byte("a")) || !bytes.Contains(msg.contents2, []byte("b")) || - bytes.Contains(msg.contents2, []byte("m")) || bytes.Contains(msg.contents2, []byte("f")) { - t.Errorf("Setting raw payload failed, contents2 contains "+ - "wrong data: %s", msg.contents2) + if bytes.Contains(msg.contents2, []byte("a")) || + !bytes.Contains(msg.contents2, []byte("b")) || + bytes.Contains(msg.contents2, []byte("m")) || + bytes.Contains(msg.contents2, []byte("f")) { + t.Errorf("Setting raw payload failed, contents2 contains wrong data: %s", + msg.contents2) } } @@ -492,7 +518,7 @@ func TestMessage_SetRawContents_LengthError(t *testing.T) { defer func() { if r := recover(); r == nil { - t.Error("SetRawContents() failed to panic when length of the " + + t.Error("SetRawContents failed to panic when length of the " + "provided data is incorrect.") } }() @@ -508,14 +534,14 @@ func TestMessage_GetKeyFP(t *testing.T) { copy(msg.keyFP, keyFP.Bytes()) if keyFP != msg.GetKeyFP() { - t.Errorf("GetKeyFP() failed to get the correct keyFP."+ + t.Errorf("GetKeyFP failed to get the correct keyFP."+ "\nexpected: %+v\nreceived: %+v", keyFP, msg.GetKeyFP()) } // Ensure that the data is copied keyFP[2] = 'x' if msg.sih[2] == 'x' { - t.Error("GetKeyFP() failed to make a copy of keyFP.") + t.Error("GetKeyFP failed to make a copy of keyFP.") } if msg.GetKeyFP()[0]&0b10000000 != 0 { @@ -531,7 +557,7 @@ func TestMessage_SetKeyFP(t *testing.T) { msg.SetKeyFP(fp) if !bytes.Equal(fp.Bytes(), msg.keyFP) { - t.Errorf("SetKeyFP() failed to set keyFP."+ + t.Errorf("SetKeyFP failed to set keyFP."+ "\nexpected: %+v\nreceived: %+v", fp, msg.keyFP) } } @@ -543,7 +569,7 @@ func TestMessage_SetKeyFP_FirstBitError(t *testing.T) { defer func() { if r := recover(); r == nil { - t.Error("SetKeyFP() failed to panic when the first bit of the " + + t.Error("SetKeyFP failed to panic when the first bit of the " + "provided data is not 0.") } }() @@ -559,14 +585,14 @@ func TestMessage_GetMac(t *testing.T) { msg.mac[0] |= 0b10000000 if !bytes.Equal(mac, msg.GetMac()) { - t.Errorf("GetMac() failed to get the correct MAC."+ + t.Errorf("GetMac failed to get the correct MAC."+ "\nexpected: %+v\nreceived: %+v", mac, msg.GetMac()) } // Ensure that the data is copied mac[2] = 'x' if msg.mac[2] == 'x' { - t.Error("GetMac() failed to make a copy of mac.") + t.Error("GetMac failed to make a copy of mac.") } if msg.GetMac()[0]&0b10000000 != 0 { @@ -582,7 +608,7 @@ func TestMessage_SetMac(t *testing.T) { msg.SetMac(mac) if !bytes.Equal(mac, msg.mac) { - t.Errorf("SetMac() failed to set the MAC."+ + t.Errorf("SetMac failed to set the MAC."+ "\nexpected: %+v\nreceived: %+v", mac, msg.mac) } } @@ -595,7 +621,7 @@ func TestMessage_SetMac_FirstBitError(t *testing.T) { defer func() { if r := recover(); r == nil { - t.Error("SetMac() failed to panic when the first bit of the " + + t.Error("SetMac failed to panic when the first bit of the " + "provided data is not 0.") } }() @@ -610,7 +636,7 @@ func TestMessage_SetMac_LenError(t *testing.T) { defer func() { if r := recover(); r == nil { - t.Error("SetMac() failed to panic when the length of the provided " + + t.Error("SetMac failed to panic when the length of the provided " + "MAC is wrong.") } }() @@ -625,14 +651,14 @@ func TestMessage_GetEphemeralRID(t *testing.T) { copy(msg.ephemeralRID, ephemeralRID) if !bytes.Equal(ephemeralRID, msg.GetEphemeralRID()) { - t.Errorf("GetEphemeralRID() failed to get the correct ephemeralRID."+ + t.Errorf("GetEphemeralRID failed to get the correct ephemeralRID."+ "\nexpected: %+v\nreceived: %+v", ephemeralRID, msg.GetEphemeralRID()) } // Ensure that the data is copied ephemeralRID[2] = 'x' if msg.ephemeralRID[2] == 'x' { - t.Error("GetEphemeralRID() failed to make a copy of ephemeralRID.") + t.Error("GetEphemeralRID failed to make a copy of ephemeralRID.") } } @@ -644,7 +670,7 @@ func TestMessage_SetEphemeralRID(t *testing.T) { // Ensure that the data is copied msg.SetEphemeralRID(ephemeralRID) if !bytes.Equal(ephemeralRID, msg.ephemeralRID) { - t.Errorf("SetEphemeralRID() failed to set the ephemeralRID."+ + t.Errorf("SetEphemeralRID failed to set the ephemeralRID."+ "\nexpected: %+v\nreceived: %+v", ephemeralRID, msg.ephemeralRID) } } @@ -655,7 +681,7 @@ func TestMessage_SetEphemeralRID_LengthError(t *testing.T) { defer func() { if r := recover(); r == nil { - t.Errorf("SetEphemeralRID() failed to panic when the length of " + + t.Errorf("SetEphemeralRID failed to panic when the length of " + "the provided data is incorrect.") } }() @@ -670,14 +696,14 @@ func TestMessage_GetIdentityFP(t *testing.T) { copy(msg.sih, identityFP) if !bytes.Equal(identityFP, msg.GetSIH()) { - t.Errorf("GetSIH() failed to get the correct sih."+ + t.Errorf("GetSIH failed to get the correct sih."+ "\nexpected: %+v\nreceived: %+v", identityFP, msg.GetSIH()) } // Ensure that the data is copied identityFP[2] = 'x' if msg.sih[2] == 'x' { - t.Error("GetSIH() failed to make a copy of sih.") + t.Error("GetSIH failed to make a copy of sih.") } } @@ -688,7 +714,7 @@ func TestMessage_SetIdentityFP(t *testing.T) { msg.SetSIH(identityFP) if !bytes.Equal(identityFP, msg.sih) { - t.Errorf("SetSIH() failed to set the sih."+ + t.Errorf("SetSIH failed to set the sih."+ "\nexpected: %+v\nreceived: %+v", identityFP, msg.sih) } } @@ -699,7 +725,7 @@ func TestMessage_SetIdentityFP_LengthError(t *testing.T) { defer func() { if r := recover(); r == nil { - t.Errorf("SetSIH() failed to panic when the length of " + + t.Errorf("SetSIH failed to panic when the length of " + "the provided data is incorrect.") } }() @@ -707,7 +733,7 @@ func TestMessage_SetIdentityFP_LengthError(t *testing.T) { msg.SetSIH(make([]byte, SIHLen*2)) } -// Tests that digests come out correctly and are diffrent +// Tests that digests come out correctly and are different. func TestMessage_Digest(t *testing.T) { expectedA := "/9SqCYEP3uUixw1ua1D7" @@ -755,27 +781,28 @@ func TestMessage_GoString(t *testing.T) { msg.SetSIH(makeAndFillSlice(SIHLen, 'f')) msg.SetContents(makeAndFillSlice(MinimumPrimeSize*2-AssociatedDataSize-1, 'g')) - expected := "format.Message{keyFP:Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2M=, " + - "MAC:ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQ=, " + - "ephemeralRID:7306357456645743973, " + - "sih:ZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZg==, " + - "contents:\"gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\"}" + expected := + "format.Message{keyFP:Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2M=, " + + "MAC:ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQ=, " + + "ephemeralRID:7306357456645743973, " + + "sih:ZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZg==, " + + "contents:\"gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\"}" if expected != msg.GoString() { - t.Errorf("GoString() returned incorrect string."+ + t.Errorf("GoString returned incorrect string."+ "\nexpected: %s\nreceived: %s", expected, msg.GoString()) } } // Unit test of Message.GoString with an empty Message. func TestMessage_GoString_EmptyMessage(t *testing.T) { + var msg Message - msg := Message{} - - expected := "format.Message{keyFP:<nil>, MAC:<nil>, ephemeralRID:<nil>, sih:<nil>, contents:\"\"}" + expected := "format.Message{keyFP:<nil>, MAC:<nil>, " + + "ephemeralRID:<nil>, sih:<nil>, contents:\"\"}" if expected != msg.GoString() { - t.Errorf("GoString() returned incorrect string."+ + t.Errorf("GoString returned incorrect string."+ "\nexpected: %s\nreceived: %s", expected, msg.GoString()) } } @@ -820,13 +847,13 @@ func TestSetFirstBit(t *testing.T) { b := []byte{0, 0, 0} setFirstBit(b, true) if b[0] != 0b10000000 { - t.Errorf("first bit didnt set") + t.Errorf("first bit did not set") } b = []byte{255, 0, 0} setFirstBit(b, false) if b[0] != 0b01111111 { - t.Errorf("first bit didnt get unset set") + t.Errorf("first bit did not get unset set") } } diff --git a/knownRounds/knownRounds.go b/knownRounds/knownRounds.go index 3f0714e4fcdc9c2569571e44fb119832030179a8..f8b25a115fb14e615a26af33a7addfedcb6e1d0b 100644 --- a/knownRounds/knownRounds.go +++ b/knownRounds/knownRounds.go @@ -5,21 +5,21 @@ // LICENSE file. // //////////////////////////////////////////////////////////////////////////////// -// Tracks which rounds have been checked and which are unchecked using a bit -// stream. +// Package knownRounds tracks which rounds have been checked and which are +// unchecked using a bit stream. package knownRounds import ( "bytes" "encoding/binary" + "math" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" + "gitlab.com/xx_network/primitives/id" - "math" ) -const blockSize = 64 - type RoundCheckFunc func(id id.Round) bool // KnownRounds structure tracks which rounds are known and which are unknown. @@ -30,7 +30,7 @@ type KnownRounds struct { bitStream uint64Buff // Buffer of check/unchecked rounds firstUnchecked id.Round // ID of the first round that us unchecked lastChecked id.Round // ID of the last round that is checked - fuPos int // Bit position of firstUnchecked in bitStream + fuPos int // The bit position of firstUnchecked in bitStream } // DiskKnownRounds structure is used to as an intermediary to marshal and @@ -53,7 +53,8 @@ func NewKnownRound(roundCapacity int) *KnownRounds { // NewFromParts creates a new KnownRounds from the given firstUnchecked, // lastChecked, fuPos, and uint64 buffer. -func NewFromParts(buff []uint64, firstUnchecked, lastChecked id.Round, fuPos int) *KnownRounds { +func NewFromParts( + buff []uint64, firstUnchecked, lastChecked id.Round, fuPos int) *KnownRounds { return &KnownRounds{ bitStream: buff, firstUnchecked: firstUnchecked, @@ -104,7 +105,8 @@ func (kr *KnownRounds) Unmarshal(data []byte) error { buf := bytes.NewBuffer(data) if buf.Len() < 16 { - return errors.Errorf("KnownRounds Unmarshal: size of data %d < %d expected", buf.Len(), 16) + return errors.Errorf("KnownRounds Unmarshal: "+ + "size of data %d < %d expected", buf.Len(), 16) } // Get firstUnchecked and lastChecked and calculate fuPos @@ -146,7 +148,8 @@ type KrChanges map[int]uint64 // lastChecked, fuPos, and a list of changes between the given uint64 buffer and // the current KnownRounds bit stream. An error is returned if the two buffers // are not of the same length. -func (kr *KnownRounds) OutputBuffChanges(old []uint64) (KrChanges, id.Round, id.Round, int, error) { +func (kr *KnownRounds) OutputBuffChanges( + old []uint64) (KrChanges, id.Round, id.Round, int, error) { // Return an error if they are not the same length if len(old) != len(kr.bitStream) { @@ -196,7 +199,7 @@ func (kr *KnownRounds) Check(rid id.Round) { if abs(int(kr.lastChecked-rid))/(len(kr.bitStream)*64) > 0 { jww.FATAL.Panicf("Cannot check a round outside the current scope. " + "Scope is KnownRounds size more rounds than last checked. A call " + - "to Forward() can be used to fix the scope.") + "to Forward can be used to fix the scope.") } kr.check(rid) } @@ -204,7 +207,8 @@ func (kr *KnownRounds) Check(rid id.Round) { func (kr *KnownRounds) ForceCheck(rid id.Round) { if rid < kr.firstUnchecked { return - } else if kr.lastChecked < rid && int(rid-kr.firstUnchecked) > (len(kr.bitStream)*64) { + } else if kr.lastChecked < rid && + int(rid-kr.firstUnchecked) > (len(kr.bitStream)*64) { kr.Forward(rid - id.Round(len(kr.bitStream)*64)) } @@ -286,7 +290,8 @@ func (kr *KnownRounds) Forward(rid id.Round) { // RangeUnchecked runs the passed function over all rounds starting with oldest // unknown and ending with func (kr *KnownRounds) RangeUnchecked(oldestUnknown id.Round, threshold uint, - roundCheck func(id id.Round) bool, maxPickups int) (id.Round, []id.Round, []id.Round) { + roundCheck func(id id.Round) bool, maxPickups int) ( + id.Round, []id.Round, []id.Round) { newestRound := kr.lastChecked @@ -303,19 +308,20 @@ func (kr *KnownRounds) RangeUnchecked(oldestUnknown id.Round, threshold uint, has := make([]id.Round, 0, maxPickups) - // If the oldest unknown round is outside the range we attempting to check, - // then skip checking + // If the oldest unknown round is outside the range we are attempting to + // check, then skip checking if oldestUnknown > kr.lastChecked { - jww.TRACE.Printf("RangeUnchecked: oldestUnknown (%d) > kr.lastChecked (%d)", + jww.TRACE.Printf( + "RangeUnchecked: oldestUnknown (%d) > kr.lastChecked (%d)", oldestUnknown, kr.lastChecked) return oldestUnknown, nil, nil } - // loop through all rounds from the oldest unknown to the last checked round + // Loop through all rounds from the oldest unknown to the last checked round // and check them, if possible for i := oldestUnknown; i <= kr.lastChecked; i++ { - // if the source does not know about the round, set that round as + // If the source does not know about the round, set that round as // unknown and don't check it if !kr.Checked(i) { if i < oldestPossibleEarliestRound { @@ -329,14 +335,14 @@ func (kr *KnownRounds) RangeUnchecked(oldestUnknown id.Round, threshold uint, // check the round hasRound := roundCheck(i) - // if checking is not complete and the round is earlier than the + // If checking is not complete and the round is earlier than the // earliest round, then set it to the earliest round if hasRound { has = append(has, i) - //do not pickup too many messages at once - if len(has)>=maxPickups{ - nextRound := i+1 - if (nextRound)<earliestRound{ + // Do not pick up too many messages at once + if len(has) >= maxPickups { + nextRound := i + 1 + if (nextRound) < earliestRound { earliestRound = nextRound } break @@ -344,7 +350,7 @@ func (kr *KnownRounds) RangeUnchecked(oldestUnknown id.Round, threshold uint, } } - // return the next round + // Return the next round return earliestRound, has, unknown } @@ -396,8 +402,8 @@ func (kr *KnownRounds) RangeUncheckedMaskedRange(mask *KnownRounds, } } -// subSample returns a subsample of the KnownRounds buffer from the start to end -// round and its length. +// subSample returns a sub sample of the KnownRounds buffer from the start to +// end round and its length. func (kr *KnownRounds) subSample(start, end id.Round) (uint64Buff, int) { // Get the number of blocks spanned by the range numBlocks := kr.bitStream.delta(kr.getBitStreamPos(start), @@ -412,7 +418,7 @@ func (kr *KnownRounds) subSample(start, end id.Round) (uint64Buff, int) { copyEnd = kr.lastChecked } - // Create subsample of the buffer + // Create a sub sample of the buffer buff := kr.bitStream.copy(kr.getBitStreamPos(start), kr.getBitStreamPos(copyEnd+1)) @@ -420,9 +426,9 @@ func (kr *KnownRounds) subSample(start, end id.Round) (uint64Buff, int) { return buff.extend(numBlocks), abs(int(end - start)) } -// Truncate returns a subsample of the KnownRounds buffer from last checked. +// Truncate returns a subs ample of the KnownRounds buffer from last checked. func (kr *KnownRounds) Truncate(start id.Round) *KnownRounds { - if start<=kr.firstUnchecked{ + if start <= kr.firstUnchecked { return kr } @@ -449,8 +455,8 @@ func (kr *KnownRounds) getBitStreamPos(rid id.Round) int { } pos := (kr.fuPos + delta) % kr.Len() - if pos <0{ - return kr.Len()+pos + if pos < 0 { + return kr.Len() + pos } return pos diff --git a/knownRounds/knownRounds_test.go b/knownRounds/knownRounds_test.go index 3e439d00999fdbc32eb8a0a48b873c108597ac49..da8c5a56c8258d0fd33e08d64d8d8a613ab2ea98 100644 --- a/knownRounds/knownRounds_test.go +++ b/knownRounds/knownRounds_test.go @@ -10,15 +10,16 @@ package knownRounds import ( "bytes" "fmt" - "gitlab.com/xx_network/primitives/id" "math" "math/rand" "reflect" "strings" "testing" + + "gitlab.com/xx_network/primitives/id" ) -// Tests happy path of NewKnownRound(). +// Tests happy path of NewKnownRound. func TestNewKnownRound(t *testing.T) { expectedKR := &KnownRounds{ bitStream: uint64Buff{0, 0, 0, 0, 0}, @@ -30,8 +31,8 @@ func TestNewKnownRound(t *testing.T) { testKR := NewKnownRound(310) if !reflect.DeepEqual(testKR, expectedKR) { - t.Errorf("NewKnownRound() did not produce the expected KnownRounds."+ - "\n\texpected: %v\n\treceived: %v", + t.Errorf("NewKnownRound did not produce the expected KnownRounds."+ + "\nexpected: %v\nreceived: %v", expectedKR, testKR) } } @@ -45,15 +46,16 @@ func TestNewFromParts(t *testing.T) { fuPos: 75, } - received := NewFromParts(expected.bitStream, expected.firstUnchecked, expected.lastChecked, expected.fuPos) + received := NewFromParts(expected.bitStream, expected.firstUnchecked, + expected.lastChecked, expected.fuPos) if !reflect.DeepEqual(expected, received) { - t.Errorf("NewFromParts() did not return the expected KnownRounds."+ + t.Errorf("NewFromParts did not return the expected KnownRounds."+ "\nexpected: %v\nreceived: %v", expected, received) } } -// Tests happy path of KnownRounds.Marshal(). +// Tests happy path of KnownRounds.Marshal. func TestKnownRounds_Marshal_Unmarshal(t *testing.T) { testKR := &KnownRounds{ bitStream: uint64Buff{0, math.MaxUint64, 0, math.MaxUint64, 0}, @@ -67,7 +69,7 @@ func TestKnownRounds_Marshal_Unmarshal(t *testing.T) { newKR := &KnownRounds{} err := newKR.Unmarshal(data) if err != nil { - t.Errorf("Unmarshal() produced an error: %+v", err) + t.Errorf("Unmarshal produced an error: %+v", err) } if !reflect.DeepEqual(testKR, newKR) { @@ -76,7 +78,7 @@ func TestKnownRounds_Marshal_Unmarshal(t *testing.T) { } } -// Tests happy path of KnownRounds.Marshal(). +// Tests happy path of KnownRounds.Marshal. func TestKnownRounds_Marshal(t *testing.T) { testKR := &KnownRounds{ bitStream: uint64Buff{0, math.MaxUint64, 0, math.MaxUint64, 0}, @@ -90,14 +92,14 @@ func TestKnownRounds_Marshal(t *testing.T) { data := testKR.Marshal() - if !bytes.Equal([]byte(expectedData), data) { - t.Errorf("Marshal() produced incorrect data."+ - "\n\texpected: %+v\n\treceived: %+v", expectedData, data) + if !bytes.Equal(expectedData, data) { + t.Errorf("Marshal produced incorrect data."+ + "\nexpected: %+v\nreceived: %+v", expectedData, data) } } -// Tests happy path of KnownRounds.Unmarshal(). +// Tests happy path of KnownRounds.Unmarshal. func TestKnownRounds_Unmarshal(t *testing.T) { testKR := &KnownRounds{ bitStream: uint64Buff{0, math.MaxUint64, 0, 0, 0}, @@ -111,17 +113,17 @@ func TestKnownRounds_Unmarshal(t *testing.T) { newKR := NewKnownRound(310) err := newKR.Unmarshal(data) if err != nil { - t.Errorf("Unmarshal() produced an unexpected error."+ - "\n\texpected: %+v\n\treceived: %+v", nil, err) + t.Errorf("Unmarshal produced an unexpected error."+ + "\nexpected: %+v\nreceived: %+v", nil, err) } if !reflect.DeepEqual(newKR, testKR) { - t.Errorf("Unmarshal() produced an incorrect KnownRounds from the data."+ - "\n\texpected: %v\n\treceived: %v", testKR, newKR) + t.Errorf("Unmarshal produced an incorrect KnownRounds from the data."+ + "\nexpected: %v\nreceived: %v", testKR, newKR) } } -// Tests that KnownRounds.Unmarshal() errors when the new bit stream is too +// Tests that KnownRounds.Unmarshal errors when the new bit stream is too // small. func TestKnownRounds_Unmarshal_SizeError(t *testing.T) { testKR := &KnownRounds{ @@ -136,78 +138,76 @@ func TestKnownRounds_Unmarshal_SizeError(t *testing.T) { newKR := NewKnownRound(1) err := newKR.Unmarshal(data) if err == nil { - t.Error("Unmarshal() did not produce an error when the size of new " + + t.Error("Unmarshal did not produce an error when the size of new " + "KnownRound bit stream is too small.") } } -// Tests that KnownRounds.Unmarshal() errors when given invalid JSON data. +// Tests that KnownRounds.Unmarshal errors when given invalid JSON data. func TestKnownRounds_Unmarshal_JsonError(t *testing.T) { newKR := NewKnownRound(1) err := newKR.Unmarshal([]byte("hello")) if err == nil { - t.Error("Unmarshal() did not produce an error on invalid JSON data.") + t.Error("Unmarshal did not produce an error on invalid JSON data.") } } // Happy path. func TestKnownRounds_OutputBuffChanges(t *testing.T) { // Generate test round IDs and expected buffers + const max = math.MaxUint64 testData := []struct { current KnownRounds old []uint64 changes KrChanges - }{ - { - current: KnownRounds{uint64Buff{}, 75, 320, 75}, - old: []uint64{}, - changes: KrChanges{}, - }, - { - current: KnownRounds{uint64Buff{0, math.MaxUint64, 0, math.MaxUint64, 0}, 75, 320, 75}, - old: []uint64{0, math.MaxUint64, 0, math.MaxUint64, 0}, - changes: KrChanges{}, - }, - { - current: KnownRounds{uint64Buff{0, math.MaxUint64, 0, math.MaxUint64, 0}, 75, 320, 75}, - old: []uint64{0, math.MaxUint64, 0, math.MaxUint64, 0}, - changes: KrChanges{}, - }, - { - current: KnownRounds{uint64Buff{1, math.MaxUint64, 0, math.MaxUint64, 0}, 75, 320, 75}, - old: []uint64{0, math.MaxUint64, 0, math.MaxUint64, 0}, - changes: KrChanges{0: 1}, - }, - { - current: KnownRounds{uint64Buff{0, math.MaxUint64, 0, math.MaxUint64, 0}, 75, 320, 75}, - old: []uint64{math.MaxUint64, 0, math.MaxUint64, 0, math.MaxUint64}, - changes: KrChanges{0: 0, 1: math.MaxUint64, 2: 0, 3: math.MaxUint64, 4: 0}, - }, - } + }{{ + current: KnownRounds{uint64Buff{}, 75, 320, 75}, + old: []uint64{}, + changes: KrChanges{}, + }, { + current: KnownRounds{uint64Buff{0, max, 0, max, 0}, 75, 320, 75}, + old: []uint64{0, max, 0, max, 0}, + changes: KrChanges{}, + }, { + current: KnownRounds{uint64Buff{0, max, 0, max, 0}, 75, 320, 75}, + old: []uint64{0, max, 0, max, 0}, + changes: KrChanges{}, + }, { + current: KnownRounds{uint64Buff{1, max, 0, max, 0}, 75, 320, 75}, + old: []uint64{0, max, 0, max, 0}, + changes: KrChanges{0: 1}, + }, { + current: KnownRounds{uint64Buff{0, max, 0, max, 0}, 75, 320, 75}, + old: []uint64{max, 0, max, 0, max}, + changes: KrChanges{0: 0, 1: max, 2: 0, 3: max, 4: 0}, + }} for i, data := range testData { - changes, firstUnchecked, lastChecked, fuPos, err := data.current.OutputBuffChanges(data.old) + changes, firstUnchecked, lastChecked, fuPos, err := + data.current.OutputBuffChanges(data.old) if err != nil { - t.Errorf("OutputBuffChanges() produced an error (%d): %+v", i, err) + t.Errorf("OutputBuffChanges produced an error (%d): %+v", i, err) } if data.current.firstUnchecked != firstUnchecked { - t.Errorf("OutputBuffChanges() returned incorrect firstUnchecked (%d)."+ - "\nexpected: %d\nreceived: %d", i, data.current.firstUnchecked, firstUnchecked) + t.Errorf("OutputBuffChanges returned incorrect firstUnchecked (%d)."+ + "\nexpected: %d\nreceived: %d", + i, data.current.firstUnchecked, firstUnchecked) } if data.current.lastChecked != lastChecked { - t.Errorf("OutputBuffChanges() returned incorrect lastChecked (%d)."+ - "\nexpected: %d\nreceived: %d", i, data.current.lastChecked, lastChecked) + t.Errorf("OutputBuffChanges returned incorrect lastChecked (%d)."+ + "\nexpected: %d\nreceived: %d", + i, data.current.lastChecked, lastChecked) } if data.current.fuPos != fuPos { - t.Errorf("OutputBuffChanges() returned incorrect fuPos (%d)."+ + t.Errorf("OutputBuffChanges returned incorrect fuPos (%d)."+ "\nexpected: %d\nreceived: %d", i, data.current.fuPos, fuPos) } if !reflect.DeepEqual(data.changes, changes) { - t.Errorf("OutputBuffChanges() returned incorrect changes (%d)."+ + t.Errorf("OutputBuffChanges returned incorrect changes (%d)."+ "\nexpected: %v\nreceived: %v", i, data.changes, changes) } } @@ -216,25 +216,25 @@ func TestKnownRounds_OutputBuffChanges(t *testing.T) { // Error path: buffers are not the same length. func TestKnownRounds_OutputBuffChanges_IncorrectLengthError(t *testing.T) { // Generate test round IDs and expected buffers + const max = math.MaxUint64 testData := []struct { current KnownRounds old []uint64 - }{ - { - current: KnownRounds{uint64Buff{0, math.MaxUint64, 0, math.MaxUint64, 0}, 75, 320, 75}, - old: []uint64{0, math.MaxUint64, 0}, - }, - { - current: KnownRounds{uint64Buff{0, math.MaxUint64, 0}, 75, 320, 75}, - old: []uint64{0, math.MaxUint64, 0, math.MaxUint64, 0}, - }, - } - + }{{ + current: KnownRounds{uint64Buff{0, max, 0, max, 0}, 75, 320, 75}, + old: []uint64{0, max, 0}, + }, { + current: KnownRounds{uint64Buff{0, max, 0}, 75, 320, 75}, + old: []uint64{0, max, 0, max, 0}, + }} + + expectedErr := "not the same as length of the current buffer" for i, data := range testData { _, _, _, _, err := data.current.OutputBuffChanges(data.old) - if err == nil || !strings.Contains(err.Error(), "not the same as length of the current buffer") { - t.Errorf("OutputBuffChanges() did not produce an error when the "+ - "buffers are the wrong lengths (%d): %+v", i, err) + if err == nil || !strings.Contains(err.Error(), expectedErr) { + t.Errorf("OutputBuffChanges did not produce the expected error "+ + "when the buffers are the wrong lengths (%d)."+ + "\nexpected: %s\nreceived: %+v", i, expectedErr, err) } } } @@ -299,7 +299,7 @@ func TestKnownRounds_GetBitStream(t *testing.T) { } } -// Tests happy path of KnownRounds.Check(). +// Tests happy path of KnownRounds.Check. func TestKnownRounds_Check(t *testing.T) { // Generate test round IDs and expected buffers testData := []struct { @@ -324,8 +324,8 @@ func TestKnownRounds_Check(t *testing.T) { kr.Check(data.rid) if !reflect.DeepEqual(kr.bitStream, data.buff) { - t.Errorf("Incorrect resulting buffer after checking round ID %d (round %d)."+ - "\n\texpected: %064b\n\treceived: %064b"+ + t.Errorf("Incorrect resulting buffer after checking round ID %d (%d)."+ + "\nexpected: %064b\nreceived: %064b"+ "\n\033[38;5;59m 0123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123"+ "\n\u001B[38;5;59m 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8"+ "\n\u001B[38;5;59m 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3", @@ -333,13 +333,14 @@ func TestKnownRounds_Check(t *testing.T) { } if kr.lastChecked != data.expectedLastChecked { - t.Errorf("Check() did not modify the the lastChecked round correctly for round ID %d (round %d)."+ - "\n\texpected: %d\n\treceived: %d", data.rid, i, data.expectedLastChecked, kr.lastChecked) + t.Errorf("Check did not modify the lastChecked round correctly "+ + "for round ID %d (%d).\nexpected: %d\nreceived: %d", + data.rid, i, data.expectedLastChecked, kr.lastChecked) } } } -// Tests happy path of KnownRounds.Check() with a new KnownRounds. +// Tests happy path of KnownRounds.Check with a new KnownRounds. func TestKnownRounds_Check_NewKR(t *testing.T) { // Generate test round IDs and expected buffers testData := []struct { @@ -356,19 +357,20 @@ func TestKnownRounds_Check_NewKR(t *testing.T) { kr := NewKnownRound(310) kr.Check(data.rid) if !reflect.DeepEqual(kr.bitStream, data.buff) { - t.Errorf("Resulting buffer after checking round ID %d (round %d)."+ - "\n\texpected: %064b\n\treceived: %064b", + t.Errorf("Resulting buffer after checking round ID %d (%d)."+ + "\nexpected: %064b\nreceived: %064b", data.rid, i, data.buff, kr.bitStream) } if kr.lastChecked != data.expectedLastChecked { - t.Errorf("Check() did not modify the the lastChecked round correctly for round ID %d (round %d)."+ - "\n\texpected: %d\n\treceived: %d", data.rid, i, data.expectedLastChecked, kr.lastChecked) + t.Errorf("Check did not modify the lastChecked round correctly "+ + "for round ID %d (%d).\nexpected: %d\nreceived: %d", + data.rid, i, data.expectedLastChecked, kr.lastChecked) } } } -// Happy path of KnownRounds.Checked(). +// Happy path of KnownRounds.Checked. func TestKnownRounds_Checked(t *testing.T) { // Generate test positions and expected value testData := []struct { @@ -395,13 +397,13 @@ func TestKnownRounds_Checked(t *testing.T) { for i, data := range testData { value := kr.Checked(data.rid) if value != data.value { - t.Errorf("Checked() returned incorrect value for round ID %d (round %d)."+ - "\n\texpected: %v\n\treceived: %v", data.rid, i, data.value, value) + t.Errorf("Checked returned incorrect value for round ID %d (%d)."+ + "\nexpected: %v\nreceived: %v", data.rid, i, data.value, value) } } } -// Happy path of KnownRounds.Checked() with a new KnownRounds. +// Happy path of KnownRounds.Checked with a new KnownRounds. func TestKnownRounds_Checked_NewKR(t *testing.T) { // Generate test positions and expected value testData := []struct { @@ -418,13 +420,13 @@ func TestKnownRounds_Checked_NewKR(t *testing.T) { kr := NewKnownRound(5) value := kr.Checked(data.rid) if value != data.value { - t.Errorf("Checked() returned incorrect value for round ID %d (round %d)."+ - "\n\texpected: %v\n\treceived: %v", data.rid, i, data.value, value) + t.Errorf("Checked returned incorrect value for round ID %d (%d)."+ + "\nexpected: %v\nreceived: %v", data.rid, i, data.value, value) } } } -// Tests happy path of KnownRounds.Forward(). +// Tests happy path of KnownRounds.Forward. func TestKnownRounds_Forward(t *testing.T) { // Generate test round IDs and expected buffers testData := []struct { @@ -449,21 +451,24 @@ func TestKnownRounds_Forward(t *testing.T) { kr.bitStream = uint64Buff{0, math.MaxUint64, 0, math.MaxUint64, 0} kr.Forward(data.rid) if kr.firstUnchecked != data.expectedFirstChecked { - t.Errorf("Forward() did not modify the the firstUnchecked round correctly for round ID %d (round %d)."+ - "\n\texpected: %d\n\treceived: %d", data.rid, i, data.expectedFirstChecked, kr.firstUnchecked) + t.Errorf("Forward did not modify the firstUnchecked round "+ + "correctly for round ID %d (%d).\nexpected: %d\nreceived: %d", + data.rid, i, data.expectedFirstChecked, kr.firstUnchecked) } if kr.lastChecked != data.expectedLastChecked { - t.Errorf("Forward() did not modify the the lastChecked round correctly for round ID %d (round %d)."+ - "\n\texpected: %d\n\treceived: %d", data.rid, i, data.expectedLastChecked, kr.lastChecked) + t.Errorf("Forward did not modify the lastChecked round correctly "+ + "or round ID %d (%d).\nexpected: %d\nreceived: %d", + data.rid, i, data.expectedLastChecked, kr.lastChecked) } if kr.fuPos != data.expectedFusPos { - t.Errorf("Forward() did not modify the the fuPos round correctly for round ID %d (round %d)."+ - "\n\texpected: %d\n\treceived: %d", data.rid, i, data.expectedFusPos, kr.fuPos) + t.Errorf("Forward did not modify the fuPos round correctly for "+ + "round ID %d (%d).\nexpected: %d\nreceived: %d", + data.rid, i, data.expectedFusPos, kr.fuPos) } } } -// Tests happy path of KnownRounds.Forward() with a new KnownRounds. +// Tests happy path of KnownRounds.Forward with a new KnownRounds. func TestKnownRounds_Forward_NewKR(t *testing.T) { // Generate test round IDs and expected buffers testData := []struct { @@ -480,21 +485,24 @@ func TestKnownRounds_Forward_NewKR(t *testing.T) { kr := NewKnownRound(5) kr.Forward(data.rid) if kr.firstUnchecked != data.expectedFirstUnchecked { - t.Errorf("Forward() did not modify the the firstUnchecked round correctly for round ID %d (round %d)."+ - "\n\texpected: %d\n\treceived: %d", data.rid, i, data.expectedFirstUnchecked, kr.firstUnchecked) + t.Errorf("Forward did not modify the firstUnchecked round "+ + "correctly for round ID %d (%d).\nexpected: %d\nreceived: %d", + data.rid, i, data.expectedFirstUnchecked, kr.firstUnchecked) } if kr.lastChecked != data.expectedLastChecked { - t.Errorf("Forward() did not modify the the lastChecked round correctly for round ID %d (round %d)."+ - "\n\texpected: %d\n\treceived: %d", data.rid, i, data.expectedLastChecked, kr.lastChecked) + t.Errorf("Forward did not modify the lastChecked round correctly "+ + "for round ID %d (%d).\nexpected: %d\nreceived: %d", + data.rid, i, data.expectedLastChecked, kr.lastChecked) } if kr.fuPos != data.expectedFusPos { - t.Errorf("Forward() did not modify the the fuPos round correctly for round ID %d (round %d)."+ - "\n\texpected: %d\n\treceived: %d", data.rid, i, data.expectedFusPos, kr.fuPos) + t.Errorf("Forward did not modify the fuPos round correctly for "+ + "round ID %d (%d).\nexpected: %d\nreceived: %d", + data.rid, i, data.expectedFusPos, kr.fuPos) } } } -// Test happy path of KnownRounds.RangeUnchecked(). +// Test happy path of KnownRounds.RangeUnchecked. func TestKnownRounds_RangeUnchecked(t *testing.T) { // Generate test round IDs and expected buffers testData := []struct { @@ -527,29 +535,30 @@ func TestKnownRounds_RangeUnchecked(t *testing.T) { fuPos: 75, } - earliestRound, has, unknown := kr.RangeUnchecked(data.oldestUnknown, 50, roundCheck, 1000) + earliestRound, has, unknown := + kr.RangeUnchecked(data.oldestUnknown, 50, roundCheck, 1000) if earliestRound != data.expected { - t.Errorf("RangeUnchecked() did not return the correct round (%d)."+ - "\n\texpected: %d\n\treceived: %d", + t.Errorf("RangeUnchecked did not return the correct round (%d)."+ + "\nexpected: %d\nreceived: %d", i, data.expected, earliestRound) } if len(data.has) != len(has) { - t.Errorf("RangeUnchecked() did not return the correct has list (%d)."+ - "\n\texpected: %v\n\treceived: %v", + t.Errorf("RangeUnchecked did not return the correct has list (%d)."+ + "\nexpected: %v\nreceived: %v", i, data.has, has) } if !reflect.DeepEqual(data.unknown, unknown) { - t.Errorf("RangeUnchecked() did not return the correct unknown list (%d)."+ - "\n\texpected: %v\n\treceived: %v", + t.Errorf("RangeUnchecked did not return the correct unknown list (%d)."+ + "\nexpected: %v\nreceived: %v", i, data.unknown, unknown) } } } -// Test happy path of KnownRounds.RangeUnchecked() with a new KnownRounds. +// Test happy path of KnownRounds.RangeUnchecked with a new KnownRounds. func TestKnownRounds_RangeUnchecked_NewKR(t *testing.T) { // Generate test round IDs and expected buffers testData := []struct { @@ -571,29 +580,30 @@ func TestKnownRounds_RangeUnchecked_NewKR(t *testing.T) { for i, data := range testData { kr := NewKnownRound(310) - earliestRound, has, unknown := kr.RangeUnchecked(data.oldestUnknown, 50, roundCheck, 1000) + earliestRound, has, unknown := + kr.RangeUnchecked(data.oldestUnknown, 50, roundCheck, 1000) if earliestRound != data.expected { - t.Errorf("RangeUnchecked() did not return the correct round (%d)."+ - "\n\texpected: %d\n\treceived: %d", + t.Errorf("RangeUnchecked did not return the correct round (%d)."+ + "\nexpected: %d\nreceived: %d", i, data.expected, earliestRound) } if !reflect.DeepEqual(data.has, has) { - t.Errorf("RangeUnchecked() did not return the correct has list (%d)."+ - "\n\texpected: %v\n\treceived: %v", + t.Errorf("RangeUnchecked did not return the correct has list (%d)."+ + "\nexpected: %v\nreceived: %v", i, data.has, has) } if !reflect.DeepEqual(data.unknown, unknown) { - t.Errorf("RangeUnchecked() did not return the correct unknown list (%d)."+ - "\n\texpected: %v\n\treceived: %v", + t.Errorf("RangeUnchecked did not return the correct unknown list (%d)."+ + "\nexpected: %v\nreceived: %v", i, data.unknown, unknown) } } } -// Test happy path of KnownRounds.RangeUncheckedMasked(). +// Test happy path of KnownRounds.RangeUncheckedMasked. func TestKnownRounds_RangeUncheckedMasked(t *testing.T) { expectedKR := KnownRounds{ bitStream: uint64Buff{42949672960, 18446744073709551615, 0, 18446744073709551615, 0}, @@ -620,13 +630,13 @@ func TestKnownRounds_RangeUncheckedMasked(t *testing.T) { kr.RangeUncheckedMasked(kr2, roundCheck, 5) if !reflect.DeepEqual(expectedKR, kr) { - t.Errorf("RangeUncheckedMasked() incorrectl modified KnownRounds."+ - "\n\texpected: %+v\n\treceived: %+v", expectedKR, kr) + t.Errorf("RangeUncheckedMasked incorrectl modified KnownRounds."+ + "\nexpected: %+v\nreceived: %+v", expectedKR, kr) } fmt.Printf("kr.bitStream: %+v\n", kr.bitStream) } -// Happy path of getBitStreamPos(). +// Happy path of getBitStreamPos. func TestKnownRounds_getBitStreamPos(t *testing.T) { // Generate test round IDs and their expected positions testData := []struct { @@ -652,14 +662,15 @@ func TestKnownRounds_getBitStreamPos(t *testing.T) { for i, data := range testData { pos := kr.getBitStreamPos(data.rid) if pos != data.pos { - t.Errorf("getBitStreamPos() returned incorrect position for round ID %d (round %d)."+ - "\n\texpected: %v\n\treceived: %v", data.rid, i, data.pos, pos) + t.Errorf("getBitStreamPos returned incorrect position for round "+ + "ID %d (%d).\nexpected: %v\nreceived: %v", + data.rid, i, data.pos, pos) } } } /* -// Test happy path of KnownRounds.RangeUncheckedMasked(). +// Test happy path of KnownRounds.RangeUncheckedMasked. func TestKnownRounds_RangeUncheckedMasked_2(t *testing.T) { expectedKR := KnownRounds{ bitStream: make(uint64Buff, 245), @@ -689,13 +700,13 @@ func TestKnownRounds_RangeUncheckedMasked_2(t *testing.T) { kr.RangeUncheckedMasked(mask, roundCheck, 5) if !reflect.DeepEqual(expectedKR, kr) { - t.Errorf("RangeUncheckedMasked() incorrect modified KnownRounds."+ - "\n\texpected: %+v\n\treceived: %+v", expectedKR, kr) + t.Errorf("RangeUncheckedMasked incorrect modified KnownRounds."+ + "\nexpected: %+v\nreceived: %+v", expectedKR, kr) } fmt.Printf("kr.bitStream: %064b\n", kr.bitStream) }*/ -// // Test happy path of KnownRounds.RangeUncheckedMasked(). +// // Test happy path of KnownRounds.RangeUncheckedMasked. // func TestKnownRounds_RangeUncheckedMasked_3(t *testing.T) { // expectedKR := KnownRounds{ // bitStream: make(uint64Buff, 245), @@ -725,14 +736,14 @@ func TestKnownRounds_RangeUncheckedMasked_2(t *testing.T) { // // kr.RangeUncheckedMasked(mask, roundCheck, 5) // if !reflect.DeepEqual(expectedKR, kr) { -// t.Errorf("RangeUncheckedMasked() incorrect modified KnownRounds."+ -// "\n\texpected: %064b\n\treceived: %064b", expectedKR, kr) +// t.Errorf("RangeUncheckedMasked incorrect modified KnownRounds."+ +// "\nexpected: %064b\nreceived: %064b", expectedKR, kr) // } // fmt.Printf("kr.bitStream: %064b\n", kr.bitStream) // } // -// // Tests that KnownRounds.subSample() produces the correct buffer for a new +// // Tests that KnownRounds.subSample produces the correct buffer for a new // // KnownRounds. // func TestKnownRounds_subSample(t *testing.T) { // kr := NewKnownRound(1) @@ -742,17 +753,17 @@ func TestKnownRounds_RangeUncheckedMasked_2(t *testing.T) { // // u64b, length := kr.subSample(5, 189) // if !reflect.DeepEqual(expectedU64b, u64b) { -// t.Errorf("subSample() returned incorrect buffer." + -// "\n\texpected: %064b\n\treceived: %064b", expectedU64b, u64b) +// t.Errorf("subSample returned incorrect buffer." + +// "\nexpected: %064b\nreceived: %064b", expectedU64b, u64b) // } // // if len(expectedU64b) != length { -// t.Errorf("subSample() returned incorrect buffer length." + -// "\n\texpected: %d\n\treceived: %d", len(expectedU64b), length) +// t.Errorf("subSample returned incorrect buffer length." + +// "\nexpected: %d\nreceived: %d", len(expectedU64b), length) // } // } // -// // Tests that KnownRounds.subSample() produces the correct buffer for a new +// // Tests that KnownRounds.subSample produces the correct buffer for a new // // KnownRounds. // func TestKnownRounds_subSample2(t *testing.T) { // kr := &KnownRounds{ @@ -775,13 +786,13 @@ func TestKnownRounds_RangeUncheckedMasked_2(t *testing.T) { // // u64b, length := kr.subSample(mask.firstUnchecked, mask.lastChecked) // if !reflect.DeepEqual(expectedU64b, u64b) { -// t.Errorf("subSample() returned incorrect buffer." + -// "\n\texpected: %064b\n\treceived: %064b", expectedU64b, u64b) +// t.Errorf("subSample returned incorrect buffer." + +// "\nexpected: %064b\nreceived: %064b", expectedU64b, u64b) // } // // if len(expectedU64b) != length { -// t.Errorf("subSample() returned incorrect buffer length." + -// "\n\texpected: %d\n\treceived: %d", len(expectedU64b), length) +// t.Errorf("subSample returned incorrect buffer length." + +// "\nexpected: %d\nreceived: %d", len(expectedU64b), length) // } // } // @@ -883,7 +894,8 @@ func TestKnownRounds_Database_Simulation(t *testing.T) { t.Logf("%d %v", i, kr) // Save changes - changes, saved.firstUnchecked, saved.lastChecked, saved.fuPos, err = kr.OutputBuffChanges(saved.bitStream) + changes, saved.firstUnchecked, saved.lastChecked, saved.fuPos, err = + kr.OutputBuffChanges(saved.bitStream) if err != nil { t.Errorf("Failed to output changed (%d): %+v", i, err) } @@ -894,7 +906,8 @@ func TestKnownRounds_Database_Simulation(t *testing.T) { } // Reconstructs the KnownRounds from the saved data - newKR := NewFromParts(saved.bitStream, saved.firstUnchecked, saved.lastChecked, saved.fuPos) + newKR := NewFromParts(saved.bitStream, + saved.firstUnchecked, saved.lastChecked, saved.fuPos) // Compare the original KnownRounds to the reconstructed KnownRounds if !reflect.DeepEqual(kr, newKR) { @@ -921,19 +934,13 @@ func makeRange(min, max int) []id.Round { } func TestKnownRounds_Len(t *testing.T) { - // decodeString, err := base64.StdEncoding.DecodeString("XTLOAAAAAACXRc4AAAAAAAIBAAID+Vf/AXdv/wi//yh//yP9/w/+/wX7/x79/yl//wXf/wl//xK//zz9/yT9/xjv/zt//8f+/wf2/wH+tlkABQ==") - // if err != nil { - // t.Fatalf("Failed to decode: %+v", err) - // } kr := NewKnownRound(0) - decodeString := []byte{174, 69, 206, 0, 0, 0, 0, 0, 150, 73, 206, 0, 0, 0, 0, 0, 2, 1, 0, 136} + decodeString := []byte{ + 174, 69, 206, 0, 0, 0, 0, 0, 150, 73, 206, 0, 0, 0, 0, 0, 2, 1, 0, 136} err := kr.Unmarshal(decodeString) if err != nil { t.Errorf("Failed to unmarshal: %+v", err) } - - t.Logf("%+v", kr) - t.Logf("%064b", kr.bitStream) } diff --git a/knownRounds/uint64Buff.go b/knownRounds/uint64Buff.go index 6507cd10878186cd5b9f5d3ce6c4c8fe371ac63e..c3f7251209fc96342fdd3f4102c9de9cf1ae620a 100644 --- a/knownRounds/uint64Buff.go +++ b/knownRounds/uint64Buff.go @@ -10,10 +10,11 @@ package knownRounds import ( "bytes" "encoding/binary" - "github.com/pkg/errors" - jww "github.com/spf13/jwalterweatherman" "io" "math" + + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" ) const ( @@ -108,7 +109,7 @@ func (u64b uint64Buff) copy(start, end int) uint64Buff { // If u64bStart is greater than u64bEnd, then the selection is inverted. // // More info on material implication: -// https://en.wikipedia.org/wiki/Material_conditional +// https://en.wikipedia.org/wiki/Material_conditional func (u64b uint64Buff) implies(mask uint64Buff) uint64Buff { if len(u64b) != len(mask) { jww.FATAL.Panicf("Cannot imply two buffers of different lengths "+ diff --git a/knownRounds/uint64Buff_test.go b/knownRounds/uint64Buff_test.go index c208066342102704a3e229550f306ec520a380d9..464a2d910f2a34c3781efb56759849d459860e6b 100644 --- a/knownRounds/uint64Buff_test.go +++ b/knownRounds/uint64Buff_test.go @@ -15,7 +15,7 @@ import ( "testing" ) -// Happy path of get(). +// Happy path of uint64Buff.get. func Test_uint64Buff_get(t *testing.T) { // Generate test positions and expected value testData := []struct { @@ -32,13 +32,15 @@ func Test_uint64Buff_get(t *testing.T) { for i, data := range testData { value := u64b.get(data.pos) if value != data.value { - t.Errorf("get() returned incorrect value for bit at position %d (round %d)."+ - "\n\texpected: %v\n\treceived: %v", data.pos, i, data.value, value) + t.Errorf( + "get returned incorrect value for the bit at position %d (%d)."+ + "\nexpected: %v\nreceived: %v", + data.pos, i, data.value, value) } } } -// Happy path of set(). +// Happy path of uint64Buff.set. func Test_uint64Buff_set(t *testing.T) { // Generate test positions and expected buffers testData := []struct { @@ -55,7 +57,7 @@ func Test_uint64Buff_set(t *testing.T) { u64b := uint64Buff{0, ones, 0, ones, 0} u64b.set(data.pos) if !reflect.DeepEqual(u64b, data.buff) { - t.Errorf("Resulting buffer after setting bit at position %d (round %d)."+ + t.Errorf("Resulting buffer after setting bit at position %d (%d)."+ "\n\texpected: %064b\n\treceived: %064b"+ "\n\033[38;5;59m 0123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123"+ "\n\u001B[38;5;59m 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8"+ @@ -65,7 +67,7 @@ func Test_uint64Buff_set(t *testing.T) { } } -// Tests that clearRange() clears the correct bits. +// Tests that uint64Buff.clearRange clears the correct bits. func Test_uint64Buff_clearRange(t *testing.T) { // Generate test ranges and expected buffer testData := []struct { @@ -93,7 +95,7 @@ func Test_uint64Buff_clearRange(t *testing.T) { u64b := uint64Buff{ones, ones, ones, ones, ones} u64b.clearRange(data.start, data.end) if !reflect.DeepEqual(u64b, data.buff) { - t.Errorf("Resulting buffer after clearing range %d to %d is incorrect (round %d)."+ + t.Errorf("Resulting buffer after clearing range %d to %d is incorrect (%d)."+ "\n\texpected: %064b\n\treceived: %064b"+ "\n\033[38;5;59m 0123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789 0123456789012345678901234567890123456789012345678901234567890123"+ "\n\u001B[38;5;59m 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8"+ @@ -103,7 +105,7 @@ func Test_uint64Buff_clearRange(t *testing.T) { } } -// Tests that copy() copies the correct bits. +// Tests that uint64Buff.copy copies the correct bits. func Test_uint64Buff_copy(t *testing.T) { // Generate test ranges and expected copied value @@ -122,47 +124,48 @@ func Test_uint64Buff_copy(t *testing.T) { for j := 0; j < lenBuf; j++ { buf[j] = prng.Uint64() } - subsampleStart, subsampleEnd := 0, 0 - for subsampleEnd-subsampleStart == 0 { - subsampleStart = int(prng.Uint64() % uint64(lenBuf*64)) - subsampleDelta := int(prng.Uint64() % (uint64(lenBuf*64 - subsampleStart))) - subsampleEnd = subsampleStart + subsampleDelta + subSampleStart, subSampleEnd := 0, 0 + for subSampleEnd-subSampleStart == 0 { + subSampleStart = int(prng.Uint64() % uint64(lenBuf*64)) + subSampleDelta := int(prng.Uint64() % (uint64(lenBuf*64 - subSampleStart))) + subSampleEnd = subSampleStart + subSampleDelta } - // delta := subsampleEnd-subsampleStart + copied := buf.copy(subSampleStart, subSampleEnd) - copied := buf.copy(subsampleStart, subsampleEnd) - - // check edge regions - for j := 0; j < subsampleStart%64; j++ { + // Check edge regions + for j := 0; j < subSampleStart%64; j++ { if !copied.get(j) { - t.Errorf("Round %v position %v < substampeStart %v(%v) is "+ - "false when should be true", i, j, subsampleStart, subsampleStart%64) + t.Errorf("Round %d position %d < substampeStart %d(%d) is "+ + "false when should be true", + i, j, subSampleStart, subSampleStart%64) } } - // dont test the edge case where the last element is the last in the + + // Do not test the edge case where the last element is the last in the // last block because nothing will have been filled in to test - if (subsampleEnd/64 - subsampleStart/64) != len(copied) { - for j := subsampleEnd % 64; j < 64; j++ { + if (subSampleEnd/64 - subSampleStart/64) != len(copied) { + for j := subSampleEnd % 64; j < 64; j++ { if copied.get(((len(copied) - 1) * 64) + j) { - t.Errorf("Round %v position %v (%v) > substampeEnd %v(%v) is "+ - "true when should be false", i, ((len(copied)-1)*64)+j, j, - subsampleEnd, subsampleEnd%64) + t.Errorf("Round %d position %d (%d) > substampeEnd %d(%d) "+ + "is true when should be false", i, + ((len(copied)-1)*64)+j, j, subSampleEnd, subSampleEnd%64) } } } - // check all in between bits are correct - for j := subsampleStart % 64; j < subsampleEnd-subsampleStart; j++ { - if copied.get(j) != buf.get(j+(subsampleStart/64)*64) { - t.Errorf("Round %v copy position %v not the same as original"+ - " position %v (%v + %v)", i, j%64, (j+subsampleStart)%64, - subsampleStart, j) + + // Check all in between bits are correct + for j := subSampleStart % 64; j < subSampleEnd-subSampleStart; j++ { + if copied.get(j) != buf.get(j+(subSampleStart/64)*64) { + t.Errorf("Round %d copy position %d not the same as original "+ + "position %d (%d + %d)", i, j%64, (j+subSampleStart)%64, + subSampleStart, j) } } } } -// Happy path of convertLoc(). +// Happy path of uint64Buff.convertLoc. func Test_uint64Buff_convertLoc(t *testing.T) { // Generate test position and expected block index and offset testData := []struct { @@ -184,15 +187,15 @@ func Test_uint64Buff_convertLoc(t *testing.T) { for i, data := range testData { bin, offset := u64b.convertLoc(data.pos) if bin != data.bin || offset != data.offset { - t.Errorf("convert() returned incorrect values for position %d "+ - "(round %d).\n\texpected: bin: %3d offset: %3d"+ - "\n\treceived: bin: %3d offset: %3d", + t.Errorf("convert returned incorrect values for position %d (%d)."+ + "\nexpected: bin: %3d offset: %3d"+ + "\nreceived: bin: %3d offset: %3d", data.pos, i, data.bin, data.offset, bin, offset) } } } -// Happy path of convertEnd(). +// Happy path of uint64Buff.convertEnd. func Test_uint64Buff_convertEnd(t *testing.T) { // Generate test position and expected block index and offset testData := []struct { @@ -215,15 +218,15 @@ func Test_uint64Buff_convertEnd(t *testing.T) { for i, data := range testData { bin, offset := u64b.convertEnd(data.pos) if bin != data.bin || offset != data.offset { - t.Errorf("convert() returned incorrect values for position %d "+ - "(round %d).\n\texpected: bin: %3d offset: %3d"+ - "\n\treceived: bin: %3d offset: %3d", + t.Errorf("convert returned incorrect values for position %d (%d)."+ + "\nexpected: bin: %3d offset: %3d"+ + "\nreceived: bin: %3d offset: %3d", data.pos, i, data.bin, data.offset, bin, offset) } } } -// Tests happy path of getBin(). +// Tests happy path of uint64Buff.getBin. func Test_uint64Buff_getBin(t *testing.T) { // Generate test block indexes and the expected index in the buffer testData := []struct { @@ -241,14 +244,14 @@ func Test_uint64Buff_getBin(t *testing.T) { for i, data := range testData { bin := u64b.getBin(data.block) if bin != data.expectedBin { - t.Errorf("getBin() returned incorrect block index for index %d "+ - "(round %d).\n\texpected: %d\n\treceived: %d", + t.Errorf("getBin returned incorrect block index for index %d (%d)."+ + "\nexpected: %d\nreceived: %d", data.block, i, data.expectedBin, bin) } } } -// Tests that delta() returns the correct delta for the given range. +// Tests that uint64Buff.delta returns the correct delta for the given range. func Test_uint64Buff_delta(t *testing.T) { // Generate test ranges and the expected delta testData := []struct { @@ -283,14 +286,14 @@ func Test_uint64Buff_delta(t *testing.T) { for i, data := range testData { delta := u64b.delta(data.start, data.end) if delta != data.expectedDelta { - t.Errorf("delta() returned incorrect value for range %d to %d (round %d)."+ - "\n\texpected: %d\n\treceived: %d", + t.Errorf("delta returned incorrect value for range %d to %d (%d)."+ + "\nexpected: %d\nreceived: %d", data.start, data.end, i, data.expectedDelta, delta) } } } -// Tests that bitMaskRange() produces the correct bit mask for the range. +// Tests that bitMaskRange produces the correct bit mask for the range. func Test_bitMaskRange(t *testing.T) { // Generate test ranges and the expected mask testData := []struct { @@ -313,7 +316,7 @@ func Test_bitMaskRange(t *testing.T) { for i, data := range testData { testMask := bitMaskRange(data.start, data.end) if testMask != data.expectedMask { - t.Errorf("Generated mask for range %d to %d is incorrect (round %d)."+ + t.Errorf("Generated mask for range %d to %d is incorrect (%d)."+ "\n\texpected: %064b\n\treceived: %064b"+ "\n 0123456789012345678901234567890123456789012345678901234567890123"+ "\n 0 1 2 3 4 5 6", @@ -365,8 +368,10 @@ func TestUint64Buff_marshal_unmarshal(t *testing.T) { {0x7FFFFFFFFFFFFFF, ones, ones, ones, 0xFFFFFFFFFFFFFC00}, initU64B(0, math.MaxUint8*2), initU64B(math.MaxUint64, math.MaxUint8*2), - append(append(uint64Buff{0xFFFFFF00F0000000}, initU64B(0, math.MaxUint8*2)...), 0x13374AFB434FF), - append(append(uint64Buff{0xFFFFFF00F0000000}, initU64B(math.MaxUint64, math.MaxUint8*2)...), 0x13374AFB434FF), + append(append(uint64Buff{0xFFFFFF00F0000000}, + initU64B(0, math.MaxUint8*2)...), 0x13374AFB434FF), + append(append(uint64Buff{0xFFFFFF00F0000000}, + initU64B(math.MaxUint64, math.MaxUint8*2)...), 0x13374AFB434FF), } for i, data := range testData { @@ -378,7 +383,7 @@ func TestUint64Buff_marshal_unmarshal(t *testing.T) { } if !reflect.DeepEqual(data, u64b) { t.Errorf("Failed to marshal and unmarshal 1 byte buffer (%d)."+ - "\n\texpected: %X\n\treceived: %X", i, data, u64b) + "\nexpected: %X\nreceived: %X", i, data, u64b) } } } @@ -407,12 +412,15 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { {0x7FFFFFFFFFFFFFF, ones, ones, ones, 0xFFFFFFFFFFFFFC00}, initU64B(0, math.MaxUint8*2), initU64B(math.MaxUint64, math.MaxUint8*2), - append(append(uint64Buff{0xFFFFFF00F0000000}, initU64B(0, math.MaxUint8*2)...), 0x13374AFB434FF), - append(append(uint64Buff{0xFFFFFF00F0000000}, initU64B(math.MaxUint64, math.MaxUint8*2)...), 0x13374AFB434FF), + append(append(uint64Buff{0xFFFFFF00F0000000}, + initU64B(0, math.MaxUint8*2)...), 0x13374AFB434FF), + append(append(uint64Buff{0xFFFFFF00F0000000}, + initU64B(math.MaxUint64, math.MaxUint8*2)...), 0x13374AFB434FF), } str := "" - str += fmt.Sprintf("%4s %4s %4s %4s %4s\n", "orig", "1B", "2B", "4B", "8B") + str += fmt.Sprintf( + "%4s %4s %4s %4s %4s\n", "orig", "1B", "2B", "4B", "8B") str += fmt.Sprintln("==================================") for i, data := range testData { @@ -424,7 +432,7 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { f1bLen := len(buff) if !reflect.DeepEqual(data, u64b) { t.Errorf("Failed to marshal and unmarshal 1 byte buffer (%d)."+ - "\n\texpected: %X\n\treceived: %X", i, data, u64b) + "\nexpected: %X\nreceived: %X", i, data, u64b) } buff = data.marshal2BytesVer2() @@ -435,7 +443,7 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { f2bLen := len(buff) if !reflect.DeepEqual(data, u64b) { t.Errorf("Failed to marshal and unmarshal 2 bytes buffer (%d)."+ - "\n\texpected: %X\n\treceived: %X", i, data, u64b) + "\nexpected: %X\nreceived: %X", i, data, u64b) } buff = data.marshal4BytesVer2() @@ -446,7 +454,7 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { f4bLen := len(buff) if !reflect.DeepEqual(data, u64b) { t.Errorf("Failed to marshal and unmarshal 4 bytes buffer (%d)."+ - "\n\texpected: %X\n\treceived: %X", i, data, u64b) + "\nexpected: %X\nreceived: %X", i, data, u64b) } buff = data.marshal8BytesVer2() @@ -457,11 +465,12 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { f8bLen := len(buff) if !reflect.DeepEqual(data, u64b) { t.Errorf("Failed to marshal and unmarshal 8 bytes buffer (%d)."+ - "\n\texpected: %X\n\treceived: %X", i, data, u64b) + "\nexpected: %X\nreceived: %X", i, data, u64b) } origLen := len(data) * 8 - str += fmt.Sprintf("%4d %4d %4d %4d %4d\n", origLen, f1bLen, f2bLen, f4bLen, f8bLen) + str += fmt.Sprintf("%4d %4d %4d %4d %4d\n", + origLen, f1bLen, f2bLen, f4bLen, f8bLen) str += fmt.Sprintf(" %4.0f%% %4.0f%% %4.0f%% %4.0f%%\n", 100-float64(f1bLen)/float64(origLen)*100, 100-float64(f2bLen)/float64(origLen)*100, @@ -501,7 +510,8 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { // // str := "" // -// str += fmt.Sprintf("%4s %4s %4s %4s %4s\n", "orig", "1B", "2B", "4B", "8B") +// str += fmt.Sprintf("%4s %4s %4s %4s %4s\n", +// "orig", "1B", "2B", "4B", "8B") // str += fmt.Sprintln("==================================") // for i, dataString := range testData { // @@ -524,7 +534,7 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { // f1bLen := len(buff) // if !reflect.DeepEqual(kr.bitStream, u64b) { // t.Errorf("Failed to marshal and unmarshal 1 byte buffer (%d)."+ -// "\n\texpected: %X\n\treceived: %X", i, kr.bitStream, u64b) +// "\nexpected: %X\nreceived: %X", i, kr.bitStream, u64b) // } // // buff = kr.bitStream.marshal2BytesVer2() @@ -535,7 +545,7 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { // f2bLen := len(buff) // if !reflect.DeepEqual(kr.bitStream, u64b) { // t.Errorf("Failed to marshal and unmarshal 2 bytes buffer (%d)."+ -// "\n\texpected: %X\n\treceived: %X", i, kr.bitStream, u64b) +// "\nexpected: %X\nreceived: %X", i, kr.bitStream, u64b) // } // // buff = kr.bitStream.marshal4BytesVer2() @@ -546,7 +556,7 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { // f4bLen := len(buff) // if !reflect.DeepEqual(kr.bitStream, u64b) { // t.Errorf("Failed to marshal and unmarshal 4 bytes buffer (%d)."+ -// "\n\texpected: %X\n\treceived: %X", i, kr.bitStream, u64b) +// "\nexpected: %X\nreceived: %X", i, kr.bitStream, u64b) // } // // buff = kr.bitStream.marshal8BytesVer2() @@ -557,11 +567,12 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { // f8bLen := len(buff) // if !reflect.DeepEqual(kr.bitStream, u64b) { // t.Errorf("Failed to marshal and unmarshal buffer (%d)."+ -// "\n\texpected: %X\n\treceived: %X", i, kr.bitStream, u64b) +// "\nexpected: %X\nreceived: %X", i, kr.bitStream, u64b) // } // // origLen := len(kr.bitStream) * 8 -// str += fmt.Sprintf("%4d %4d %4d %4d %4d\n", origLen, f1bLen, f2bLen, f4bLen, f8bLen) +// str += fmt.Sprintf("%4d %4d %4d %4d %4d\n", +// origLen, f1bLen, f2bLen, f4bLen, f8bLen) // str += fmt.Sprintf(" %4.0f%% %4.0f%% %4.0f%% %4.0f%%\n", // 100-float64(f1bLen)/float64(origLen)*100, // 100-float64(f2bLen)/float64(origLen)*100, @@ -590,7 +601,7 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { // // err := kr.Unmarshal(data) // if err != nil { -// t.Errorf("Unmarshal() returned an error: %+v", err) +// t.Errorf("Unmarshal returned an error: %+v", err) // } // // t.Log(kr) @@ -610,7 +621,7 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { // // err := kr.Unmarshal(data) // if err != nil { -// t.Errorf("Unmarshal() returned an error (%d): %+v", i, err) +// t.Errorf("Unmarshal returned an error (%d): %+v", i, err) // } // // t.Log(kr) @@ -622,7 +633,8 @@ func TestUint64Buff_marshal_unmarshal_Bytes(t *testing.T) { // printBuff prints the buffer and mask in binary with their start and end point // labeled. -func printBuff(buff, mask uint64Buff, buffStart, buffEnd, maskStart, maskEnd int) { +func printBuff( + buff, mask uint64Buff, buffStart, buffEnd, maskStart, maskEnd int) { fmt.Printf("\n\u001B[38;5;59m 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3" + "\n\u001B[38;5;59m 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8" + "\n\033[38;5;59m 0123456789012345678901234567890123456789012345678901234567890123 4567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901 2345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789012345678901\n") diff --git a/nicknames/isValid.go b/nicknames/isValid.go index b2edde92bde01310a68eba0e7ce7868ef858acc9..2c6244d8acb40cf055e2e7877f1675f8a03d7dad 100644 --- a/nicknames/isValid.go +++ b/nicknames/isValid.go @@ -20,16 +20,17 @@ var ErrNicknameTooLong = errors.Errorf("nicknames must be %d "+ // Rules: // - A nickname must not be longer than 24 characters. // - A nickname must not be shorter than 1 character. -// - A nickname may be blank, this will be treated by the system as -// no nickname +// - If a nickname is blank (empty string), then it will be treated by the +// system as no nickname. // // TODO: Add character filtering. func IsValid(nick string) error { if nick == "" { - jww.INFO.Printf("empty nickname passed, treating like no " + - "nickname") + jww.INFO.Printf( + "empty nickname passed, treating like no nickname") return nil } + runeNick := []rune(nick) if len(runeNick) < MinNicknameLength { return errors.WithStack(ErrNicknameTooShort) diff --git a/nicknames/isValid_test.go b/nicknames/isValid_test.go index bc2ce5a11513f687da89873b2b351a65eff40121..14ca53005435b1435693aafa8897bd965793e123 100644 --- a/nicknames/isValid_test.go +++ b/nicknames/isValid_test.go @@ -1,56 +1,58 @@ package nicknames import ( - "github.com/pkg/errors" "testing" + + "github.com/pkg/errors" ) -func TestIsNicknameValid(t *testing.T) { +const nicknameSource = "Sodium, atomic number 11, was first isolated by " + + "Humphry Davy in 1807. A chemical component of salt, he named it Na " + + "in honor of the saltiest region on earth, North America." - // test that behavior for an empty nickname is correct +// Tests that IsValid returns true for all usernames within the correct lengths. +func TestIsValid(t *testing.T) { + for i := MinNicknameLength; i <= MaxNicknameLength; i++ { + nick := nicknameSource[:i] + if err := IsValid(nick); err != nil { + t.Errorf("Error returned from nicknames.IsValid with valid "+ + "nickname %q of input of length %d: %+v", nick, i, err) + } + } +} +// Tests that IsValid return nil for an empty nickname. +func TestIsValid_Empty(t *testing.T) { if err := IsValid(""); err != nil { t.Errorf("Empty nickname should be valid, received: %+v", err) } +} - nicknameSource := "Sodium, atomic number 11, was first isolated by Humphry " + - "Davy in 1807. A chemical component of salt, he named it Na in honor " + - "of the saltiest region on earth, North America." - - // test that behavior for too short nicknames is correct - for i := 1; i < MinNicknameLength; i++ { - nick := nicknameSource[:i] - - if err := IsValid(nick); err != nil && - !errors.Is(err, ErrNicknameTooShort) { - t.Errorf("Wrong error returned from nicknames.IsValid() "+ - "with too short input of length %d: %+v", i, err) - } else if err == nil { - t.Errorf("No error returned from nicknames.IsValid() "+ - "with too short input of length %d", i) - } - } - - // test that behavior for too long nicknames is correct +// Error path: Tests that IsValid returns the error ErrNicknameTooLong when the +// nickname is too long. +func TestIsValid_MaxLengthError(t *testing.T) { for i := MaxNicknameLength + 1; i < MaxNicknameLength*5; i++ { nick := nicknameSource[:i] - - if err := IsValid(nick); err != nil && - !errors.Is(err, ErrNicknameTooLong) { - t.Errorf("Wrong error returned from nicknames.IsValid() "+ - "with too long input of length %d: %+v", i, err) - } else if err == nil { - t.Errorf("No error returned from nicknames.IsValid() "+ - "with too long input of length %d", i) + err := IsValid(nick) + if err == nil || !errors.Is(err, ErrNicknameTooLong) { + t.Errorf("Wrong error returned from nicknames.IsValid with too "+ + "long input of length %d.\nexpected: %v\nreceived: %+v", + i, ErrNicknameTooLong, err) } } +} - // test that behavior for valid nicknames is correct - for i := MinNicknameLength; i <= MaxNicknameLength; i++ { +// Error path: Tests that IsValid returns the error ErrNicknameTooShort when the +// nickname is too short. +func TestIsValid_MinLengthError(t *testing.T) { + for i := 1; i < MinNicknameLength; i++ { nick := nicknameSource[:i] - if err := IsValid(nick); err != nil { - t.Errorf("Error returned from nicknames.IsValid() "+ - "with valid nickname of input of length %d: %+v", i, err) + + err := IsValid(nick) + if err == nil || !errors.Is(err, ErrNicknameTooShort) { + t.Errorf("Wrong error returned from nicknames.IsValid with too "+ + "short input of length %d.\nexpected: %v\nreceived: %+v", + i, ErrNicknameTooShort, err) } } } diff --git a/notifications/data.go b/notifications/data.go index 107ffa5d5bb3be4422c087825f400bcf9c591062..9b0aad2f3dfae84d79d74df566fa4eeaa927cb4c 100644 --- a/notifications/data.go +++ b/notifications/data.go @@ -11,9 +11,10 @@ import ( "bytes" "encoding/base64" "encoding/csv" + "strings" + "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" - "strings" ) type Data struct { @@ -23,15 +24,22 @@ type Data struct { MessageHash []byte } +// BuildNotificationCSV converts the [Data] list into a CSV of the specified max +// size and return it along with the included [Data] entries. Any [Data] entries +// over that size are excluded. +// +// The CSV contains each [Data] entry on its own row with column one the +// [Data.MessageHash] and column two having the [Data.IdentityFP], but base 64 +// encoded func BuildNotificationCSV(ndList []*Data, maxSize int) ([]byte, []*Data) { - buf := &bytes.Buffer{} - - numWritten := 0 + var buf bytes.Buffer + var numWritten int for _, nd := range ndList { - line := &bytes.Buffer{} - w := csv.NewWriter(line) - output := []string{base64.StdEncoding.EncodeToString(nd.MessageHash), + var line bytes.Buffer + w := csv.NewWriter(&line) + output := []string{ + base64.StdEncoding.EncodeToString(nd.MessageHash), base64.StdEncoding.EncodeToString(nd.IdentityFP)} if err := w.Write(output); err != nil { @@ -53,28 +61,30 @@ func BuildNotificationCSV(ndList []*Data, maxSize int) ([]byte, []*Data) { return buf.Bytes(), ndList[numWritten:] } +// DecodeNotificationsCSV decodes the Data list CSV into a slice of Data. func DecodeNotificationsCSV(data string) ([]*Data, error) { r := csv.NewReader(strings.NewReader(data)) - read, err := r.ReadAll() + records, err := r.ReadAll() if err != nil { return nil, errors.WithMessage(err, "Failed to decode notifications CSV") } - l := make([]*Data, len(read)) - for i, touple := range read { - messageHash, err := base64.StdEncoding.DecodeString(touple[0]) + list := make([]*Data, len(records)) + for i, tuple := range records { + messageHash, err := base64.StdEncoding.DecodeString(tuple[0]) if err != nil { return nil, errors.WithMessage(err, "Failed decode an element") } - identityFP, err := base64.StdEncoding.DecodeString(touple[1]) + identityFP, err := base64.StdEncoding.DecodeString(tuple[1]) if err != nil { return nil, errors.WithMessage(err, "Failed decode an element") } - l[i] = &Data{ + list[i] = &Data{ EphemeralID: 0, IdentityFP: identityFP, MessageHash: messageHash, } } - return l, nil + + return list, nil } diff --git a/notifications/data_test.go b/notifications/data_test.go index c1796d7cbe95a4fe1c7062d27317e2285d3206a7..44938899342269ffb53c64ee80a25654ce07f9e6 100644 --- a/notifications/data_test.go +++ b/notifications/data_test.go @@ -10,140 +10,166 @@ package notifications import ( "math/rand" "reflect" + "strings" "testing" - "time" ) -func TestMake_DecodeNotificationsCSV(t *testing.T) { - - rng := rand.New(rand.NewSource(time.Now().UnixNano())) - - const numNotifications = 45 - - notifList := make([]*Data, 0, numNotifications) - - for i := 0; i < numNotifications; i++ { - msgHash := make([]byte, 32) - ifp := make([]byte, 25) - rng.Read(msgHash) - rng.Read(ifp) - notifList = append(notifList, &Data{MessageHash: msgHash, IdentityFP: ifp}) +// Tests that a list of Data CSV encoded by BuildNotificationCSV and decoded bu +// DecodeNotificationsCSV matches the original. +func TestBuildNotificationCSV_DecodeNotificationsCSV(t *testing.T) { + rng := rand.New(rand.NewSource(186745)) + expected := make([]*Data, 50) + for i := range expected { + identityFP, messageHash := make([]byte, 25), make([]byte, 32) + rng.Read(messageHash) + rng.Read(identityFP) + expected[i] = &Data{IdentityFP: identityFP, MessageHash: messageHash} } - notifCSV, _ := BuildNotificationCSV(notifList, 4096) - newNotifList, err := DecodeNotificationsCSV(string(notifCSV)) - + csvData, _ := BuildNotificationCSV(expected, 9999) + dataList, err := DecodeNotificationsCSV(string(csvData)) if err != nil { - t.Error(err) + t.Errorf("Failed to decode notifications CSV: %+v", err) } - if !reflect.DeepEqual(notifList, newNotifList) { - t.Errorf("The generated notifivations do not match") + if !reflect.DeepEqual(expected, dataList) { + t.Errorf("The generated Data list does not match the original."+ + "\nexpected: %v\nreceived: %v", expected, dataList) } } +// Consistency test of BuildNotificationCSV. func TestBuildNotificationCSV(t *testing.T) { - expected := "U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVI=,39ebTXZCm2F6DJ+fDTulWwzA1hRMiIU1hA==" + - "\nGsvgcJsHWAg/YdN1vAK0HfT5GSnhj9qeb4LlTnSOgec=,nku9b+NM3LqEPujWPoxP/hzr6lRtj6wT3Q==" + - "\nGqwEzi6ih3xVec+ix44bC6+uiBuCp1EQikLtPJA8qkM=,Rlp4YgYWl4rtDOPGxPOue8PgSVtXEv79vg==" + - "\nDBAoh+EA2s0tiF9pLLYH2gChHBxwceeWotwtwlpbdLI=,4SlwXic/BckjJoKOKwVuOBdljhBhSYlH/Q==" + - "\n80RBDtTBFgI/qONXa2/tJ/+JdLrAyv2a0FaSsTYZ5zg=,lk39x56NU0NzZhz9ZtdP7B4biUkatyNuSw==" + - "\ndSFikM8r60LDyicyhWDxqsBnzqbov0bUqytGgEAsX7I=,gg6IXTJg8d6XgoPUoJo2+WwglBdG4+1Npg==" + - "\nRqmui0+ntPw6ILr6GnXtMnqGuLDDmvHP0rO1EhnqeVM=,Or9EjSxHnTJgdTOQWRTIzBzwnaOeDpKdAg==" + - "\nSry8sWk5e7c05+8KbgHxhU3rX+Qk/vesIQiR9ZdeKSo=,oriqBHxhzbMzc+vnLCegmMAhl9rmtzLDUQ==" + - "\n32aPh04snxzgnKhgF+fiF0gwP/QcGyPhHEjtF1OdaF8=,dvKnmLxk3g5dsoZLKtPCbOY4I0J2WhPWlg==" + - "\n5S33YPbDRl4poNykasOg1XATO8IVcfX1SmQxBVE/2EI=,mxlK4bqfKoOGrnKzZh/oLCrGTb9GFRgk4g==" + - "\nMFMSY3yZwrh9bfDdXvKDZxkHLWcvYfqgvob0V5Iew3w=,DkYM8NcD0H3F9WYaRQEzQJpxK2pmq9e6ZQ==" + - "\nIkyiaXjZpc5i/rEag48WYi61TO4+Z1UinBg8GTOpFlg=,Xhg7twkZLbDmyNcJudc4O5k8aUmZRbCwzw==" + - "\n49wuwfyWENfusZ0JFqJ0I8KeRC8OMcLJU5Zg8F+zfkU=,zRvwvPwaNGxDTxHPAEFvphaVuSAuaDY6HA==" + - "\neH9HhOCu2ceFZBhOEx8efIEfvYhbzGc06JM/PLLyXVI=,+fjHVHrX4dYnjJ98hy+ED52U2f3trpPbJA==" + - "\nlXGPWAuMjyvsxqp2w7D5SK++YSelz9VrwRs8Lqg3ocY=,aagi92hk7CrgzWv93yGxFER0v9N80ga1Gg==" + - "\nzgUKthmex7OW1hj94OGimZpvPZ+LergUn3Leulxs1P0=,TTkskrSyGsgSA0Bi38MGOnpoYrD+8QUpGQ==" + - "\nwqh6SZT8HkAeEcWknH6OqeZdbMQEZf01LyxC7D0+9g0=,tpdAUX3HZSue7/UWU1qhyfM9sT7R964b4w==" + - "\nhBMjKNED+HGvm80VIzw5OXj1wXCJ6PMmegzMfjm/ysc=,rEK+LBcsYkPRBjMDbT1GuBkWrkb/E9amsg==" + - "\n+tkHnW3zRAWQKWZ7LrQaQAEXVW/ly0BbMXCsrKXHW68=,f3tw6GFE07oDazsfWP5CeVDn0E9MJuvhLw==" + - "\n1eEjcZgIogS4Ubps8spsRu2IFi9dRc21oHY65+GDP7c=,rfmJNvUeTdqKKE7xmoW7h0N7QQMwWjs4bA==" + - "\nfTbZLSJUmWCnFPKoKeHCAhZzvzDFC2edUFaJVcnBmAg=,nZX2A5fSr1+PyREL46nhJelEhJeXCNaqfA==" + - "\n/GKejZFHzy9ftqBVkauGhzoerQWkpmcdaVFcg53Yrzo=,Otd0AsX9OoOgRgipiTMAIWLdTB/1VH9XUg==" + - "\nAx8hIeFBCKpaV0VsrpHBcymtWs5h6um2Ut8zALTCq1g=,J3bYW2jKMtXDc8JkeFg7xI+ja+SNZZw/4Q==" + - "\nc0EBx+SP03+5+uPwu06bbfR1Ki6RZM8F9WjSyJ6k1l0=,dgYOZIeQWTJLt1rbFBovfC/eeBH0gc8Iag==" + - "\nPsPYs3cAEv0npLZbAq6FJW9zbt4+TdhXIJV1pIjVdA0=,L3JpWlcNvyZH8pXiM5Xu2s/2NuGwzyDeag==" + - "\nEP+ZQ+3Kb5a/TdrwC51PzWrL27P2MZRQNYaopliuYLU=,7lOata0Z8roj3KZn36ZVE0xZSiyAa9+k5w==" + - "\nVuRYtIuuSQ0ELgejVels+4nMq/KBnXlNnhKC/QpyVPE=,s5T26rxmpki639tH01CKaTgLpg1f9LQyew==" + - "\n9lDgExuPV3WthpenNGPNKAbmru75K16b/+QOlGaZD6M=,rsEeSny2rrsXt/7SlRPTHtT/HRbm1ZlWGQ==" + - "\nUV9fU4dpAO0PetHyOLszRAnjwWSVc6VvQ6jh0hNyRvw=,psYzJNQ/g+wNTS/WUG/f7uIeJDI9gOfLhA==" + - "\nX0PSIyKapCEUSifbt8RAwceY+aJNLIXxLCSIv4fS2Sk=,oKR5pVt7c+TvskFDTjbUT315OI2hnlz+gw==" + - "\nIWN1mCbfOfgzaVyiKqZRlUiQvNzPZq09c6jhq5+Dh30=,Jju7J/W8SXvWVEdNy4YqtN1om6BNDa5ooA==" + - "\ng9al6HTEHOSudp3dtiHBZDI5vTeKLpGprOJ38sCNcUs=,ydnmLAViyiluEqd2F0TduCOoLxm6fQpSSw==" + - "\nVJK79yrDTvy5Cl7fbbwhn78w7PJfpmbJJGsIHV0sV44=,7wAIsI1hoJdkBPQuqCpIc/sNZId3faZHBg==" + - "\nt0hXpZ8dKn82F6O81VqVn9GSBMLjv6zg5gMLfABpuXw=,aQyYNMIoKbqb1P+pr1gZb3deMPPJO0nsLw==" + - "\nHoo35EiId/9sfiQlH+FQ7OfMWvss7XprvKzj7qAb11k=,QA2HuYCzU8EVy8Fip3jdnqBCNZ1MIP4hig==" + - "\nRm/cqgfzRclH5aCWoj+JZ89P4Si96pz8xljy7bEkkpw=,3M9Yj0lOvjNGwZrteHuXxXcN/t6EXPWwQA==" + - "\n3LYIlEhmP8MyF8HyL7TKpWBOFiDDl7Oo40e3k0PkPl4=,lPyl5AhHBG352IgCviQSoTRntmVWLzKHSA==" + - "\n5IPF6phRI8xCLk96jOl0B1OPYfZ+ga42GtW89w8iiDE=,aw4ukENMK3yiyg2KICMlx7gMtjXoXb0jNw==" + - "\nQNWTeKISlTt5F8x/RdbsAU0fC1kNaLRRMzwAisvlEjE=,+4CfIcugABlRkeMY0PNJ84IlHeA7NfV9zw==" + - "\nUrloJgqUXJGcj7n7jfqEfWb7oCNK27w240akwcvimRg=,FGu6CxanGNbECj5ZdsoEaGR0nEgEx5zJrQ==" + - "\nZLZ2Bw9hP9+WSKJW3DwiOkvOiRWUK9lrAHMdrZWDfD8=,r/8aTMECHltCu3V4nHCj932lPCXgSLkLqg==" + - "\nHrARGizMUEcrKECJa840U6mtBJct5H/GZEahdvtaE8I=,Xcu6Vrv2NV4bKvhmVDH3RyqWYYFmnxAfWg==" + - "\nVyy0GiAUFyBexvVbintbSsYQjuBFVTHkOGRH9fTJGdw=,S77jKfBIvvwO5ArLSmxuEHLQQwBQjdXzWw==" + - "\nLPwGgdnQAZaEWYyCdG1Zk/AB99k9z/INedKtTv1e5Ow=,qyjyubYZBFj+NsS3dayvYMFUI5W2jO9WjQ==" + - "\nOWA4Tr2KTqoq6+xmTlY4cNuAPSgOPmJwo7D+A4vILZw=,gw/oRNJWsLXpYvMxM58T2FKXOynKoD6QFA==" + - "\nqIfiAe4BFutxC8au4sJOXZBExUpNymRkA2w2FMafnII=,PFvyIccm6amL8jQBONIh2lPeVMi1Bvk/fg==" + - "\nAcsU15TF3uaMZzKcHTyptNP7EBq5eBYhI2vBK/rFKCQ=,Gcam+D1Hzebx9Zs8AHd3yAALcOHAyJAiuQ==" + - "\n2xNm0x0FAN2fAkPW6rUP0gFhx0hJw94sUaubeM+WWRA=,iC3H9TvHMgsc9IRy9ks2Qd/TaY9zTNkOXA==" + - "\nA3hMWMAcrvqWoVNZPxQqYFWLMoCUCnrl2NArseYXnTk=,WsPBzNwVH8QF0fcpHDoq7po6JHhgL9Zcew==\n" + expected := `U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVI=,39ebTXZCm2F6DJ+fDTulWwzA1hRMiIU1hA== +GsvgcJsHWAg/YdN1vAK0HfT5GSnhj9qeb4LlTnSOgec=,nku9b+NM3LqEPujWPoxP/hzr6lRtj6wT3Q== +GqwEzi6ih3xVec+ix44bC6+uiBuCp1EQikLtPJA8qkM=,Rlp4YgYWl4rtDOPGxPOue8PgSVtXEv79vg== +DBAoh+EA2s0tiF9pLLYH2gChHBxwceeWotwtwlpbdLI=,4SlwXic/BckjJoKOKwVuOBdljhBhSYlH/Q== +80RBDtTBFgI/qONXa2/tJ/+JdLrAyv2a0FaSsTYZ5zg=,lk39x56NU0NzZhz9ZtdP7B4biUkatyNuSw== +dSFikM8r60LDyicyhWDxqsBnzqbov0bUqytGgEAsX7I=,gg6IXTJg8d6XgoPUoJo2+WwglBdG4+1Npg== +Rqmui0+ntPw6ILr6GnXtMnqGuLDDmvHP0rO1EhnqeVM=,Or9EjSxHnTJgdTOQWRTIzBzwnaOeDpKdAg== +Sry8sWk5e7c05+8KbgHxhU3rX+Qk/vesIQiR9ZdeKSo=,oriqBHxhzbMzc+vnLCegmMAhl9rmtzLDUQ== +32aPh04snxzgnKhgF+fiF0gwP/QcGyPhHEjtF1OdaF8=,dvKnmLxk3g5dsoZLKtPCbOY4I0J2WhPWlg== +5S33YPbDRl4poNykasOg1XATO8IVcfX1SmQxBVE/2EI=,mxlK4bqfKoOGrnKzZh/oLCrGTb9GFRgk4g== +MFMSY3yZwrh9bfDdXvKDZxkHLWcvYfqgvob0V5Iew3w=,DkYM8NcD0H3F9WYaRQEzQJpxK2pmq9e6ZQ== +IkyiaXjZpc5i/rEag48WYi61TO4+Z1UinBg8GTOpFlg=,Xhg7twkZLbDmyNcJudc4O5k8aUmZRbCwzw== +49wuwfyWENfusZ0JFqJ0I8KeRC8OMcLJU5Zg8F+zfkU=,zRvwvPwaNGxDTxHPAEFvphaVuSAuaDY6HA== +eH9HhOCu2ceFZBhOEx8efIEfvYhbzGc06JM/PLLyXVI=,+fjHVHrX4dYnjJ98hy+ED52U2f3trpPbJA== +lXGPWAuMjyvsxqp2w7D5SK++YSelz9VrwRs8Lqg3ocY=,aagi92hk7CrgzWv93yGxFER0v9N80ga1Gg== +zgUKthmex7OW1hj94OGimZpvPZ+LergUn3Leulxs1P0=,TTkskrSyGsgSA0Bi38MGOnpoYrD+8QUpGQ== +wqh6SZT8HkAeEcWknH6OqeZdbMQEZf01LyxC7D0+9g0=,tpdAUX3HZSue7/UWU1qhyfM9sT7R964b4w== +hBMjKNED+HGvm80VIzw5OXj1wXCJ6PMmegzMfjm/ysc=,rEK+LBcsYkPRBjMDbT1GuBkWrkb/E9amsg== ++tkHnW3zRAWQKWZ7LrQaQAEXVW/ly0BbMXCsrKXHW68=,f3tw6GFE07oDazsfWP5CeVDn0E9MJuvhLw== +1eEjcZgIogS4Ubps8spsRu2IFi9dRc21oHY65+GDP7c=,rfmJNvUeTdqKKE7xmoW7h0N7QQMwWjs4bA== +fTbZLSJUmWCnFPKoKeHCAhZzvzDFC2edUFaJVcnBmAg=,nZX2A5fSr1+PyREL46nhJelEhJeXCNaqfA== +/GKejZFHzy9ftqBVkauGhzoerQWkpmcdaVFcg53Yrzo=,Otd0AsX9OoOgRgipiTMAIWLdTB/1VH9XUg== +Ax8hIeFBCKpaV0VsrpHBcymtWs5h6um2Ut8zALTCq1g=,J3bYW2jKMtXDc8JkeFg7xI+ja+SNZZw/4Q== +c0EBx+SP03+5+uPwu06bbfR1Ki6RZM8F9WjSyJ6k1l0=,dgYOZIeQWTJLt1rbFBovfC/eeBH0gc8Iag== +PsPYs3cAEv0npLZbAq6FJW9zbt4+TdhXIJV1pIjVdA0=,L3JpWlcNvyZH8pXiM5Xu2s/2NuGwzyDeag== +EP+ZQ+3Kb5a/TdrwC51PzWrL27P2MZRQNYaopliuYLU=,7lOata0Z8roj3KZn36ZVE0xZSiyAa9+k5w== +VuRYtIuuSQ0ELgejVels+4nMq/KBnXlNnhKC/QpyVPE=,s5T26rxmpki639tH01CKaTgLpg1f9LQyew== +9lDgExuPV3WthpenNGPNKAbmru75K16b/+QOlGaZD6M=,rsEeSny2rrsXt/7SlRPTHtT/HRbm1ZlWGQ== +UV9fU4dpAO0PetHyOLszRAnjwWSVc6VvQ6jh0hNyRvw=,psYzJNQ/g+wNTS/WUG/f7uIeJDI9gOfLhA== +X0PSIyKapCEUSifbt8RAwceY+aJNLIXxLCSIv4fS2Sk=,oKR5pVt7c+TvskFDTjbUT315OI2hnlz+gw== +IWN1mCbfOfgzaVyiKqZRlUiQvNzPZq09c6jhq5+Dh30=,Jju7J/W8SXvWVEdNy4YqtN1om6BNDa5ooA== +g9al6HTEHOSudp3dtiHBZDI5vTeKLpGprOJ38sCNcUs=,ydnmLAViyiluEqd2F0TduCOoLxm6fQpSSw== +VJK79yrDTvy5Cl7fbbwhn78w7PJfpmbJJGsIHV0sV44=,7wAIsI1hoJdkBPQuqCpIc/sNZId3faZHBg== +t0hXpZ8dKn82F6O81VqVn9GSBMLjv6zg5gMLfABpuXw=,aQyYNMIoKbqb1P+pr1gZb3deMPPJO0nsLw== +Hoo35EiId/9sfiQlH+FQ7OfMWvss7XprvKzj7qAb11k=,QA2HuYCzU8EVy8Fip3jdnqBCNZ1MIP4hig== +Rm/cqgfzRclH5aCWoj+JZ89P4Si96pz8xljy7bEkkpw=,3M9Yj0lOvjNGwZrteHuXxXcN/t6EXPWwQA== +3LYIlEhmP8MyF8HyL7TKpWBOFiDDl7Oo40e3k0PkPl4=,lPyl5AhHBG352IgCviQSoTRntmVWLzKHSA== +5IPF6phRI8xCLk96jOl0B1OPYfZ+ga42GtW89w8iiDE=,aw4ukENMK3yiyg2KICMlx7gMtjXoXb0jNw== +QNWTeKISlTt5F8x/RdbsAU0fC1kNaLRRMzwAisvlEjE=,+4CfIcugABlRkeMY0PNJ84IlHeA7NfV9zw== +UrloJgqUXJGcj7n7jfqEfWb7oCNK27w240akwcvimRg=,FGu6CxanGNbECj5ZdsoEaGR0nEgEx5zJrQ== +ZLZ2Bw9hP9+WSKJW3DwiOkvOiRWUK9lrAHMdrZWDfD8=,r/8aTMECHltCu3V4nHCj932lPCXgSLkLqg== +HrARGizMUEcrKECJa840U6mtBJct5H/GZEahdvtaE8I=,Xcu6Vrv2NV4bKvhmVDH3RyqWYYFmnxAfWg== +Vyy0GiAUFyBexvVbintbSsYQjuBFVTHkOGRH9fTJGdw=,S77jKfBIvvwO5ArLSmxuEHLQQwBQjdXzWw== +LPwGgdnQAZaEWYyCdG1Zk/AB99k9z/INedKtTv1e5Ow=,qyjyubYZBFj+NsS3dayvYMFUI5W2jO9WjQ== +OWA4Tr2KTqoq6+xmTlY4cNuAPSgOPmJwo7D+A4vILZw=,gw/oRNJWsLXpYvMxM58T2FKXOynKoD6QFA== +qIfiAe4BFutxC8au4sJOXZBExUpNymRkA2w2FMafnII=,PFvyIccm6amL8jQBONIh2lPeVMi1Bvk/fg== +AcsU15TF3uaMZzKcHTyptNP7EBq5eBYhI2vBK/rFKCQ=,Gcam+D1Hzebx9Zs8AHd3yAALcOHAyJAiuQ== +2xNm0x0FAN2fAkPW6rUP0gFhx0hJw94sUaubeM+WWRA=,iC3H9TvHMgsc9IRy9ks2Qd/TaY9zTNkOXA== +A3hMWMAcrvqWoVNZPxQqYFWLMoCUCnrl2NArseYXnTk=,WsPBzNwVH8QF0fcpHDoq7po6JHhgL9Zcew== +` extra := "Zq3/Nor7+NgAzkvg7LxVOYyRMMnAEDxkHpGnKpeHltc=,wGc+G+CLk/qEIoGMQ0XBZlyHkiYS3r7nkw==\n" rng := rand.New(rand.NewSource(42)) - - const numNotifications = 50 - - notifList := make([]*Data, 0, numNotifications) - - for i := 0; i < numNotifications; i++ { - msgHash := make([]byte, 32) - ifp := make([]byte, 25) - rng.Read(msgHash) - rng.Read(ifp) - notifList = append(notifList, &Data{MessageHash: msgHash, IdentityFP: ifp}) + dataList := make([]*Data, 50) + for i := range dataList { + identityFP, messageHash := make([]byte, 25), make([]byte, 32) + rng.Read(messageHash) + rng.Read(identityFP) + dataList[i] = &Data{IdentityFP: identityFP, MessageHash: messageHash} } - csv, rest := BuildNotificationCSV(notifList, 4096) - + csv, rest := BuildNotificationCSV(dataList, 4096) second, _ := BuildNotificationCSV(rest, 4096) - if expected != string(csv) { - t.Errorf("First pass mismatch: Expected:\n[%s]\n, received: \n[%s]\n", expected, string(csv)) + t.Errorf("First pass mismatch.\nexpected:\n[%s]\n\nreceived:\n[%s]", + expected, string(csv)) } if extra != string(second) { - t.Errorf("Second pass mismatch: Expected: \n[%s]\n, received: \n[%s]\n", extra, string(second)) + t.Errorf("Second pass mismatch.\nexpected:\n[%s]\n\nreceived:\n[%s]", + extra, string(second)) } } func TestBuildNotificationCSV_small(t *testing.T) { - expected := "U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVI=,39ebTXZCm2F6DJ+fDTulWwzA1hRMiIU1hA==" + - "\nGsvgcJsHWAg/YdN1vAK0HfT5GSnhj9qeb4LlTnSOgec=,nku9b+NM3LqEPujWPoxP/hzr6lRtj6wT3Q==\n" - + expected := `U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVI=,39ebTXZCm2F6DJ+fDTulWwzA1hRMiIU1hA== +GsvgcJsHWAg/YdN1vAK0HfT5GSnhj9qeb4LlTnSOgec=,nku9b+NM3LqEPujWPoxP/hzr6lRtj6wT3Q== +` rng := rand.New(rand.NewSource(42)) - - const numNotifications = 2 - - notifList := make([]*Data, 0, numNotifications) - - for i := 0; i < numNotifications; i++ { - msgHash := make([]byte, 32) - ifp := make([]byte, 25) - rng.Read(msgHash) - rng.Read(ifp) - notifList = append(notifList, &Data{MessageHash: msgHash, IdentityFP: ifp}) + dataList := make([]*Data, 2) + for i := range dataList { + identityFP, messageHash := make([]byte, 25), make([]byte, 32) + rng.Read(messageHash) + rng.Read(identityFP) + dataList[i] = &Data{IdentityFP: identityFP, MessageHash: messageHash} } - csv, rest := BuildNotificationCSV(notifList, 4096) - + csv, rest := BuildNotificationCSV(dataList, 4096) if expected != string(csv) { - t.Errorf("First pass mismatch: Expected:\n[%s]\n, received: \n[%s]\n", expected, string(csv)) + t.Errorf("First pass mismatch.\nexpected:\n[%s]\n\nreceived:\n[%s]", + expected, string(csv)) } if len(rest) != 0 { - t.Errorf("Should not have been any overflow, but got [%+v]", rest) + t.Errorf("Should not have been any overflow, but got %+v", rest) + } +} + +// Error path: Tests that DecodeNotificationsCSV returns the expected error for +// an invalid MessageHash. +func TestDecodeNotificationsCSV_InvalidMessageHashError(t *testing.T) { + invalidCSV := `U4x/lrFkvxuXu59LtHLonnZND6SugndnVI=,39ebTXZCm2F6DJ+fDTulWwzA1hRMiIU1hA== +` + expectedErr := "Failed decode an element" + _, err := DecodeNotificationsCSV(invalidCSV) + if err == nil || !strings.Contains(err.Error(), expectedErr) { + t.Errorf("Unexpected error for invalid MessageHash."+ + "\nexpected: %s\nreceived: %+v", expectedErr, err) + } +} + +// Error path: Tests that DecodeNotificationsCSV returns the expected error for +// an invalid identityFP. +func TestDecodeNotificationsCSV_InvalididentityFPError(t *testing.T) { + invalidCSV := `U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVI=,39ebTXZCm2F6DJ1hRMiIU1hA== +` + expectedErr := "Failed decode an element" + _, err := DecodeNotificationsCSV(invalidCSV) + if err == nil || !strings.Contains(err.Error(), expectedErr) { + t.Errorf("Unexpected error for invalid identityFP."+ + "\nexpected: %s\nreceived: %+v", expectedErr, err) + } +} + +// Error path: Tests that DecodeNotificationsCSV returns the expected error for +// an invalid identityFP. +func TestDecodeNotificationsCSV_NoEofError(t *testing.T) { + invalidCSV := `U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVI=,39ebTXZCm2F6DJ+fDTulWwzA1hRMiIU1hA==,"` + expectedErr := "Failed to decode notifications CSV" + _, err := DecodeNotificationsCSV(invalidCSV) + if err == nil || !strings.Contains(err.Error(), expectedErr) { + t.Errorf("Unexpected error for invalid identityFP."+ + "\nexpected: %s\nreceived: %+v", expectedErr, err) } } diff --git a/states/state.go b/states/state.go index 6ceea0134c1f2710df55bb8b34f02ae2b31755bf..95cd44c7ad00c378861bdc9cd2c897d93b89745e 100644 --- a/states/state.go +++ b/states/state.go @@ -7,16 +7,18 @@ package states -import "fmt" +import ( + "fmt" +) -// this holds the enum for the states of a round. It is in primitives so +// This holds the enum for the states of a round. It is in primitives so // other repos such as registration/permissioning, gateway, and client can // access it -// type which holds activities so they have have an associated stringer +// Round describes the state of the round. type Round uint32 -// List of Activities server can be in +// List of round states. const ( PENDING = Round(iota) PRECOMPUTING @@ -25,13 +27,13 @@ const ( REALTIME COMPLETED FAILED + NUM_STATES ) -const NUM_STATES = FAILED + 1 - -// Stringer to get the name of the activity, primarily for for error prints -func (s Round) String() string { - switch s { +// String returns the string representation of the Round state. This functions +// adheres to the fmt.Stringer interface. +func (r Round) String() string { + switch r { case PENDING: return "PENDING" case PRECOMPUTING: @@ -47,6 +49,6 @@ func (s Round) String() string { case FAILED: return "FAILED" default: - return fmt.Sprintf("UNKNOWN STATE: %d", s) + return fmt.Sprintf("UNKNOWN STATE: %d", r) } } diff --git a/states/states_test.go b/states/states_test.go index 39b911081f913283807d2fd4518a0b1b713b6b15..e01647f1c716cbab089a8529eae6d745997d8106 100644 --- a/states/states_test.go +++ b/states/states_test.go @@ -9,17 +9,15 @@ package states import "testing" -//tests the test stringer is correct -func TestActivity_String(t *testing.T) { - //define some states to check - expectedStateStringer := []string{"PENDING", "PRECOMPUTING", "STANDBY", "QUEUED", +// Consistency test of Round.String. +func TestRound_String(t *testing.T) { + expected := []string{"PENDING", "PRECOMPUTING", "STANDBY", "QUEUED", "REALTIME", "COMPLETED", "FAILED", "UNKNOWN STATE: 7"} - //check if states give the correct return for st := PENDING; st <= NUM_STATES; st++ { - if st.String() != expectedStateStringer[st] { - t.Errorf("Round %d did not string correctly: expected: %s,"+ - "received: %s", uint8(st), expectedStateStringer[st], st.String()) + if st.String() != expected[st] { + t.Errorf("Incorrect string for Round state %d."+ + "\nexpected: %s\nreceived: %s", st, expected[st], st.String()) } } } diff --git a/version/checkVersion.go b/version/checkVersion.go index d2c453791c1c796f83b647009c1b8b2b4f069bac..d9ea667fd0fb86317c15ab85fec8b18af5cf8d4d 100644 --- a/version/checkVersion.go +++ b/version/checkVersion.go @@ -5,16 +5,19 @@ // LICENSE file. // //////////////////////////////////////////////////////////////////////////////// -// The version for an entity is composed of a major version , minor version, and +// Package version describes a version used for a repository. +// +// The version for an entity is composed of a major version, minor version, and // patch. The major and minor version numbers are both integers and dictate the // compatibility between two versions. The patch provides extra information that // is not part of the compatibility check, but still must be present. package version import ( - "github.com/pkg/errors" "strconv" "strings" + + "github.com/pkg/errors" ) // String version delimiter @@ -77,13 +80,15 @@ func ParseVersion(versionString string) (Version, error) { // Check that the major version is an integer version.major, err = strconv.Atoi(versionParts[0]) if err != nil { - return Version{}, errors.Errorf("expected integer for major version: %+v", err) + return Version{}, + errors.Errorf("expected integer for major version: %+v", err) } // Check that the minor version is an integer version.minor, err = strconv.Atoi(versionParts[1]) if err != nil { - return Version{}, errors.Errorf("expected integer for minor version: %+v", err) + return Version{}, + errors.Errorf("expected integer for minor version: %+v", err) } // Check that the patch is not empty diff --git a/version/checkVersion_test.go b/version/checkVersion_test.go index b5ec520a9848badd1b55b475b2d15f109d941a05..9e1cc0b55726265e9e4ea8285b7ac466ba64e1b6 100644 --- a/version/checkVersion_test.go +++ b/version/checkVersion_test.go @@ -20,7 +20,7 @@ func TestNew(t *testing.T) { test := New(expected.major, expected.minor, expected.patch) if !reflect.DeepEqual(expected, test) { - t.Errorf("New() did not created the expected Version."+ + t.Errorf("New did not create the expected Version."+ "\nexpected: %+v\nreceived: %+v", expected, test) } } @@ -30,7 +30,7 @@ func TestVersion_Major(t *testing.T) { v := Version{1, 2, "3"} if v.Major() != v.major { - t.Errorf("Major() did not return the expected value."+ + t.Errorf("Major did not return the expected value."+ "\nexpected: %d\nreceived: %d", v.major, v.Major()) } } @@ -40,7 +40,7 @@ func TestVersion_Minor(t *testing.T) { v := Version{1, 2, "3"} if v.Minor() != v.minor { - t.Errorf("Minor() did not return the expected value."+ + t.Errorf("Minor did not return the expected value."+ "\nexpected: %d\nreceived: %d", v.minor, v.Minor()) } } @@ -50,7 +50,7 @@ func TestVersion_Patch(t *testing.T) { v := Version{1, 2, "3"} if v.Patch() != v.patch { - t.Errorf("Patch() did not return the expected value."+ + t.Errorf("Patch did not return the expected value."+ "\nexpected: %s\nreceived: %s", v.patch, v.Patch()) } } @@ -68,7 +68,7 @@ func TestVersion_String(t *testing.T) { for expected, ver := range testValues { test := ver.String() if expected != test { - t.Errorf("String() did not return the expected string."+ + t.Errorf("String did not return the expected string."+ "\nexpected: %s\nreceived: %s", expected, test) } } @@ -86,11 +86,11 @@ func TestParseVersion(t *testing.T) { for versionString, expected := range testValues { test, err := ParseVersion(versionString) if err != nil { - t.Errorf("ParseVersion() produced an unexpected error: %+v", err) + t.Errorf("ParseVersion produced an unexpected error: %+v", err) } if expected != test { - t.Errorf("ParseVersion() did not return the expected Version."+ + t.Errorf("ParseVersion did not return the expected Version."+ "\nexpected: %+v\nreceived: %+v", expected, test) } } @@ -119,7 +119,7 @@ func TestParseVersion_Error(t *testing.T) { for str, expectedErr := range testStrings { _, err := ParseVersion(str) if err == nil || !strings.Contains(err.Error(), expectedErr) { - t.Errorf("ParseVersion() did not produce the expected error for \"%s\"."+ + t.Errorf("ParseVersion did not produce the expected error for \"%s\"."+ "\nexpected: %s\nreceived: %+v", str, expectedErr, err) } } @@ -137,7 +137,7 @@ func TestIsCompatible(t *testing.T) { for i, v := range testValues { if !IsCompatible(v.required, v.current) { - t.Errorf("IsCompatible() incorectly determined the current version"+ + t.Errorf("IsCompatible incorectly determined the current version"+ "is not comptabile with the required version (%d)."+ "\nrequired: %s\ncurrent: %s", i, v.required, v.current) } @@ -155,7 +155,7 @@ func TestIsCompatible_Failure(t *testing.T) { for i, v := range testValues { if IsCompatible(v.required, v.current) { - t.Errorf("IsCompatible() incorectly determined the current version"+ + t.Errorf("IsCompatible incorectly determined the current version"+ "is comptabile with the required version (%d)."+ "\nrequired: %s\ncurrent: %s", i, v.required, v.current) } @@ -173,7 +173,7 @@ func TestEqual_Same(t *testing.T) { for i, v := range testValues { if !Equal(v.a, v.b) { - t.Errorf("Equal() determined the versions are not equal (%d)."+ + t.Errorf("Equal determined the versions are not equal (%d)."+ "\na: %s\nb: %s", i, v.a, v.b) } } @@ -191,7 +191,7 @@ func TestEqual_Different(t *testing.T) { for i, v := range testValues { if Equal(v.a, v.b) { - t.Errorf("Equal() determined the versions are equal (%d)."+ + t.Errorf("Equal determined the versions are equal (%d)."+ "\na: %s\nb: %s", i, v.a, v.b) } } @@ -216,7 +216,7 @@ func TestCmp(t *testing.T) { for i, v := range testValues { test := Cmp(v.a, v.b) if v.expected != test { - t.Errorf("Cmp() did not return the expected value for %s and %s (%d)."+ + t.Errorf("Cmp did not return the expected value for %s and %s (%d)."+ "\nexpected: %d\nreceived: %d", v.a, v.b, i, v.expected, test) } }