github.com/tc-hib/go-winres@v0.3.4-0.20240411120550-c4d55a3dfc2e/main_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "crypto/md5" 6 "io" 7 "io/ioutil" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "testing" 12 ) 13 14 const tmpDir = "_testdata/tmp" 15 16 func Test_Extract(t *testing.T) { 17 a := os.Args 18 defer func() { os.Args = a }() 19 20 f := makeTmpDir(t) 21 defer f() 22 23 os.Args = []string{"./go-winres.exe", "extract", "--dir", "_testdata/tmp", "_testdata/rh.exe"} 24 main() 25 if loadJSON(t, "winres.json") != jsonRHM { 26 t.Error("json is different (json manifest)") 27 } 28 checkFile(t, "#1_0000.ico", []byte{0x00, 0x24, 0x99, 0x66, 0x72, 0xaf, 0x62, 0x12, 0x35, 0x22, 0x9b, 0x7b, 0x2, 0x2f, 0xe5, 0x94}) 29 checkFile(t, "APP_040C.ico", []byte{0xdd, 0xaf, 0x55, 0xb5, 0xd7, 0x3c, 0x65, 0xc3, 0x59, 0xb7, 0x3a, 0x39, 0x48, 0x62, 0xb3, 0x10}) 30 checkFile(t, "APP_0409.ico", []byte{0xee, 0x29, 0x1d, 0xaa, 0xc1, 0x3d, 0x24, 0xfc, 0xc5, 0xe, 0x64, 0x71, 0x44, 0xf0, 0x1e, 0x46}) 31 checkFile(t, "CURSOR_0000.cur", []byte{0x9f, 0x41, 0xe3, 0x26, 0xcc, 0x10, 0xb1, 0xed, 0xd9, 0x96, 0x38, 0x59, 0xc6, 0x93, 0x37, 0x9e}) 32 checkFile(t, "PNG_CUR-64X128_0000.png", []byte{0x40, 0x83, 0x52, 0xdb, 0x5, 0xe7, 0xc2, 0x32, 0x5b, 0xc1, 0x40, 0x15, 0x5b, 0x16, 0x9f, 0x4d}) 33 checkFile(t, "ICON16_0000.bmp", []byte{0xd7, 0x0c, 0xa6, 0x11, 0x23, 0xf6, 0x81, 0xef, 0xaa, 0xd3, 0x01, 0x61, 0x5f, 0x3e, 0x68, 0x1a}) 34 } 35 36 func Test_Init(t *testing.T) { 37 a := os.Args 38 defer func() { os.Args = a }() 39 40 f := makeTmpDir(t) 41 defer f() 42 43 func() { 44 f := moveToTmpDir(t) 45 defer f() 46 47 os.Args = []string{"./go-winres.exe", "init"} 48 main() 49 50 s, err := os.Stat("winres/winres.json") 51 if err != nil || s.Size() == 0 { 52 t.Fatal(err) 53 } 54 s, err = os.Stat("winres/icon.png") 55 if err != nil || s.Size() == 0 { 56 t.Fatal(err) 57 } 58 s, err = os.Stat("winres/icon16.png") 59 if err != nil || s.Size() == 0 { 60 t.Fatal(err) 61 } 62 }() 63 } 64 65 func Test_Extract_XMLManifest(t *testing.T) { 66 a := os.Args 67 defer func() { os.Args = a }() 68 69 f := makeTmpDir(t) 70 defer f() 71 72 os.Args = []string{"./go-winres.exe", "extract", "--dir", "_testdata/tmp", "--xml-manifest", "_testdata/rh.exe"} 73 main() 74 if loadJSON(t, "winres.json") != jsonRH { 75 t.Error("json is different (xml manifest)") 76 } 77 checkFile(t, "#1_0000.manifest", []byte{0x21, 0x19, 0x26, 0x2f, 0x8a, 0x5b, 0x5f, 0x64, 0x0e, 0x6e, 0xe7, 0x01, 0x20, 0xdb, 0xd2, 0x05}) 78 checkFile(t, "#1_0000.ico", []byte{0x00, 0x24, 0x99, 0x66, 0x72, 0xaf, 0x62, 0x12, 0x35, 0x22, 0x9b, 0x7b, 0x2, 0x2f, 0xe5, 0x94}) 79 checkFile(t, "APP_040C.ico", []byte{0xdd, 0xaf, 0x55, 0xb5, 0xd7, 0x3c, 0x65, 0xc3, 0x59, 0xb7, 0x3a, 0x39, 0x48, 0x62, 0xb3, 0x10}) 80 checkFile(t, "APP_0409.ico", []byte{0xee, 0x29, 0x1d, 0xaa, 0xc1, 0x3d, 0x24, 0xfc, 0xc5, 0xe, 0x64, 0x71, 0x44, 0xf0, 0x1e, 0x46}) 81 checkFile(t, "CURSOR_0000.cur", []byte{0x9f, 0x41, 0xe3, 0x26, 0xcc, 0x10, 0xb1, 0xed, 0xd9, 0x96, 0x38, 0x59, 0xc6, 0x93, 0x37, 0x9e}) 82 checkFile(t, "PNG_CUR-64X128_0000.png", []byte{0x40, 0x83, 0x52, 0xdb, 0x5, 0xe7, 0xc2, 0x32, 0x5b, 0xc1, 0x40, 0x15, 0x5b, 0x16, 0x9f, 0x4d}) 83 checkFile(t, "ICON16_0000.bmp", []byte{0xd7, 0x0c, 0xa6, 0x11, 0x23, 0xf6, 0x81, 0xef, 0xaa, 0xd3, 0x01, 0x61, 0x5f, 0x3e, 0x68, 0x1a}) 84 } 85 86 func Test_Patch(t *testing.T) { 87 a := os.Args 88 defer func() { os.Args = a }() 89 90 f := makeTmpDir(t) 91 defer f() 92 93 copyFile(t, "_testdata/vs0.exe", "_testdata/tmp/temp.exe") 94 os.Args = []string{"./go-winres.exe", "patch", "--in", "_testdata/icons.json", "--product-version", "1.2.3.4", "_testdata/tmp/temp.exe"} 95 main() 96 checkFile(t, "temp.exe", []byte{0xae, 0x96, 0xc0, 0xfd, 0x7a, 0x9c, 0x95, 0xab, 0xd8, 0xe1, 0x8e, 0x55, 0x91, 0xd2, 0xbc, 0xa0}) 97 checkFile(t, "temp.exe.bak", []byte{0x29, 0x13, 0xa7, 0xc5, 0x4a, 0xf9, 0x47, 0xef, 0xd6, 0x4f, 0x37, 0xc5, 0x62, 0xba, 0xd4, 0x39}) 98 } 99 100 func Test_Patch_Add(t *testing.T) { 101 a := os.Args 102 defer func() { os.Args = a }() 103 104 f := makeTmpDir(t) 105 defer f() 106 107 copyFile(t, "_testdata/rh.exe", "_testdata/tmp/temp.exe") 108 os.Args = []string{"./go-winres.exe", "patch", "--in", "_testdata/icons.json", "--no-backup", "_testdata/tmp/temp.exe"} 109 main() 110 checkFile(t, "temp.exe", []byte{0xc4, 0x4a, 0x7f, 0x74, 0xe9, 0x0c, 0xfb, 0x37, 0x9a, 0x62, 0x82, 0x28, 0xbc, 0x68, 0x77, 0xc2}) 111 if _, err := os.Stat("_testdata/tmp/temp.exe.bak"); err == nil { 112 t.Error("temp.exe.bak should not exist") 113 } 114 } 115 116 func Test_Patch_Replace(t *testing.T) { 117 a := os.Args 118 defer func() { os.Args = a }() 119 120 f := makeTmpDir(t) 121 defer f() 122 123 copyFile(t, "_testdata/rh.exe", "_testdata/tmp/temp.exe") 124 125 os.Args = []string{"./go-winres.exe", "patch", "--in", "_testdata/test.json", "--delete", "--file-version", "1.2", "_testdata/tmp/temp.exe"} 126 main() 127 checkFile(t, "temp.exe", []byte{0x67, 0x5b, 0xc5, 0x8a, 0xb3, 0x48, 0xfc, 0xf0, 0xaf, 0xea, 0xa5, 0xc0, 0x5f, 0xba, 0x8d, 0xc3}) 128 checkFile(t, "temp.exe.bak", []byte{0x79, 0xbc, 0x0f, 0x27, 0x2b, 0x3f, 0x82, 0x69, 0xfa, 0xc1, 0x42, 0x1d, 0xc7, 0xdb, 0x68, 0x6c}) 129 } 130 131 func Test_GitTag(t *testing.T) { 132 a := os.Args 133 defer func() { os.Args = a }() 134 135 f := makeTmpDir(t) 136 defer f() 137 138 copyFile(t, "_testdata/vs0.exe", "_testdata/tmp/temp1.exe") 139 copyFile(t, "_testdata/rh.exe", "_testdata/tmp/temp2.exe") 140 141 func() { 142 f := moveToTmpDir(t) 143 defer f() 144 145 createTmpGitTag(t, "v1.42.3.24") 146 147 os.Args = []string{"./go-winres.exe", "patch", "--in", "../icons.json", "--file-version", "git-tag", "temp1.exe"} 148 main() 149 os.Args = []string{"./go-winres.exe", "patch", "--in", "../test.json", "--product-version", "git-tag", "temp2.exe"} 150 main() 151 }() 152 153 checkFile(t, "temp1.exe", []byte{0x70, 0xb9, 0x34, 0x4d, 0x62, 0xe3, 0xdb, 0x62, 0xe9, 0xb5, 0xc8, 0x85, 0x48, 0xaa, 0xe7, 0x65}) 154 checkFile(t, "temp2.exe", []byte{0xd9, 0x19, 0x0c, 0xc2, 0x72, 0x3c, 0xc4, 0x6b, 0x9e, 0x6e, 0xbe, 0x58, 0xb1, 0x26, 0xa7, 0x4b}) 155 } 156 157 func Test_Simply(t *testing.T) { 158 a := os.Args 159 defer func() { os.Args = a }() 160 161 f := makeTmpDir(t) 162 defer f() 163 164 os.Args = []string{ 165 "./go-winres.exe", 166 "simply", 167 "--arch", 168 " amd64, 386 , arm, arm64 ", 169 "--out", 170 "_testdata/tmp/simply", 171 "--product-version", 172 "v42.5.3.8 alpha", 173 "--file-version", 174 "1.2.3.4.5.6.7", 175 "--manifest", 176 "gui", 177 "--admin", 178 "--file-description", 179 "description", 180 "--product-name", 181 "Product name", 182 "--copyright", 183 "©", 184 "--original-filename", 185 "xxx.exe", 186 "--icon", 187 "_testdata/fr.ico", 188 } 189 main() 190 checkFile(t, "simply_windows_arm64.syso", []byte{0xb1, 0x1b, 0x8f, 0x79, 0xea, 0xac, 0x72, 0xae, 0x0e, 0x8a, 0xa6, 0xf2, 0x2c, 0x61, 0x10, 0x8d}) 191 checkFile(t, "simply_windows_arm.syso", []byte{0x66, 0xe5, 0x83, 0xd1, 0x62, 0xe8, 0x51, 0x10, 0xb1, 0x2e, 0x5b, 0xdc, 0x57, 0x23, 0xd9, 0x8c}) 192 checkFile(t, "simply_windows_amd64.syso", []byte{0xc4, 0xfe, 0x6e, 0x34, 0xb2, 0xe5, 0x9e, 0x93, 0x00, 0xf7, 0x1f, 0x5a, 0x62, 0x9b, 0xea, 0x37}) 193 checkFile(t, "simply_windows_386.syso", []byte{0xa0, 0x02, 0x97, 0x0f, 0xc9, 0x0d, 0x2c, 0x28, 0xf1, 0x23, 0xd0, 0x31, 0x6b, 0x3f, 0x0d, 0x73}) 194 } 195 196 func Test_SimplyGitTag(t *testing.T) { 197 a := os.Args 198 defer func() { os.Args = a }() 199 200 f := makeTmpDir(t) 201 defer f() 202 203 copyFile(t, "_testdata/cur-32x64.png", "_testdata/tmp/icon.png") 204 205 func() { 206 f := moveToTmpDir(t) 207 defer f() 208 209 createTmpGitTag(t, "v1.42.3.24") 210 211 os.Args = []string{"./go-winres.exe", "simply", "--arch", "amd64", "--file-version", "git-tag", "--icon", "icon.png"} 212 main() 213 os.Args = []string{"./go-winres.exe", "simply", "--arch", "arm64", "--product-version", "git-tag", "--icon", "icon.png"} 214 main() 215 }() 216 217 checkFile(t, "rsrc_windows_amd64.syso", []byte{0x66, 0x4b, 0xca, 0x71, 0xad, 0x35, 0x0f, 0x91, 0xca, 0xdf, 0xd1, 0x11, 0x9b, 0x5d, 0x42, 0xc7}) 218 checkFile(t, "rsrc_windows_arm64.syso", []byte{0x29, 0xa1, 0xde, 0x27, 0xf2, 0x5a, 0x96, 0x4e, 0xc2, 0x59, 0xbf, 0xa3, 0x60, 0x11, 0xe0, 0xed}) 219 } 220 221 func Test_Simply_PNGIcon(t *testing.T) { 222 a := os.Args 223 defer func() { os.Args = a }() 224 225 f := makeTmpDir(t) 226 defer f() 227 228 os.Args = []string{ 229 "./go-winres.exe", 230 "simply", 231 "--out", 232 "_testdata/tmp/rsrc.syso", 233 "--arch", 234 "386", 235 "--no-suffix", 236 "--icon", 237 "icon.png", 238 } 239 main() 240 checkFile(t, "rsrc.syso", []byte{0x8e, 0xc8, 0xe5, 0x44, 0x8e, 0x93, 0xd2, 0xab, 0x84, 0x10, 0x67, 0x16, 0xac, 0x70, 0x1a, 0xad}) 241 } 242 243 func Test_Make(t *testing.T) { 244 a := os.Args 245 defer func() { os.Args = a }() 246 247 f := makeTmpDir(t) 248 defer f() 249 250 os.Args = []string{ 251 "./go-winres.exe", 252 "make", 253 "--arch", 254 " amd64, 386 , arm, arm64 ", 255 "--out", 256 "_testdata/tmp/make", 257 "--product-version", 258 "v42.5.3.8 alpha", 259 "--file-version", 260 "1.2.3.4.5.6.7", 261 "--in", 262 "_testdata/test.json", 263 } 264 main() 265 checkFile(t, "make_windows_arm64.syso", []byte{0x5e, 0xc2, 0xf1, 0xb3, 0x6c, 0x49, 0x56, 0x25, 0xa8, 0x1e, 0x68, 0x49, 0x5b, 0x92, 0x3d, 0x9c}) 266 checkFile(t, "make_windows_arm.syso", []byte{0x9e, 0xdf, 0x5a, 0x08, 0x38, 0x95, 0x38, 0x07, 0x13, 0xa1, 0x14, 0xba, 0xd7, 0x35, 0xbf, 0x11}) 267 checkFile(t, "make_windows_amd64.syso", []byte{0x05, 0x6f, 0xa2, 0x0a, 0x06, 0xef, 0x64, 0x7f, 0xcd, 0x69, 0x07, 0x63, 0xc2, 0xa8, 0xc1, 0xa1}) 268 checkFile(t, "make_windows_386.syso", []byte{0x35, 0xcc, 0x28, 0x6e, 0x57, 0x1c, 0x58, 0xf4, 0xaf, 0x82, 0x8a, 0xf1, 0x85, 0x5a, 0x9e, 0x61}) 269 } 270 271 func copyFile(t *testing.T, src, dst string) { 272 s, err := os.Open(src) 273 if err != nil { 274 t.Fatal(err) 275 } 276 defer s.Close() 277 278 d, err := os.Create(dst) 279 if err != nil { 280 t.Fatal(err) 281 } 282 defer d.Close() 283 284 io.Copy(d, s) 285 } 286 287 func makeTmpDir(t *testing.T) func() { 288 os.RemoveAll(tmpDir) 289 290 err := os.MkdirAll(tmpDir, 0666) 291 if err != nil { 292 t.Fatal(err) 293 } 294 295 return func() { 296 err = os.RemoveAll(tmpDir) 297 if err != nil { 298 t.Log(err) 299 } 300 } 301 } 302 303 func moveToTmpDir(t *testing.T) func() { 304 dir, err := os.Getwd() 305 if err != nil { 306 t.Fatal(err) 307 } 308 309 err = os.Chdir(tmpDir) 310 if err != nil { 311 t.Fatal(err) 312 } 313 314 return func() { 315 err = os.Chdir(dir) 316 if err != nil { 317 t.Fatal(err) 318 } 319 } 320 } 321 322 func createTmpGitTag(t *testing.T, tag string) { 323 err := ioutil.WriteFile("tmp.txt", []byte{}, 0666) 324 if err != nil { 325 t.Fatal(err) 326 } 327 cmd := exec.Command("git", "init") 328 err = cmd.Run() 329 if err != nil { 330 t.Fatal(err) 331 } 332 cmd = exec.Command("git", "add", "tmp.txt") 333 err = cmd.Run() 334 if err != nil { 335 t.Fatal(err) 336 } 337 cmd = exec.Command("git", "commit", "-m", ".") 338 err = cmd.Run() 339 if err != nil { 340 t.Fatal(err) 341 } 342 cmd = exec.Command("git", "tag", "-a", tag, "-m", ".") 343 err = cmd.Run() 344 if err != nil { 345 t.Fatal(err) 346 } 347 } 348 349 func loadJSON(t *testing.T, file string) string { 350 d, err := ioutil.ReadFile(filepath.Join(tmpDir, file)) 351 if err != nil { 352 t.Fatal(err) 353 } 354 return string(d) 355 } 356 357 func checkFile(t *testing.T, file string, hash []byte) { 358 f, err := os.Open(filepath.Join(tmpDir, file)) 359 if err != nil { 360 t.Fatal(err) 361 } 362 defer f.Close() 363 364 h := md5.New() 365 io.Copy(h, f) 366 if !bytes.Equal(h.Sum(nil), hash) { 367 t.Errorf("wrong hash for %s %x", file, h.Sum(nil)) 368 } 369 } 370 371 // language=json 372 const jsonRHM = `{ 373 "PNG": { 374 "CUR-64X128": { 375 "0000": "PNG_CUR-64X128_0000.png" 376 } 377 }, 378 "RT_BITMAP": { 379 "ICON16": { 380 "0000": "ICON16_0000.bmp" 381 } 382 }, 383 "RT_GROUP_CURSOR": { 384 "CURSOR": { 385 "0000": "CURSOR_0000.cur" 386 } 387 }, 388 "RT_GROUP_ICON": { 389 "#1": { 390 "0000": "#1_0000.ico" 391 }, 392 "APP": { 393 "0409": "APP_0409.ico", 394 "040C": "APP_040C.ico" 395 } 396 }, 397 "RT_MANIFEST": { 398 "#1": { 399 "0000": { 400 "identity": {}, 401 "description": "", 402 "minimum-os": "win7", 403 "execution-level": "", 404 "ui-access": false, 405 "auto-elevate": false, 406 "dpi-awareness": "system", 407 "disable-theming": false, 408 "disable-window-filtering": false, 409 "high-resolution-scrolling-aware": false, 410 "ultra-high-resolution-scrolling-aware": false, 411 "long-path-aware": false, 412 "printer-driver-isolation": false, 413 "gdi-scaling": false, 414 "segment-heap": false, 415 "use-common-controls-v6": false 416 } 417 } 418 }, 419 "RT_VERSION": { 420 "#1": { 421 "0409": { 422 "fixed": { 423 "file_version": "1.2.3.4", 424 "product_version": "5.6.7.8" 425 }, 426 "info": { 427 "0409": { 428 "CompanyName": "WinRes Corp.", 429 "FileDescription": "WinRes", 430 "FileVersion": "1.2.3.4 (Build.42.42)", 431 "InternalName": "winres", 432 "LegalCopyright": "© WinRes.", 433 "OriginalFilename": "WINRES.EXE", 434 "ProductName": "WinRes CLI", 435 "ProductVersion": "5.6.7.8" 436 } 437 } 438 } 439 } 440 } 441 }` 442 443 // language=json 444 const jsonRH = `{ 445 "PNG": { 446 "CUR-64X128": { 447 "0000": "PNG_CUR-64X128_0000.png" 448 } 449 }, 450 "RT_BITMAP": { 451 "ICON16": { 452 "0000": "ICON16_0000.bmp" 453 } 454 }, 455 "RT_GROUP_CURSOR": { 456 "CURSOR": { 457 "0000": "CURSOR_0000.cur" 458 } 459 }, 460 "RT_GROUP_ICON": { 461 "#1": { 462 "0000": "#1_0000.ico" 463 }, 464 "APP": { 465 "0409": "APP_0409.ico", 466 "040C": "APP_040C.ico" 467 } 468 }, 469 "RT_MANIFEST": { 470 "#1": { 471 "0000": "#1_0000.manifest" 472 } 473 }, 474 "RT_VERSION": { 475 "#1": { 476 "0409": { 477 "fixed": { 478 "file_version": "1.2.3.4", 479 "product_version": "5.6.7.8" 480 }, 481 "info": { 482 "0409": { 483 "CompanyName": "WinRes Corp.", 484 "FileDescription": "WinRes", 485 "FileVersion": "1.2.3.4 (Build.42.42)", 486 "InternalName": "winres", 487 "LegalCopyright": "© WinRes.", 488 "OriginalFilename": "WINRES.EXE", 489 "ProductName": "WinRes CLI", 490 "ProductVersion": "5.6.7.8" 491 } 492 } 493 } 494 } 495 } 496 }`