github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/fs/enum_test.go (about)

     1  package fs
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  type choices struct{}
    13  
    14  func (choices) Choices() []string {
    15  	return []string{
    16  		choiceA: "A",
    17  		choiceB: "B",
    18  		choiceC: "C",
    19  	}
    20  }
    21  
    22  type choice = Enum[choices]
    23  
    24  const (
    25  	choiceA choice = iota
    26  	choiceB
    27  	choiceC
    28  )
    29  
    30  // Check it satisfies the interfaces
    31  var (
    32  	_ flagger   = (*choice)(nil)
    33  	_ flaggerNP = choice(0)
    34  )
    35  
    36  func TestEnumString(t *testing.T) {
    37  	for _, test := range []struct {
    38  		in   choice
    39  		want string
    40  	}{
    41  		{choiceA, "A"},
    42  		{choiceB, "B"},
    43  		{choiceC, "C"},
    44  		{choice(100), "Unknown(100)"},
    45  	} {
    46  		got := test.in.String()
    47  		assert.Equal(t, test.want, got)
    48  	}
    49  }
    50  
    51  func TestEnumType(t *testing.T) {
    52  	assert.Equal(t, "A|B|C", choiceA.Type())
    53  }
    54  
    55  // Enum with Type() on the choices
    56  type choicestype struct{}
    57  
    58  func (choicestype) Choices() []string {
    59  	return []string{}
    60  }
    61  
    62  func (choicestype) Type() string {
    63  	return "potato"
    64  }
    65  
    66  type choicetype = Enum[choicestype]
    67  
    68  func TestEnumTypeWithFunction(t *testing.T) {
    69  	assert.Equal(t, "potato", choicetype(0).Type())
    70  }
    71  
    72  func TestEnumHelp(t *testing.T) {
    73  	assert.Equal(t, "A, B, C", choice(0).Help())
    74  }
    75  
    76  func TestEnumSet(t *testing.T) {
    77  	for _, test := range []struct {
    78  		in   string
    79  		want choice
    80  		err  bool
    81  	}{
    82  		{"A", choiceA, false},
    83  		{"B", choiceB, false},
    84  		{"C", choiceC, false},
    85  		{"D", choice(100), true},
    86  	} {
    87  		var got choice
    88  		err := got.Set(test.in)
    89  		if test.err {
    90  			require.Error(t, err)
    91  		} else {
    92  			require.NoError(t, err)
    93  			assert.Equal(t, test.want, got)
    94  		}
    95  	}
    96  }
    97  
    98  func TestEnumScan(t *testing.T) {
    99  	var v choice
   100  	n, err := fmt.Sscan(" A ", &v)
   101  	require.NoError(t, err)
   102  	assert.Equal(t, 1, n)
   103  	assert.Equal(t, choiceA, v)
   104  }
   105  
   106  func TestEnumUnmarshalJSON(t *testing.T) {
   107  	for _, test := range []struct {
   108  		in   string
   109  		want choice
   110  		err  string
   111  	}{
   112  		{`"A"`, choiceA, ""},
   113  		{`"B"`, choiceB, ""},
   114  		{`0`, choiceA, ""},
   115  		{`1`, choiceB, ""},
   116  		{`"D"`, choice(0), `invalid choice "D" from: A, B, C`},
   117  		{`100`, choice(0), `100 is out of range: must be 0..3`},
   118  	} {
   119  		var got choice
   120  		err := json.Unmarshal([]byte(test.in), &got)
   121  		if test.err != "" {
   122  			require.Error(t, err, test.in)
   123  			assert.ErrorContains(t, err, test.err)
   124  		} else {
   125  			require.NoError(t, err, test.in)
   126  		}
   127  		assert.Equal(t, test.want, got, test.in)
   128  	}
   129  }
   130  
   131  func TestEnumMarshalJSON(t *testing.T) {
   132  	for _, test := range []struct {
   133  		in   choice
   134  		want string
   135  	}{
   136  		{choiceA, `"A"`},
   137  		{choiceB, `"B"`},
   138  	} {
   139  		got, err := json.Marshal(&test.in)
   140  		require.NoError(t, err)
   141  		assert.Equal(t, test.want, string(got), fmt.Sprintf("%#v", test.in))
   142  	}
   143  }