1// Copyright (C) MongoDB, Inc. 2017-present.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7package readpref
8
9import (
10	"testing"
11	"time"
12
13	"github.com/stretchr/testify/require"
14	"go.mongodb.org/mongo-driver/internal/testutil/assert"
15	"go.mongodb.org/mongo-driver/tag"
16)
17
18func TestPrimary(t *testing.T) {
19	require := require.New(t)
20	subject := Primary()
21
22	require.Equal(PrimaryMode, subject.Mode())
23	_, set := subject.MaxStaleness()
24	require.False(set)
25	require.Empty(subject.TagSets())
26}
27
28func TestPrimaryPreferred(t *testing.T) {
29	require := require.New(t)
30	subject := PrimaryPreferred()
31
32	require.Equal(PrimaryPreferredMode, subject.Mode())
33	_, set := subject.MaxStaleness()
34	require.False(set)
35	require.Empty(subject.TagSets())
36}
37
38func TestPrimaryPreferred_with_options(t *testing.T) {
39	require := require.New(t)
40	subject := PrimaryPreferred(
41		WithMaxStaleness(time.Duration(10)),
42		WithTags("a", "1", "b", "2"),
43	)
44
45	require.Equal(PrimaryPreferredMode, subject.Mode())
46	ms, set := subject.MaxStaleness()
47	require.True(set)
48	require.Equal(time.Duration(10), ms)
49	require.Equal([]tag.Set{{tag.Tag{Name: "a", Value: "1"}, tag.Tag{Name: "b", Value: "2"}}}, subject.TagSets())
50}
51
52func TestSecondaryPreferred(t *testing.T) {
53	require := require.New(t)
54	subject := SecondaryPreferred()
55
56	require.Equal(SecondaryPreferredMode, subject.Mode())
57	_, set := subject.MaxStaleness()
58	require.False(set)
59	require.Empty(subject.TagSets())
60}
61
62func TestSecondaryPreferred_with_options(t *testing.T) {
63	require := require.New(t)
64	subject := SecondaryPreferred(
65		WithMaxStaleness(time.Duration(10)),
66		WithTags("a", "1", "b", "2"),
67	)
68
69	require.Equal(SecondaryPreferredMode, subject.Mode())
70	ms, set := subject.MaxStaleness()
71	require.True(set)
72	require.Equal(time.Duration(10), ms)
73	require.Equal([]tag.Set{{tag.Tag{Name: "a", Value: "1"}, tag.Tag{Name: "b", Value: "2"}}}, subject.TagSets())
74}
75
76func TestSecondary(t *testing.T) {
77	require := require.New(t)
78	subject := Secondary()
79
80	require.Equal(SecondaryMode, subject.Mode())
81	_, set := subject.MaxStaleness()
82	require.False(set)
83	require.Empty(subject.TagSets())
84}
85
86func TestSecondary_with_options(t *testing.T) {
87	require := require.New(t)
88	subject := Secondary(
89		WithMaxStaleness(time.Duration(10)),
90		WithTags("a", "1", "b", "2"),
91	)
92
93	require.Equal(SecondaryMode, subject.Mode())
94	ms, set := subject.MaxStaleness()
95	require.True(set)
96	require.Equal(time.Duration(10), ms)
97	require.Equal([]tag.Set{{tag.Tag{Name: "a", Value: "1"}, tag.Tag{Name: "b", Value: "2"}}}, subject.TagSets())
98}
99
100func TestNearest(t *testing.T) {
101	require := require.New(t)
102	subject := Nearest()
103
104	require.Equal(NearestMode, subject.Mode())
105	_, set := subject.MaxStaleness()
106	require.False(set)
107	require.Empty(subject.TagSets())
108}
109
110func TestNearest_with_options(t *testing.T) {
111	require := require.New(t)
112	subject := Nearest(
113		WithMaxStaleness(time.Duration(10)),
114		WithTags("a", "1", "b", "2"),
115	)
116
117	require.Equal(NearestMode, subject.Mode())
118	ms, set := subject.MaxStaleness()
119	require.True(set)
120	require.Equal(time.Duration(10), ms)
121	require.Equal([]tag.Set{{tag.Tag{Name: "a", Value: "1"}, tag.Tag{Name: "b", Value: "2"}}}, subject.TagSets())
122}
123
124func TestHedge(t *testing.T) {
125	t.Run("hedge specified with primary mode errors", func(t *testing.T) {
126		_, err := New(PrimaryMode, WithHedgeEnabled(true))
127		assert.Equal(t, errInvalidReadPreference, err, "expected error %v, got %v", errInvalidReadPreference, err)
128	})
129	t.Run("valid hedge document and mode succeeds", func(t *testing.T) {
130		rp, err := New(SecondaryMode, WithHedgeEnabled(true))
131		assert.Nil(t, err, "expected no error, got %v", err)
132		enabled := rp.HedgeEnabled()
133		assert.NotNil(t, enabled, "expected HedgeEnabled to return a non-nil value, got nil")
134		assert.True(t, *enabled, "expected HedgeEnabled to return true, got false")
135	})
136}
137
138func TestReadPref_String(t *testing.T) {
139	t.Run("ReadPref.String() with all options", func(t *testing.T) {
140		readPref := Nearest(
141			WithMaxStaleness(120*time.Second),
142			WithTagSets(tag.Set{{"a", "1"}, {"b", "2"}}, tag.Set{{"q", "5"}, {"r", "6"}}),
143			WithHedgeEnabled(true),
144		)
145		expected := "nearest(maxStaleness=2m0s tagSet=a=1,b=2 tagSet=q=5,r=6 hedgeEnabled=true)"
146		assert.Equal(t, expected, readPref.String(), "expected %q, got %q", expected, readPref.String())
147	})
148	t.Run("ReadPref.String() with one option", func(t *testing.T) {
149		readPref := Secondary(WithTags("a", "1", "b", "2"))
150		expected := "secondary(tagSet=a=1,b=2)"
151		assert.Equal(t, expected, readPref.String(), "expected %q, got %q", expected, readPref.String())
152	})
153	t.Run("ReadPref.String() with no options", func(t *testing.T) {
154		readPref := Primary()
155		expected := "primary"
156		assert.Equal(t, expected, readPref.String(), "expected %q, got %q", expected, readPref.String())
157	})
158}
159