github.com/pkg/sftp@v1.13.6/internal/encoding/ssh/filexfer/attrs_test.go (about) 1 package sshfx 2 3 import ( 4 "bytes" 5 "testing" 6 ) 7 8 func TestAttributes(t *testing.T) { 9 const ( 10 size uint64 = 0x123456789ABCDEF0 11 uid = 1000 12 gid = 100 13 perms FileMode = 0x87654321 14 atime = 0x2A2B2C2D 15 mtime = 0x42434445 16 ) 17 18 extAttr := ExtendedAttribute{ 19 Type: "foo", 20 Data: "bar", 21 } 22 23 attr := &Attributes{ 24 Size: size, 25 UID: uid, 26 GID: gid, 27 Permissions: perms, 28 ATime: atime, 29 MTime: mtime, 30 ExtendedAttributes: []ExtendedAttribute{ 31 extAttr, 32 }, 33 } 34 35 type test struct { 36 name string 37 flags uint32 38 encoded []byte 39 } 40 41 tests := []test{ 42 { 43 name: "empty", 44 encoded: []byte{ 45 0x00, 0x00, 0x00, 0x00, 46 }, 47 }, 48 { 49 name: "size", 50 flags: AttrSize, 51 encoded: []byte{ 52 0x00, 0x00, 0x00, 0x01, 53 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 54 }, 55 }, 56 { 57 name: "uidgid", 58 flags: AttrUIDGID, 59 encoded: []byte{ 60 0x00, 0x00, 0x00, 0x02, 61 0x00, 0x00, 0x03, 0xE8, 62 0x00, 0x00, 0x00, 100, 63 }, 64 }, 65 { 66 name: "permissions", 67 flags: AttrPermissions, 68 encoded: []byte{ 69 0x00, 0x00, 0x00, 0x04, 70 0x87, 0x65, 0x43, 0x21, 71 }, 72 }, 73 { 74 name: "acmodtime", 75 flags: AttrACModTime, 76 encoded: []byte{ 77 0x00, 0x00, 0x00, 0x08, 78 0x2A, 0x2B, 0x2C, 0x2D, 79 0x42, 0x43, 0x44, 0x45, 80 }, 81 }, 82 { 83 name: "extended", 84 flags: AttrExtended, 85 encoded: []byte{ 86 0x80, 0x00, 0x00, 0x00, 87 0x00, 0x00, 0x00, 0x01, 88 0x00, 0x00, 0x00, 0x03, 'f', 'o', 'o', 89 0x00, 0x00, 0x00, 0x03, 'b', 'a', 'r', 90 }, 91 }, 92 { 93 name: "size uidgid permisssions acmodtime extended", 94 flags: AttrSize | AttrUIDGID | AttrPermissions | AttrACModTime | AttrExtended, 95 encoded: []byte{ 96 0x80, 0x00, 0x00, 0x0F, 97 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 98 0x00, 0x00, 0x03, 0xE8, 99 0x00, 0x00, 0x00, 100, 100 0x87, 0x65, 0x43, 0x21, 101 0x2A, 0x2B, 0x2C, 0x2D, 102 0x42, 0x43, 0x44, 0x45, 103 0x00, 0x00, 0x00, 0x01, 104 0x00, 0x00, 0x00, 0x03, 'f', 'o', 'o', 105 0x00, 0x00, 0x00, 0x03, 'b', 'a', 'r', 106 }, 107 }, 108 } 109 110 for _, tt := range tests { 111 attr := *attr 112 113 t.Run(tt.name, func(t *testing.T) { 114 attr.Flags = tt.flags 115 116 buf, err := attr.MarshalBinary() 117 if err != nil { 118 t.Fatal("unexpected error:", err) 119 } 120 121 if !bytes.Equal(buf, tt.encoded) { 122 t.Fatalf("MarshalBinary() = %X, but wanted %X", buf, tt.encoded) 123 } 124 125 attr = Attributes{} 126 127 if err := attr.UnmarshalBinary(buf); err != nil { 128 t.Fatal("unexpected error:", err) 129 } 130 131 if attr.Flags != tt.flags { 132 t.Errorf("UnmarshalBinary(): Flags was %x, but wanted %x", attr.Flags, tt.flags) 133 } 134 135 if attr.Flags&AttrSize != 0 && attr.Size != size { 136 t.Errorf("UnmarshalBinary(): Size was %x, but wanted %x", attr.Size, size) 137 } 138 139 if attr.Flags&AttrUIDGID != 0 { 140 if attr.UID != uid { 141 t.Errorf("UnmarshalBinary(): UID was %x, but wanted %x", attr.UID, uid) 142 } 143 144 if attr.GID != gid { 145 t.Errorf("UnmarshalBinary(): GID was %x, but wanted %x", attr.GID, gid) 146 } 147 } 148 149 if attr.Flags&AttrPermissions != 0 && attr.Permissions != perms { 150 t.Errorf("UnmarshalBinary(): Permissions was %#v, but wanted %#v", attr.Permissions, perms) 151 } 152 153 if attr.Flags&AttrACModTime != 0 { 154 if attr.ATime != atime { 155 t.Errorf("UnmarshalBinary(): ATime was %x, but wanted %x", attr.ATime, atime) 156 } 157 158 if attr.MTime != mtime { 159 t.Errorf("UnmarshalBinary(): MTime was %x, but wanted %x", attr.MTime, mtime) 160 } 161 } 162 163 if attr.Flags&AttrExtended != 0 { 164 extAttrs := attr.ExtendedAttributes 165 166 if count := len(extAttrs); count != 1 { 167 t.Fatalf("UnmarshalBinary(): len(ExtendedAttributes) was %d, but wanted %d", count, 1) 168 } 169 170 if got := extAttrs[0]; got != extAttr { 171 t.Errorf("UnmarshalBinary(): ExtendedAttributes[0] was %#v, but wanted %#v", got, extAttr) 172 } 173 } 174 }) 175 } 176 } 177 178 func TestNameEntry(t *testing.T) { 179 const ( 180 filename = "foo" 181 longname = "bar" 182 perms FileMode = 0x87654321 183 ) 184 185 e := &NameEntry{ 186 Filename: filename, 187 Longname: longname, 188 Attrs: Attributes{ 189 Flags: AttrPermissions, 190 Permissions: perms, 191 }, 192 } 193 194 buf, err := e.MarshalBinary() 195 if err != nil { 196 t.Fatal("unexpected error:", err) 197 } 198 199 want := []byte{ 200 0x00, 0x00, 0x00, 0x03, 'f', 'o', 'o', 201 0x00, 0x00, 0x00, 0x03, 'b', 'a', 'r', 202 0x00, 0x00, 0x00, 0x04, 203 0x87, 0x65, 0x43, 0x21, 204 } 205 206 if !bytes.Equal(buf, want) { 207 t.Fatalf("MarshalBinary() = %X, but wanted %X", buf, want) 208 } 209 210 *e = NameEntry{} 211 212 if err := e.UnmarshalBinary(buf); err != nil { 213 t.Fatal("unexpected error:", err) 214 } 215 216 if e.Filename != filename { 217 t.Errorf("UnmarhsalFrom(): Filename was %q, but expected %q", e.Filename, filename) 218 } 219 220 if e.Longname != longname { 221 t.Errorf("UnmarhsalFrom(): Longname was %q, but expected %q", e.Longname, longname) 222 } 223 224 if e.Attrs.Flags != AttrPermissions { 225 t.Errorf("UnmarshalBinary(): Attrs.Flag was %#x, but expected %#x", e.Attrs.Flags, AttrPermissions) 226 } 227 228 if e.Attrs.Permissions != perms { 229 t.Errorf("UnmarshalBinary(): Attrs.Permissions was %#v, but expected %#v", e.Attrs.Permissions, perms) 230 } 231 }