Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api: ensure all enumeration types implement UnmarshalText #515

Merged
merged 1 commit into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions pkg/forwarding/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,29 @@ func (s Status) MarshalText() ([]byte, error) {
return []byte(result), nil
}

// UnmarshalText implements encoding.TextUnmarshaler.UnmarshalText.
func (s *Status) UnmarshalText(textBytes []byte) error {
// Convert the bytes to a string.
text := string(textBytes)

// Convert to a forwarding status.
switch text {
case "disconnected":
*s = Status_Disconnected
case "connecting-source":
*s = Status_ConnectingSource
case "connecting-destination":
*s = Status_ConnectingDestination
case "forwarding":
*s = Status_ForwardingConnections
default:
return fmt.Errorf("unknown forwarding status: %s", text)
}

// Success.
return nil
}

// ensureValid ensures that EndpointState's invariants are respected.
func (s *EndpointState) ensureValid() error {
// A nil endpoint state is not valid.
Expand Down
40 changes: 39 additions & 1 deletion pkg/forwarding/state_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
package forwarding

// TODO: Implement.
import (
"testing"
)

// TestStatusUnmarshal tests that unmarshaling from a string specification
// succeeeds for Status.
func TestStatusUnmarshal(t *testing.T) {
// Set up test cases.
testCases := []struct {
text string
expected Status
expectFailure bool
}{
{"", Status_Disconnected, true},
{"asdf", Status_Disconnected, true},
{"disconnected", Status_Disconnected, false},
{"connecting-source", Status_ConnectingSource, false},
{"connecting-destination", Status_ConnectingDestination, false},
{"forwarding", Status_ForwardingConnections, false},
}

// Process test cases.
for _, testCase := range testCases {
var status Status
if err := status.UnmarshalText([]byte(testCase.text)); err != nil {
if !testCase.expectFailure {
t.Errorf("unable to unmarshal text (%s): %s", testCase.text, err)
}
} else if testCase.expectFailure {
t.Error("unmarshaling succeeded unexpectedly for text:", testCase.text)
} else if status != testCase.expected {
t.Errorf(
"unmarshaled status (%s) does not match expected (%s)",
status,
testCase.expected,
)
}
}
}
28 changes: 28 additions & 0 deletions pkg/synchronization/core/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package core
import (
"bytes"
"errors"
"fmt"
"strings"

"github.com/mutagen-io/mutagen/pkg/synchronization/core/fastpath"
Expand Down Expand Up @@ -38,6 +39,33 @@ func (k EntryKind) MarshalText() ([]byte, error) {
return []byte(result), nil
}

// UnmarshalText implements encoding.TextUnmarshaler.UnmarshalText.
func (k *EntryKind) UnmarshalText(textBytes []byte) error {
// Convert the bytes to a string.
text := string(textBytes)

// Convert to a forwarding status.
switch text {
case "directory":
*k = EntryKind_Directory
case "file":
*k = EntryKind_File
case "symlink":
*k = EntryKind_SymbolicLink
case "untracked":
*k = EntryKind_Untracked
case "problematic":
*k = EntryKind_Problematic
case "phantom-directory":
*k = EntryKind_PhantomDirectory
default:
return fmt.Errorf("unknown entry kind: %s", text)
}

// Success.
return nil
}

// EnsureValid ensures that Entry's invariants are respected. If synchronizable
// is true, then unsynchronizable content will be considered invalid.
func (e *Entry) EnsureValid(synchronizable bool) error {
Expand Down
38 changes: 38 additions & 0 deletions pkg/synchronization/core/entry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,44 @@ func TestEntryKindSynchronizable(t *testing.T) {
}
}

// TestEntryKindUnmarshal tests that unmarshaling from a string specification
// succeeeds for EntryKind.
func TestEntryKindUnmarshal(t *testing.T) {
// Set up test cases.
testCases := []struct {
text string
expected EntryKind
expectFailure bool
}{
{"", EntryKind_Directory, true},
{"asdf", EntryKind_Directory, true},
{"directory", EntryKind_Directory, false},
{"file", EntryKind_File, false},
{"symlink", EntryKind_SymbolicLink, false},
{"untracked", EntryKind_Untracked, false},
{"problematic", EntryKind_Problematic, false},
{"phantom-directory", EntryKind_PhantomDirectory, false},
}

// Process test cases.
for _, testCase := range testCases {
var kind EntryKind
if err := kind.UnmarshalText([]byte(testCase.text)); err != nil {
if !testCase.expectFailure {
t.Errorf("unable to unmarshal text (%s): %s", testCase.text, err)
}
} else if testCase.expectFailure {
t.Error("unmarshaling succeeded unexpectedly for text:", testCase.text)
} else if kind != testCase.expected {
t.Errorf(
"unmarshaled entry kind (%s) does not match expected (%s)",
kind,
testCase.expected,
)
}
}
}

func init() {
// Enable wildcard problem matching for tests.
entryEqualWildcardProblemMatch = true
Expand Down
43 changes: 43 additions & 0 deletions pkg/synchronization/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,49 @@ func (s Status) MarshalText() ([]byte, error) {
return []byte(result), nil
}

// UnmarshalText implements encoding.TextUnmarshaler.UnmarshalText.
func (s *Status) UnmarshalText(textBytes []byte) error {
// Convert the bytes to a string.
text := string(textBytes)

// Convert to a synchronization status.
switch text {
case "disconnected":
*s = Status_Disconnected
case "halted-on-root-emptied":
*s = Status_HaltedOnRootEmptied
case "halted-on-root-deletion":
*s = Status_HaltedOnRootDeletion
case "halted-on-root-type-change":
*s = Status_HaltedOnRootTypeChange
case "connecting-alpha":
*s = Status_ConnectingAlpha
case "connecting-beta":
*s = Status_ConnectingBeta
case "watching":
*s = Status_Watching
case "scanning":
*s = Status_Scanning
case "waiting-for-rescan":
*s = Status_WaitingForRescan
case "reconciling":
*s = Status_Reconciling
case "staging-alpha":
*s = Status_StagingAlpha
case "staging-beta":
*s = Status_StagingBeta
case "transitioning":
*s = Status_Transitioning
case "saving":
*s = Status_Saving
default:
return fmt.Errorf("unknown synchronization status: %s", text)
}

// Success.
return nil
}

// ensureValid ensures that EndpointState's invariants are respected.
func (s *EndpointState) ensureValid() error {
// A nil endpoint state is not valid.
Expand Down
50 changes: 49 additions & 1 deletion pkg/synchronization/state_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,51 @@
package synchronization

// TODO: Implement.
import (
"testing"
)

// TestStatusUnmarshal tests that unmarshaling from a string specification
// succeeeds for Status.
func TestStatusUnmarshal(t *testing.T) {
// Set up test cases.
testCases := []struct {
text string
expected Status
expectFailure bool
}{
{"", Status_Disconnected, true},
{"asdf", Status_Disconnected, true},
{"disconnected", Status_Disconnected, false},
{"halted-on-root-emptied", Status_HaltedOnRootEmptied, false},
{"halted-on-root-deletion", Status_HaltedOnRootDeletion, false},
{"halted-on-root-type-change", Status_HaltedOnRootTypeChange, false},
{"connecting-alpha", Status_ConnectingAlpha, false},
{"connecting-beta", Status_ConnectingBeta, false},
{"watching", Status_Watching, false},
{"scanning", Status_Scanning, false},
{"waiting-for-rescan", Status_WaitingForRescan, false},
{"reconciling", Status_Reconciling, false},
{"staging-alpha", Status_StagingAlpha, false},
{"staging-beta", Status_StagingBeta, false},
{"transitioning", Status_Transitioning, false},
{"saving", Status_Saving, false},
}

// Process test cases.
for _, testCase := range testCases {
var status Status
if err := status.UnmarshalText([]byte(testCase.text)); err != nil {
if !testCase.expectFailure {
t.Errorf("unable to unmarshal text (%s): %s", testCase.text, err)
}
} else if testCase.expectFailure {
t.Error("unmarshaling succeeded unexpectedly for text:", testCase.text)
} else if status != testCase.expected {
t.Errorf(
"unmarshaled status (%s) does not match expected (%s)",
status,
testCase.expected,
)
}
}
}
Loading