github.com/noirx94/tendermintmp@v0.0.1/libs/os/os_test.go (about) 1 package os 2 3 import ( 4 "bytes" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "testing" 10 11 "github.com/stretchr/testify/require" 12 ) 13 14 func TestCopyFile(t *testing.T) { 15 tmpfile, err := ioutil.TempFile("", "example") 16 if err != nil { 17 t.Fatal(err) 18 } 19 defer os.Remove(tmpfile.Name()) 20 content := []byte("hello world") 21 if _, err := tmpfile.Write(content); err != nil { 22 t.Fatal(err) 23 } 24 25 copyfile := fmt.Sprintf("%s.copy", tmpfile.Name()) 26 if err := CopyFile(tmpfile.Name(), copyfile); err != nil { 27 t.Fatal(err) 28 } 29 if _, err := os.Stat(copyfile); os.IsNotExist(err) { 30 t.Fatal("copy should exist") 31 } 32 data, err := ioutil.ReadFile(copyfile) 33 if err != nil { 34 t.Fatal(err) 35 } 36 if !bytes.Equal(data, content) { 37 t.Fatalf("copy file content differs: expected %v, got %v", content, data) 38 } 39 os.Remove(copyfile) 40 } 41 42 func TestEnsureDir(t *testing.T) { 43 tmp, err := ioutil.TempDir("", "ensure-dir") 44 require.NoError(t, err) 45 defer os.RemoveAll(tmp) 46 47 // Should be possible to create a new directory. 48 err = EnsureDir(filepath.Join(tmp, "dir"), 0755) 49 require.NoError(t, err) 50 require.DirExists(t, filepath.Join(tmp, "dir")) 51 52 // Should succeed on existing directory. 53 err = EnsureDir(filepath.Join(tmp, "dir"), 0755) 54 require.NoError(t, err) 55 56 // Should fail on file. 57 err = ioutil.WriteFile(filepath.Join(tmp, "file"), []byte{}, 0644) 58 require.NoError(t, err) 59 err = EnsureDir(filepath.Join(tmp, "file"), 0755) 60 require.Error(t, err) 61 62 // Should allow symlink to dir. 63 err = os.Symlink(filepath.Join(tmp, "dir"), filepath.Join(tmp, "linkdir")) 64 require.NoError(t, err) 65 err = EnsureDir(filepath.Join(tmp, "linkdir"), 0755) 66 require.NoError(t, err) 67 68 // Should error on symlink to file. 69 err = os.Symlink(filepath.Join(tmp, "file"), filepath.Join(tmp, "linkfile")) 70 require.NoError(t, err) 71 err = EnsureDir(filepath.Join(tmp, "linkfile"), 0755) 72 require.Error(t, err) 73 } 74 75 // Ensure that using CopyFile does not truncate the destination file before 76 // the origin is positively a non-directory and that it is ready for copying. 77 // See https://github.com/tendermint/tendermint/issues/6427 78 func TestTrickedTruncation(t *testing.T) { 79 tmpDir, err := ioutil.TempDir(os.TempDir(), "pwn_truncate") 80 if err != nil { 81 t.Fatal(err) 82 } 83 defer os.Remove(tmpDir) 84 85 originalWALPath := filepath.Join(tmpDir, "wal") 86 originalWALContent := []byte("I AM BECOME DEATH, DESTROYER OF ALL WORLDS!") 87 if err := ioutil.WriteFile(originalWALPath, originalWALContent, 0755); err != nil { 88 t.Fatal(err) 89 } 90 91 // 1. Sanity check. 92 readWAL, err := ioutil.ReadFile(originalWALPath) 93 if err != nil { 94 t.Fatal(err) 95 } 96 if !bytes.Equal(readWAL, originalWALContent) { 97 t.Fatalf("Cannot proceed as the content does not match\nGot: %q\nWant: %q", readWAL, originalWALContent) 98 } 99 100 // 2. Now cause the truncation of the original file. 101 // It is absolutely legal to invoke os.Open on a directory. 102 if err := CopyFile(tmpDir, originalWALPath); err == nil { 103 t.Fatal("Expected an error") 104 } 105 106 // 3. Check the WAL's content 107 reReadWAL, err := ioutil.ReadFile(originalWALPath) 108 if err != nil { 109 t.Fatal(err) 110 } 111 if !bytes.Equal(reReadWAL, originalWALContent) { 112 t.Fatalf("Oops, the WAL's content was changed :(\nGot: %q\nWant: %q", reReadWAL, originalWALContent) 113 } 114 }