|
|
@@ -0,0 +1,88 @@
|
|
|
+// Copyright (C) 2017 The Syncthing Authors.
|
|
|
+//
|
|
|
+// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
+// You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
+
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "io/ioutil"
|
|
|
+ "os"
|
|
|
+ "path/filepath"
|
|
|
+ "testing"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+func TestAutoClosedFile(t *testing.T) {
|
|
|
+ os.RemoveAll("_autoclose")
|
|
|
+ defer os.RemoveAll("_autoclose")
|
|
|
+ os.Mkdir("_autoclose", 0755)
|
|
|
+ file := filepath.FromSlash("_autoclose/tmp")
|
|
|
+ data := []byte("hello, world\n")
|
|
|
+
|
|
|
+ // An autoclosed file that closes very quickly
|
|
|
+ ac := newAutoclosedFile(file, time.Millisecond, time.Millisecond)
|
|
|
+
|
|
|
+ // Write some data.
|
|
|
+ if _, err := ac.Write(data); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Wait for it to close
|
|
|
+ start := time.Now()
|
|
|
+ for {
|
|
|
+ time.Sleep(time.Millisecond)
|
|
|
+ ac.mut.Lock()
|
|
|
+ fd := ac.fd
|
|
|
+ ac.mut.Unlock()
|
|
|
+ if fd == nil {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if time.Since(start) > time.Second {
|
|
|
+ t.Fatal("File should have been closed after first write")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Write more data, which should be an append.
|
|
|
+ if _, err := ac.Write(data); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Close.
|
|
|
+ if err := ac.Close(); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // The file should have both writes in it.
|
|
|
+ bs, err := ioutil.ReadFile(file)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ if len(bs) != 2*len(data) {
|
|
|
+ t.Fatalf("Writes failed, expected %d bytes, not %d", 2*len(data), len(bs))
|
|
|
+ }
|
|
|
+
|
|
|
+ // Open the file again.
|
|
|
+ ac = newAutoclosedFile(file, time.Second, time.Second)
|
|
|
+
|
|
|
+ // Write something
|
|
|
+ if _, err := ac.Write(data); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // It should now contain only one write, because the first open
|
|
|
+ // should be a truncate.
|
|
|
+ bs, err = ioutil.ReadFile(file)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ if len(bs) != len(data) {
|
|
|
+ t.Fatalf("Write failed, expected %d bytes, not %d", len(data), len(bs))
|
|
|
+ }
|
|
|
+
|
|
|
+ // Close.
|
|
|
+ if err := ac.Close(); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+}
|