master
go 189 lines 4.66 KB
Raw
1 package commands
2
3 import (
4 "os"
5 "testing"
6 "time"
7
8 "github.com/stretchr/testify/assert"
9 )
10
11 func TestFormatMode(t *testing.T) {
12 t.Parallel()
13
14 tests := []struct {
15 name string
16 mode os.FileMode
17 expected string
18 }{
19 // File types
20 {
21 name: "regular file with rw-r--r--",
22 mode: 0644,
23 expected: "-rw-r--r--",
24 },
25 {
26 name: "regular file with rwxr-xr-x",
27 mode: 0755,
28 expected: "-rwxr-xr-x",
29 },
30 {
31 name: "regular file with no permissions",
32 mode: 0,
33 expected: "----------",
34 },
35 {
36 name: "regular file with full permissions",
37 mode: 0777,
38 expected: "-rwxrwxrwx",
39 },
40 {
41 name: "directory with rwxr-xr-x",
42 mode: os.ModeDir | 0755,
43 expected: "drwxr-xr-x",
44 },
45 {
46 name: "directory with rwx------",
47 mode: os.ModeDir | 0700,
48 expected: "drwx------",
49 },
50 {
51 name: "symlink with rwxrwxrwx",
52 mode: os.ModeSymlink | 0777,
53 expected: "lrwxrwxrwx",
54 },
55 {
56 name: "named pipe with rw-r--r--",
57 mode: os.ModeNamedPipe | 0644,
58 expected: "prw-r--r--",
59 },
60 {
61 name: "socket with rw-rw-rw-",
62 mode: os.ModeSocket | 0666,
63 expected: "srw-rw-rw-",
64 },
65 {
66 name: "block device with rw-rw----",
67 mode: os.ModeDevice | 0660,
68 expected: "brw-rw----",
69 },
70 {
71 name: "character device with rw-rw-rw-",
72 mode: os.ModeDevice | os.ModeCharDevice | 0666,
73 expected: "crw-rw-rw-",
74 },
75
76 // Special permission bits - setuid
77 {
78 name: "setuid with execute",
79 mode: os.ModeSetuid | 0755,
80 expected: "-rwsr-xr-x",
81 },
82 {
83 name: "setuid without execute",
84 mode: os.ModeSetuid | 0644,
85 expected: "-rwSr--r--",
86 },
87
88 // Special permission bits - setgid
89 {
90 name: "setgid with execute",
91 mode: os.ModeSetgid | 0755,
92 expected: "-rwxr-sr-x",
93 },
94 {
95 name: "setgid without execute",
96 mode: os.ModeSetgid | 0745,
97 expected: "-rwxr-Sr-x",
98 },
99
100 // Special permission bits - sticky
101 {
102 name: "sticky with execute",
103 mode: os.ModeSticky | 0755,
104 expected: "-rwxr-xr-t",
105 },
106 {
107 name: "sticky without execute",
108 mode: os.ModeSticky | 0754,
109 expected: "-rwxr-xr-T",
110 },
111
112 // Combined special bits
113 {
114 name: "setuid + setgid + sticky all with execute",
115 mode: os.ModeSetuid | os.ModeSetgid | os.ModeSticky | 0777,
116 expected: "-rwsrwsrwt",
117 },
118 {
119 name: "setuid + setgid + sticky none with execute",
120 mode: os.ModeSetuid | os.ModeSetgid | os.ModeSticky | 0666,
121 expected: "-rwSrwSrwT",
122 },
123
124 // Directory with special bits
125 {
126 name: "directory with sticky bit",
127 mode: os.ModeDir | os.ModeSticky | 0755,
128 expected: "drwxr-xr-t",
129 },
130 }
131
132 for _, tc := range tests {
133 t.Run(tc.name, func(t *testing.T) {
134 t.Parallel()
135 result := formatMode(tc.mode)
136 assert.Equal(t, tc.expected, result)
137 })
138 }
139 }
140
141 func TestFormatModTime(t *testing.T) {
142 t.Parallel()
143
144 t.Run("zero time returns dash", func(t *testing.T) {
145 t.Parallel()
146 result := formatModTime(time.Time{})
147 assert.Equal(t, "-", result)
148 })
149
150 t.Run("old time shows year format", func(t *testing.T) {
151 t.Parallel()
152 // Use a time clearly in the past (more than 6 months ago)
153 oldTime := time.Date(2020, time.March, 15, 10, 30, 0, 0, time.UTC)
154 result := formatModTime(oldTime)
155 // Format: "Jan 02 2006" (note: two spaces before year)
156 assert.Equal(t, "Mar 15 2020", result)
157 })
158
159 t.Run("very old time shows year format", func(t *testing.T) {
160 t.Parallel()
161 veryOldTime := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
162 result := formatModTime(veryOldTime)
163 assert.Equal(t, "Jan 01 2000", result)
164 })
165
166 t.Run("future time shows year format", func(t *testing.T) {
167 t.Parallel()
168 // Times more than 24h in the future should show year format
169 futureTime := time.Now().AddDate(1, 0, 0)
170 result := formatModTime(futureTime)
171 // Should contain the future year
172 assert.Contains(t, result, " ") // two spaces before year
173 assert.Regexp(t, `^[A-Z][a-z]{2} \d{2} \d{4}$`, result) // matches "Mon DD YYYY"
174 assert.Contains(t, result, futureTime.Format("2006")) // contains the year
175 })
176
177 t.Run("format lengths are consistent", func(t *testing.T) {
178 t.Parallel()
179 // Both formats should produce 12-character strings for alignment
180 oldTime := time.Date(2020, time.March, 15, 10, 30, 0, 0, time.UTC)
181 oldResult := formatModTime(oldTime)
182 assert.Len(t, oldResult, 12, "old time format should be 12 chars")
183
184 // Recent time: use 1 month ago to ensure it's always within the 6-month window
185 recentTime := time.Now().AddDate(0, -1, 0)
186 recentResult := formatModTime(recentTime)
187 assert.Len(t, recentResult, 12, "recent time format should be 12 chars")
188 })
189 }