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  }