github.com/mutagen-io/mutagen@v0.18.0-rc1/pkg/encoding/common_test.go (about)

     1  package encoding
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"os"
     7  	"testing"
     8  )
     9  
    10  // testMessageJSON is a test structure to use for encoding tests using JSON.
    11  type testMessageJSON struct {
    12  	// Name represents a person's name.
    13  	Name string
    14  	// Age represent's a person's age.
    15  	Age uint
    16  }
    17  
    18  const (
    19  	// testMessageJSONString is the JSON-encoded form of the JSON test data.
    20  	testMessageJSONString = `{"Name":"George","Age":67}`
    21  	// testMessageJSONName is the JSON test name.
    22  	testMessageJSONName = "George"
    23  	// testMessageJSONAge is the JSON test age.
    24  	testMessageJSONAge = 67
    25  )
    26  
    27  // TestLoadAndUnmarshalNonExistentPath tests that loading fails from a
    28  // non-existent path.
    29  func TestLoadAndUnmarshalNonExistentPath(t *testing.T) {
    30  	if !os.IsNotExist(LoadAndUnmarshal("/this/does/not/exist", nil)) {
    31  		t.Error("expected LoadAndUnmarshal to pass through non-existence errors")
    32  	}
    33  }
    34  
    35  // TestLoadAndUnmarshalDirectory tests that loading fails from a directory.
    36  func TestLoadAndUnmarshalDirectory(t *testing.T) {
    37  	// Compute the path to the user's home directory.
    38  	homeDirectory, err := os.UserHomeDir()
    39  	if err != nil {
    40  		t.Fatal("unable to compute home directory:", err)
    41  	}
    42  
    43  	// Perform the test.
    44  	if LoadAndUnmarshal(homeDirectory, nil) == nil {
    45  		t.Error("expected LoadAndUnmarshal error when loading directory")
    46  	}
    47  }
    48  
    49  // TestLoadAndUnmarshalUnmarshalFail tests that unmarshaling fails if the
    50  // unmarshaling callback fails.
    51  func TestLoadAndUnmarshalUnmarshalFail(t *testing.T) {
    52  	// Create an empty temporary file and defer its cleanup.
    53  	file, err := os.CreateTemp("", "mutagen_encoding")
    54  	if err != nil {
    55  		t.Fatal("unable to create temporary file:", err)
    56  	} else if err = file.Close(); err != nil {
    57  		t.Fatal("unable to close temporary file:", err)
    58  	}
    59  	defer os.Remove(file.Name())
    60  
    61  	// Create a broken unmarshaling function.
    62  	unmarshal := func(_ []byte) error {
    63  		return errors.New("unmarshal failed")
    64  	}
    65  
    66  	// Attempt to load and unmarshal using a broken unmarshaling function.
    67  	if LoadAndUnmarshal(file.Name(), unmarshal) == nil {
    68  		t.Error("expected LoadAndUnmarshal to return an error")
    69  	}
    70  }
    71  
    72  // TestLoadAndUnmarshal tests that loading and unmarshaling succeed.
    73  func TestLoadAndUnmarshal(t *testing.T) {
    74  	// Write the test JSON to a temporary file and defer its cleanup.
    75  	file, err := os.CreateTemp("", "mutagen_encoding")
    76  	if err != nil {
    77  		t.Fatal("unable to create temporary file:", err)
    78  	} else if _, err = file.Write([]byte(testMessageJSONString)); err != nil {
    79  		t.Fatal("unable to write data to temporary file:", err)
    80  	} else if err = file.Close(); err != nil {
    81  		t.Fatal("unable to close temporary file:", err)
    82  	}
    83  	defer os.Remove(file.Name())
    84  
    85  	// Create an unmarshaling function.
    86  	value := &testMessageJSON{}
    87  	unmarshal := func(data []byte) error {
    88  		return json.Unmarshal(data, value)
    89  	}
    90  
    91  	// Attempt to load and unmarshal.
    92  	if err := LoadAndUnmarshal(file.Name(), unmarshal); err != nil {
    93  		t.Fatal("LoadAndUnmarshal failed:", err)
    94  	}
    95  
    96  	// Verify test value names.
    97  	if value.Name != testMessageJSONName {
    98  		t.Error("test message name mismatch:", value.Name, "!=", testMessageJSONName)
    99  	}
   100  	if value.Age != testMessageJSONAge {
   101  		t.Error("test message age mismatch:", value.Age, "!=", testMessageJSONAge)
   102  	}
   103  }
   104  
   105  // TestMarshalAndSaveMarshalFail tests that marshaling fails if the marshaling
   106  // callback fails.
   107  func TestMarshalAndSaveMarshalFail(t *testing.T) {
   108  	// Create an empty temporary file and defer its cleanup.
   109  	file, err := os.CreateTemp("", "mutagen_encoding")
   110  	if err != nil {
   111  		t.Fatal("unable to create temporary file:", err)
   112  	} else if err = file.Close(); err != nil {
   113  		t.Fatal("unable to close temporary file:", err)
   114  	}
   115  	defer os.Remove(file.Name())
   116  
   117  	// Create a broken marshaling function.
   118  	marshal := func() ([]byte, error) {
   119  		return nil, errors.New("marshal failed")
   120  	}
   121  
   122  	// Attempt to marshal and save using a broken unmarshaling function.
   123  	if MarshalAndSave(file.Name(), marshal) == nil {
   124  		t.Error("expected MarshalAndSave to return an error")
   125  	}
   126  }
   127  
   128  // TestMarshalAndSaveOverDirectory tests that saving over a directory fails.
   129  func TestMarshalAndSaveOverDirectory(t *testing.T) {
   130  	// Create a marshaling function.
   131  	marshal := func() ([]byte, error) {
   132  		return []byte{0}, nil
   133  	}
   134  
   135  	// Attempt to marshal and save over a directory.
   136  	if MarshalAndSave(t.TempDir(), marshal) == nil {
   137  		t.Error("expected MarshalAndSave to return an error")
   138  	}
   139  }
   140  
   141  // TestMarshalAndSave tests that marshaling and saving succeed.
   142  func TestMarshalAndSave(t *testing.T) {
   143  	// Create an empty temporary file and defer its cleanup.
   144  	file, err := os.CreateTemp("", "mutagen_encoding")
   145  	if err != nil {
   146  		t.Fatal("unable to create temporary file:", err)
   147  	} else if err = file.Close(); err != nil {
   148  		t.Fatal("unable to close temporary file:", err)
   149  	}
   150  	defer os.Remove(file.Name())
   151  
   152  	// Create a marshaling function.
   153  	value := &testMessageJSON{Name: testMessageJSONName, Age: testMessageJSONAge}
   154  	marshal := func() ([]byte, error) {
   155  		return json.Marshal(value)
   156  	}
   157  
   158  	// Attempt to marshal and save.
   159  	if err := MarshalAndSave(file.Name(), marshal); err != nil {
   160  		t.Fatal("MarshalAndSave failed:", err)
   161  	}
   162  
   163  	// Read the contents of the file and ensure they match what's expected.
   164  	// TODO: Are we relying too much on the implementation details of the JSON
   165  	// encoder here?
   166  	contents, err := os.ReadFile(file.Name())
   167  	if err != nil {
   168  		t.Fatal("unable to read saved contents:", err)
   169  	} else if string(contents) != testMessageJSONString {
   170  		t.Error("marshaled contents do not match expected:", string(contents), "!=", testMessageJSONString)
   171  	}
   172  }