github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/protocol/keybase1/extras_test.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package keybase1 5 6 import ( 7 "errors" 8 "fmt" 9 "strings" 10 "testing" 11 "time" 12 13 "github.com/stretchr/testify/require" 14 ) 15 16 func TestTime(t *testing.T) { 17 var time1 time.Time 18 kbTime1 := ToTime(time1) 19 if kbTime1 != 0 { 20 t.Fatalf("Protocol marshaling from zero time failed") 21 } 22 time2 := FromTime(kbTime1) 23 if !time2.IsZero() { 24 t.Fatalf("Protocol marshaling to zero time failed") 25 } 26 27 now := time.Now() 28 kbNow := ToTime(now) 29 rev := FromTime(kbNow) 30 31 if rev.Unix() != now.Unix() { 32 t.Errorf("keybase time messed up: now = %s, rev = %s", now, rev) 33 } 34 } 35 36 func Test0TimeConversion(t *testing.T) { 37 require.Equal(t, UnixTime(0), ToUnixTime(time.Time{})) 38 require.Equal(t, Time(0), ToTime(time.Time{})) 39 require.Equal(t, time.Time{}, FromUnixTime(UnixTime(0))) 40 require.Equal(t, time.Time{}, FromTime(Time(0))) 41 } 42 43 func TestTimeConversions(t *testing.T) { 44 const longForm = "Jan 2, 2006 at 3:04pm (MST)" 45 constTime, err := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)") 46 require.NoError(t, err) 47 48 // add an offset to test precision below a second 49 constTimeWithOffset := constTime.Add(5 * time.Nanosecond) 50 51 times := []time.Time{ 52 {}, 53 time.Now(), 54 time.Now().AddDate(1000, 0, 0), // in a thousand years 55 time.Now().AddDate(10000, 0, 0), // in 10 thousand years 56 time.Now().AddDate(-3000, 0, 0), // 3 thousand years ago 57 constTime, 58 constTime.AddDate(1000, 0, 0), 59 constTime.AddDate(10000, 0, 0), 60 constTime.AddDate(-3000, 0, 0), 61 constTime.Add(12345678 * time.Second), 62 constTime.Add(3 * time.Millisecond), 63 constTime.Add(3 * time.Nanosecond), 64 constTimeWithOffset, 65 constTimeWithOffset.AddDate(1000, 0, 0), 66 constTimeWithOffset.AddDate(10000, 0, 0), 67 constTimeWithOffset.AddDate(-3000, 0, 0), 68 constTimeWithOffset.Add(12345678 * time.Second), 69 } 70 71 assertTimesEqualSec := func(t1, t2 time.Time) { 72 require.Equal(t, t1.Unix(), t2.Unix(), "expected %v and %v to be equal (with up to a second precision)", t1, t2) 73 } 74 assertTimesEqualMSec := func(t1, t2 time.Time) { 75 assertTimesEqualSec(t1, t2) 76 require.True(t, (t1.Nanosecond()-t2.Nanosecond()) < 1e6, "expected %v and %v to be equal (with up to a millisecond precision)", t1, t2) 77 require.True(t, (t2.Nanosecond()-t1.Nanosecond()) < 1e6, "expected %v and %v to be equal (with up to a millisecond precision)", t1, t2) 78 } 79 assertTimesEqualStrict := func(t1, t2 time.Time) { 80 require.True(t, t1.Equal(t2), "expected %v and %v to be equal", t1, t2) 81 } 82 83 for _, tm := range times { 84 kbTime := ToTime(tm) 85 tRev := FromTime(kbTime) 86 // conversion to Time are only precise up to a millisecond 87 assertTimesEqualMSec(tm, tRev) 88 if tm.Nanosecond() == 0 { 89 assertTimesEqualStrict(tm, tRev) 90 } 91 92 kbUnixTime := ToUnixTime(tm) 93 tUnixRev := FromUnixTime(kbUnixTime) 94 // conversion to UnixTime are only precise up to a second 95 assertTimesEqualSec(tm, tUnixRev) 96 if tm.Nanosecond() == 0 { 97 assertTimesEqualStrict(tm, tUnixRev) 98 } 99 } 100 } 101 102 // IsUser and co. should return false and 103 // not crash on arbitrary input. 104 func TestUserOrTeamIDChecking(t *testing.T) { 105 var invalidIDTestCases = [6]string{ 106 "", " ", "%%@#$", "223123", 107 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 108 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 109 } 110 var validUserIDTestCases = [4]string{ 111 "bd9e818f230819d3ecc813522c71f600", 112 "bd9e818f230819d3ecc813522c71f619", 113 "2721c9d9a247028cf51efa0760af6d00", 114 "2721c9d9a247028cf51efa0760af6d19", 115 } 116 var validTeamIDTestCases = [2]string{ 117 "bd9e818f230819d3ecc813522c71f624", 118 "2721c9d9a247028cf51efa0760af6d24", 119 } 120 var validSubteamIDTestCases = [2]string{ 121 "bd9e818f230819d3ecc813522c71f625", 122 "2721c9d9a247028cf51efa0760af6d25", 123 } 124 125 for _, idCase := range invalidIDTestCases { 126 ut := UserOrTeamID(idCase) 127 if ut.IsUser() || ut.IsTeam() || ut.IsSubteam() || ut.IsTeamOrSubteam() { 128 t.Errorf("Invalid ID %s is incorrectly marked valid.", idCase) 129 } 130 } 131 for _, idCase := range validUserIDTestCases { 132 ut := UserOrTeamID(idCase) 133 if !ut.IsUser() { 134 t.Errorf("Valid UserID %s is incorrectly marked invalid.", idCase) 135 } 136 if ut.IsTeam() || ut.IsSubteam() || ut.IsTeamOrSubteam() { 137 t.Errorf("Valid UserID %s is incorrectly marked as valid for another kind of ID.", idCase) 138 } 139 } 140 for _, idCase := range validTeamIDTestCases { 141 ut := UserOrTeamID(idCase) 142 if !ut.IsTeam() || !ut.IsTeamOrSubteam() { 143 t.Errorf("Valid TeamID %s is incorrectly marked invalid.", idCase) 144 } 145 if ut.IsUser() || ut.IsSubteam() { 146 t.Errorf("Valid TeamID %s is incorrectly marked as valid for another kind of ID.", idCase) 147 } 148 } 149 for _, idCase := range validSubteamIDTestCases { 150 ut := UserOrTeamID(idCase) 151 if !ut.IsSubteam() || !ut.IsTeamOrSubteam() { 152 t.Errorf("Valid SubteamID %s is incorrectly marked invalid.", idCase) 153 } 154 if ut.IsUser() || ut.IsTeam() { 155 t.Errorf("Valid SubteamID %s is incorrectly marked as valid for another kind of ID.", idCase) 156 } 157 } 158 } 159 160 func TestTeamNameFromString(t *testing.T) { 161 formatMsg := "Keybase team names must be letters (a-z), numbers, and underscores. Also, they can't start with underscores or use double underscores, to avoid confusion." 162 subteamMsg := "Could not parse name as team; bad name component " 163 lenMsg := "team names must be between 2 and 16 characters long" 164 emptyMsg := "team names cannot be empty" 165 tests := []struct { 166 input string 167 name TeamName 168 err error 169 }{ 170 {"aabb", TeamName{Parts: []TeamNamePart{stringToTeamNamePart("aabb")}}, nil}, 171 {"aa.BB.cc.DD", TeamName{Parts: []TeamNamePart{stringToTeamNamePart("aa"), stringToTeamNamePart("bb"), stringToTeamNamePart("cc"), stringToTeamNamePart("dd")}}, nil}, 172 {"a & b", TeamName{}, errors.New(formatMsg)}, 173 {" aa", TeamName{}, errors.New(formatMsg)}, 174 {"a__a", TeamName{}, errors.New(formatMsg)}, 175 {"_aa", TeamName{}, errors.New(formatMsg)}, 176 {"a-a", TeamName{}, errors.New(formatMsg)}, 177 {"cc.a & b", TeamName{}, errors.New(subteamMsg + "\"a & b\": " + formatMsg)}, 178 {"", TeamName{}, errors.New(emptyMsg)}, 179 {"aaa..bbb", TeamName{}, errors.New(subteamMsg + "\"\": " + emptyMsg)}, 180 {"aabbccddeeff00112233", TeamName{}, errors.New(lenMsg)}, 181 {"a", TeamName{}, errors.New(lenMsg)}, 182 {"aa.bb.cc.aabbccddeeff00112233", TeamName{}, errors.New(subteamMsg + "\"aabbccddeeff00112233\": " + lenMsg)}, 183 } 184 for i, tc := range tests { 185 nm, err := TeamNameFromString(tc.input) 186 if err == nil { 187 if tc.err != nil { 188 t.Fatalf("expected an error in test case %d", i) 189 } 190 if nm.IsNil() { 191 t.Fatalf("expected a non-nil TeamName since no error in test case %d", i) 192 } 193 if !nm.Eq(tc.name) { 194 t.Fatalf("failed name equality at test case %d", i) 195 } 196 } else { 197 if tc.err == nil { 198 t.Fatalf("got an error, but non expected at test case %d", i) 199 } 200 if tc.err.Error() != err.Error() { 201 t.Fatalf("bad error string at test case %d: %s != %s", i, tc.err.Error(), err.Error()) 202 } 203 } 204 } 205 } 206 207 func TestRedact(t *testing.T) { 208 cmd1 := "keybase fs ls anything really here" 209 rcmd1 := fmt.Sprintf("keybase fs %s", redactedReplacer) 210 arg := ClientDetails{ 211 Argv: strings.Split(cmd1, " ")} 212 arg.Redact() 213 require.Equal(t, strings.Split(rcmd1, " "), arg.Argv) 214 215 cmd2 := "keybase whatever command paperkey --another-flag" 216 arg = ClientDetails{ 217 Argv: strings.Split(cmd2, " ")} 218 arg.Redact() 219 require.Equal(t, strings.Split(cmd2, " "), arg.Argv) 220 }