Skip to content

Commit 581c896

Browse files
authored
Merge pull request #9 from cpunion/tests
add tests
2 parents 744c0be + d730a9b commit 581c896

19 files changed

+1075
-47
lines changed

bool.go

+4
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ func False() Bool {
3131
func (b Bool) Bool() bool {
3232
return C.PyObject_IsTrue(b.obj) != 0
3333
}
34+
35+
func (b Bool) Not() Bool {
36+
return MakeBool(!b.Bool())
37+
}

bool_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package gp
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestBool(t *testing.T) {
8+
// Test MakeBool
9+
b1 := MakeBool(true)
10+
if !b1.Bool() {
11+
t.Error("MakeBool(true) should return true")
12+
}
13+
14+
b2 := MakeBool(false)
15+
if b2.Bool() {
16+
t.Error("MakeBool(false) should return false")
17+
}
18+
19+
// Test True and False
20+
if !True().Bool() {
21+
t.Error("True() should return true")
22+
}
23+
24+
if False().Bool() {
25+
t.Error("False() should return false")
26+
}
27+
28+
// Test Not method
29+
if True().Not().Bool() {
30+
t.Error("True().Not() should return false")
31+
}
32+
33+
if !False().Not().Bool() {
34+
t.Error("False().Not() should return true")
35+
}
36+
}

bytes_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package gp
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
)
7+
8+
func TestBytesCreation(t *testing.T) {
9+
// Test BytesFromStr
10+
b1 := BytesFromStr("hello")
11+
if string(b1.Bytes()) != "hello" {
12+
t.Errorf("BytesFromStr: expected 'hello', got '%s'", string(b1.Bytes()))
13+
}
14+
15+
// Test MakeBytes
16+
data := []byte("world")
17+
b2 := MakeBytes(data)
18+
if !bytes.Equal(b2.Bytes(), data) {
19+
t.Errorf("MakeBytes: expected '%v', got '%v'", data, b2.Bytes())
20+
}
21+
}
22+
23+
func TestBytesDecode(t *testing.T) {
24+
// Test UTF-8 decode
25+
b := BytesFromStr("你好")
26+
if !bytes.Equal(b.Bytes(), []byte("你好")) {
27+
t.Errorf("BytesFromStr: expected '你好', got '%s'", string(b.Bytes()))
28+
}
29+
s := b.Decode("utf-8")
30+
if s.String() != "你好" {
31+
t.Errorf("Decode: expected '你好', got '%s'", s.String())
32+
}
33+
34+
// Test ASCII decode
35+
b2 := BytesFromStr("hello")
36+
s2 := b2.Decode("ascii")
37+
if s2.String() != "hello" {
38+
t.Errorf("Decode: expected 'hello', got '%s'", s2.String())
39+
}
40+
}
41+
42+
func TestBytesConversion(t *testing.T) {
43+
original := []byte{0x48, 0x65, 0x6c, 0x6c, 0x6f} // "Hello" in hex
44+
b := MakeBytes(original)
45+
46+
// Test conversion back to []byte
47+
result := b.Bytes()
48+
if !bytes.Equal(result, original) {
49+
t.Errorf("Bytes conversion: expected %v, got %v", original, result)
50+
}
51+
}

complex_test.go

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package gp
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestComplex(t *testing.T) {
8+
tests := []struct {
9+
name string
10+
input complex128
11+
wantReal float64
12+
wantImag float64
13+
}{
14+
{
15+
name: "zero complex",
16+
input: complex(0, 0),
17+
wantReal: 0,
18+
wantImag: 0,
19+
},
20+
{
21+
name: "positive real and imaginary",
22+
input: complex(3.14, 2.718),
23+
wantReal: 3.14,
24+
wantImag: 2.718,
25+
},
26+
{
27+
name: "negative real and imaginary",
28+
input: complex(-1.5, -2.5),
29+
wantReal: -1.5,
30+
wantImag: -2.5,
31+
},
32+
{
33+
name: "mixed signs",
34+
input: complex(-1.23, 4.56),
35+
wantReal: -1.23,
36+
wantImag: 4.56,
37+
},
38+
}
39+
40+
for _, tt := range tests {
41+
t.Run(tt.name, func(t *testing.T) {
42+
c := MakeComplex(tt.input)
43+
44+
// Test Real() method
45+
if got := c.Real(); got != tt.wantReal {
46+
t.Errorf("Complex.Real() = %v, want %v", got, tt.wantReal)
47+
}
48+
49+
// Test Imag() method
50+
if got := c.Imag(); got != tt.wantImag {
51+
t.Errorf("Complex.Imag() = %v, want %v", got, tt.wantImag)
52+
}
53+
54+
// Test Complex128() method
55+
if got := c.Complex128(); got != tt.input {
56+
t.Errorf("Complex.Complex128() = %v, want %v", got, tt.input)
57+
}
58+
})
59+
}
60+
}
61+
62+
func TestComplexZeroValue(t *testing.T) {
63+
// Create a proper zero complex number instead of using zero-value struct
64+
c := MakeComplex(complex(0, 0))
65+
66+
// Test that zero complex behaves correctly
67+
if got := c.Real(); got != 0 {
68+
t.Errorf("Zero Complex.Real() = %v, want 0", got)
69+
}
70+
if got := c.Imag(); got != 0 {
71+
t.Errorf("Zero Complex.Imag() = %v, want 0", got)
72+
}
73+
if got := c.Complex128(); got != 0 {
74+
t.Errorf("Zero Complex.Complex128() = %v, want 0", got)
75+
}
76+
}
77+
78+
func TestComplexNilHandling(t *testing.T) {
79+
var c Complex // zero-value struct with nil pointer
80+
defer func() {
81+
if r := recover(); r == nil {
82+
t.Error("Expected panic for nil pointer access, but got none")
83+
}
84+
}()
85+
86+
// This should panic
87+
_ = c.Real()
88+
}

dict.go

-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ func newDict(obj *PyObject) Dict {
1717
return Dict{newObject(obj)}
1818
}
1919

20-
func NewDict(obj *PyObject) Dict {
21-
return newDict(obj)
22-
}
23-
2420
func DictFromPairs(pairs ...any) Dict {
2521
if len(pairs)%2 != 0 {
2622
panic("DictFromPairs requires an even number of arguments")

dict_test.go

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
package gp
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestDictFromPairs(t *testing.T) {
8+
// Add panic test case
9+
t.Run("odd number of arguments", func(t *testing.T) {
10+
defer func() {
11+
if r := recover(); r == nil {
12+
t.Errorf("DictFromPairs() with odd number of arguments should panic")
13+
} else if r != "DictFromPairs requires an even number of arguments" {
14+
t.Errorf("Expected panic message 'DictFromPairs requires an even number of arguments', got '%v'", r)
15+
}
16+
}()
17+
18+
DictFromPairs("key1", "value1", "key2") // Should panic
19+
})
20+
21+
tests := []struct {
22+
name string
23+
pairs []any
24+
wantKeys []any
25+
wantVals []any
26+
}{
27+
{
28+
name: "string keys and values",
29+
pairs: []any{"key1", "value1", "key2", "value2"},
30+
wantKeys: []any{"key1", "key2"},
31+
wantVals: []any{"value1", "value2"},
32+
},
33+
{
34+
name: "mixed types",
35+
pairs: []any{"key1", 42, "key2", 3.14},
36+
wantKeys: []any{"key1", "key2"},
37+
wantVals: []any{42, 3.14},
38+
},
39+
}
40+
41+
for _, tt := range tests {
42+
t.Run(tt.name, func(t *testing.T) {
43+
dict := DictFromPairs(tt.pairs...)
44+
45+
// Verify each key-value pair
46+
for i := 0; i < len(tt.wantKeys); i++ {
47+
key := From(tt.wantKeys[i])
48+
val := dict.Get(key)
49+
if !ObjectsAreEqual(val, From(tt.wantVals[i])) {
50+
t.Errorf("DictFromPairs() got value %v for key %v, want %v",
51+
val, tt.wantKeys[i], tt.wantVals[i])
52+
}
53+
}
54+
})
55+
}
56+
}
57+
58+
func TestMakeDict(t *testing.T) {
59+
tests := []struct {
60+
name string
61+
m map[any]any
62+
}{
63+
{
64+
name: "string map",
65+
m: map[any]any{
66+
"key1": "value1",
67+
"key2": "value2",
68+
},
69+
},
70+
{
71+
name: "mixed types map",
72+
m: map[any]any{
73+
"int": 42,
74+
"float": 3.14,
75+
"string": "hello",
76+
},
77+
},
78+
}
79+
80+
for _, tt := range tests {
81+
t.Run(tt.name, func(t *testing.T) {
82+
dict := MakeDict(tt.m)
83+
84+
// Verify each key-value pair
85+
for k, v := range tt.m {
86+
key := From(k)
87+
got := dict.Get(key)
88+
if !ObjectsAreEqual(got, From(v)) {
89+
t.Errorf("MakeDict() got value %v for key %v, want %v", got, k, v)
90+
}
91+
}
92+
})
93+
}
94+
}
95+
96+
func TestDictSetGet(t *testing.T) {
97+
dict := DictFromPairs()
98+
99+
// Test Set and Get
100+
key := From("test_key")
101+
value := From("test_value")
102+
dict.Set(key, value)
103+
104+
got := dict.Get(key)
105+
if !ObjectsAreEqual(got, value) {
106+
t.Errorf("Dict.Get() got %v, want %v", got, value)
107+
}
108+
}
109+
110+
func TestDictSetGetString(t *testing.T) {
111+
dict := DictFromPairs()
112+
113+
// Test SetString and GetString
114+
value := From("test_value")
115+
dict.SetString("test_key", value)
116+
117+
got := dict.GetString("test_key")
118+
if !ObjectsAreEqual(got, value) {
119+
t.Errorf("Dict.GetString() got %v, want %v", got, value)
120+
}
121+
}
122+
123+
func TestDictDel(t *testing.T) {
124+
dict := DictFromPairs("test_key", "test_value")
125+
key := From("test_key")
126+
127+
// Verify key exists
128+
got := dict.Get(key)
129+
if !ObjectsAreEqual(got, From("test_value")) {
130+
t.Errorf("Before deletion, got %v, want %v", got, "test_value")
131+
}
132+
133+
// Delete the key
134+
dict.Del(key)
135+
136+
// After deletion, Get should return nil object
137+
got = dict.Get(key)
138+
if got.Obj() != nil {
139+
t.Errorf("After deletion, got %v, want nil", got)
140+
}
141+
}
142+
143+
func TestDictForEach(t *testing.T) {
144+
dict := DictFromPairs(
145+
"key1", "value1",
146+
"key2", "value2",
147+
"key3", "value3",
148+
)
149+
150+
count := 0
151+
expectedPairs := map[string]string{
152+
"key1": "value1",
153+
"key2": "value2",
154+
"key3": "value3",
155+
}
156+
157+
dict.ForEach(func(key, value Object) {
158+
count++
159+
k := key.String()
160+
v := value.String()
161+
if expectedVal, ok := expectedPairs[k]; !ok || expectedVal != v {
162+
t.Errorf("ForEach() unexpected pair: %v: %v", k, v)
163+
}
164+
})
165+
166+
if count != len(expectedPairs) {
167+
t.Errorf("ForEach() visited %d pairs, want %d", count, len(expectedPairs))
168+
}
169+
}
170+
171+
// Helper function to compare Python objects
172+
func ObjectsAreEqual(obj1, obj2 Object) bool {
173+
return obj1.String() == obj2.String()
174+
}

float.go

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ package gp
55
*/
66
import "C"
77

8+
// Float represents a Python float object. It provides methods to convert between
9+
// Go float types and Python float objects, as well as checking numeric properties.
810
type Float struct {
911
Object
1012
}
@@ -21,6 +23,10 @@ func (f Float) Float64() float64 {
2123
return float64(C.PyFloat_AsDouble(f.obj))
2224
}
2325

26+
func (f Float) Float32() float32 {
27+
return float32(C.PyFloat_AsDouble(f.obj))
28+
}
29+
2430
func (f Float) IsInteger() Bool {
2531
fn := Cast[Func](f.Attr("is_integer"))
2632
return Cast[Bool](fn.callNoArgs())

0 commit comments

Comments
 (0)