once_test.gno

4.45 Kb ยท 231 lines
  1package once
  2
  3import (
  4	"errors"
  5	"testing"
  6)
  7
  8func TestOnce_Do(t *testing.T) {
  9	counter := 0
 10	once := New()
 11
 12	increment := func() {
 13		counter++
 14	}
 15
 16	// First call should execute
 17	once.Do(increment)
 18	if counter != 1 {
 19		t.Errorf("expected counter to be 1, got %d", counter)
 20	}
 21
 22	// Second call should not execute
 23	once.Do(increment)
 24	if counter != 1 {
 25		t.Errorf("expected counter to still be 1, got %d", counter)
 26	}
 27}
 28
 29func TestOnce_DoErr(t *testing.T) {
 30	once := New()
 31	expectedErr := errors.New("test error")
 32
 33	fn := func() error {
 34		return expectedErr
 35	}
 36
 37	// First call should return error
 38	if err := once.DoErr(fn); err != expectedErr {
 39		t.Errorf("expected error %v, got %v", expectedErr, err)
 40	}
 41
 42	// Second call should return same error
 43	if err := once.DoErr(fn); err != expectedErr {
 44		t.Errorf("expected error %v, got %v", expectedErr, err)
 45	}
 46}
 47
 48func TestOnce_DoOrPanic(t *testing.T) {
 49	once := New()
 50	executed := false
 51
 52	fn := func() {
 53		executed = true
 54	}
 55
 56	// First call should execute
 57	once.DoOrPanic(fn)
 58	if !executed {
 59		t.Error("function should have executed")
 60	}
 61
 62	// Second call should panic
 63	defer func() {
 64		if r := recover(); r == nil {
 65			t.Error("expected panic on second execution")
 66		}
 67	}()
 68	once.DoOrPanic(fn)
 69}
 70
 71func TestOnce_DoValue(t *testing.T) {
 72	once := New()
 73	expected := "test value"
 74	counter := 0
 75
 76	fn := func() any {
 77		counter++
 78		return expected
 79	}
 80
 81	// First call should return value
 82	if result := once.DoValue(fn); result != expected {
 83		t.Errorf("expected %v, got %v", expected, result)
 84	}
 85
 86	// Second call should return cached value
 87	if result := once.DoValue(fn); result != expected {
 88		t.Errorf("expected %v, got %v", expected, result)
 89	}
 90
 91	if counter != 1 {
 92		t.Errorf("function should have executed only once, got %d executions", counter)
 93	}
 94}
 95
 96func TestOnce_DoValueErr(t *testing.T) {
 97	once := New()
 98	expectedVal := "test value"
 99	expectedErr := errors.New("test error")
100	counter := 0
101
102	fn := func() (any, error) {
103		counter++
104		return expectedVal, expectedErr
105	}
106
107	// First call should return value and error
108	val, err := once.DoValueErr(fn)
109	if val != expectedVal || err != expectedErr {
110		t.Errorf("expected (%v, %v), got (%v, %v)", expectedVal, expectedErr, val, err)
111	}
112
113	// Second call should return cached value and error
114	val, err = once.DoValueErr(fn)
115	if val != expectedVal || err != expectedErr {
116		t.Errorf("expected (%v, %v), got (%v, %v)", expectedVal, expectedErr, val, err)
117	}
118
119	if counter != 1 {
120		t.Errorf("function should have executed only once, got %d executions", counter)
121	}
122}
123
124func TestOnce_Reset(t *testing.T) {
125	once := New()
126	counter := 0
127
128	fn := func() {
129		counter++
130	}
131
132	once.Do(fn)
133	if counter != 1 {
134		t.Errorf("expected counter to be 1, got %d", counter)
135	}
136
137	once.Reset()
138	once.Do(fn)
139	if counter != 2 {
140		t.Errorf("expected counter to be 2 after reset, got %d", counter)
141	}
142}
143
144func TestOnce_IsDone(t *testing.T) {
145	once := New()
146
147	if once.IsDone() {
148		t.Error("new Once instance should not be done")
149	}
150
151	once.Do(func() {})
152
153	if !once.IsDone() {
154		t.Error("Once instance should be done after execution")
155	}
156}
157
158func TestOnce_Error(t *testing.T) {
159	once := New()
160	expectedErr := errors.New("test error")
161
162	if err := once.Error(); err != nil {
163		t.Errorf("expected nil error, got %v", err)
164	}
165
166	once.DoErr(func() error {
167		return expectedErr
168	})
169
170	if err := once.Error(); err != expectedErr {
171		t.Errorf("expected error %v, got %v", expectedErr, err)
172	}
173}
174
175func TestOnce_Value(t *testing.T) {
176	once := New()
177
178	// Test unexecuted state
179	val, err := once.Value()
180	if err != ErrNotExecuted {
181		t.Errorf("expected ErrNotExecuted, got %v", err)
182	}
183	if val != nil {
184		t.Errorf("expected nil value, got %v", val)
185	}
186
187	// Test after execution
188	expected := "test value"
189	once.DoValue(func() any {
190		return expected
191	})
192
193	val, err = once.Value()
194	if err != nil {
195		t.Errorf("expected nil error, got %v", err)
196	}
197	if val != expected {
198		t.Errorf("expected value %v, got %v", expected, val)
199	}
200}
201
202func TestOnce_DoValueErr_Panic_MarkedDone(t *testing.T) {
203	once := New()
204	count := 0
205	fn := func() (any, error) {
206		count++
207		panic("panic")
208	}
209	var r any
210	func() {
211		defer func() { r = recover() }()
212		once.DoValueErr(fn)
213	}()
214	if r == nil {
215		t.Error("expected panic on first call")
216	}
217	if !once.IsDone() {
218		t.Error("expected once to be marked as done after panic")
219	}
220	r = nil
221	func() {
222		defer func() { r = recover() }()
223		once.DoValueErr(fn)
224	}()
225	if r != nil {
226		t.Error("expected no panic on subsequent call")
227	}
228	if count != 1 {
229		t.Errorf("expected count to be 1, got %d", count)
230	}
231}