Skip to content

Commit

Permalink
Merge pull request #9 from cpunion/tests
Browse files Browse the repository at this point in the history
add tests
  • Loading branch information
cpunion authored Nov 3, 2024
2 parents 744c0be + d730a9b commit 581c896
Show file tree
Hide file tree
Showing 19 changed files with 1,075 additions and 47 deletions.
4 changes: 4 additions & 0 deletions bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ func False() Bool {
func (b Bool) Bool() bool {
return C.PyObject_IsTrue(b.obj) != 0
}

func (b Bool) Not() Bool {
return MakeBool(!b.Bool())
}
36 changes: 36 additions & 0 deletions bool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package gp

import (
"testing"
)

func TestBool(t *testing.T) {
// Test MakeBool
b1 := MakeBool(true)
if !b1.Bool() {
t.Error("MakeBool(true) should return true")
}

b2 := MakeBool(false)
if b2.Bool() {
t.Error("MakeBool(false) should return false")
}

// Test True and False
if !True().Bool() {
t.Error("True() should return true")
}

if False().Bool() {
t.Error("False() should return false")
}

// Test Not method
if True().Not().Bool() {
t.Error("True().Not() should return false")
}

if !False().Not().Bool() {
t.Error("False().Not() should return true")
}
}
51 changes: 51 additions & 0 deletions bytes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package gp

import (
"bytes"
"testing"
)

func TestBytesCreation(t *testing.T) {
// Test BytesFromStr
b1 := BytesFromStr("hello")
if string(b1.Bytes()) != "hello" {
t.Errorf("BytesFromStr: expected 'hello', got '%s'", string(b1.Bytes()))
}

// Test MakeBytes
data := []byte("world")
b2 := MakeBytes(data)
if !bytes.Equal(b2.Bytes(), data) {
t.Errorf("MakeBytes: expected '%v', got '%v'", data, b2.Bytes())
}
}

func TestBytesDecode(t *testing.T) {
// Test UTF-8 decode
b := BytesFromStr("你好")
if !bytes.Equal(b.Bytes(), []byte("你好")) {
t.Errorf("BytesFromStr: expected '你好', got '%s'", string(b.Bytes()))
}
s := b.Decode("utf-8")
if s.String() != "你好" {
t.Errorf("Decode: expected '你好', got '%s'", s.String())
}

// Test ASCII decode
b2 := BytesFromStr("hello")
s2 := b2.Decode("ascii")
if s2.String() != "hello" {
t.Errorf("Decode: expected 'hello', got '%s'", s2.String())
}
}

func TestBytesConversion(t *testing.T) {
original := []byte{0x48, 0x65, 0x6c, 0x6c, 0x6f} // "Hello" in hex
b := MakeBytes(original)

// Test conversion back to []byte
result := b.Bytes()
if !bytes.Equal(result, original) {
t.Errorf("Bytes conversion: expected %v, got %v", original, result)
}
}
88 changes: 88 additions & 0 deletions complex_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package gp

import (
"testing"
)

func TestComplex(t *testing.T) {
tests := []struct {
name string
input complex128
wantReal float64
wantImag float64
}{
{
name: "zero complex",
input: complex(0, 0),
wantReal: 0,
wantImag: 0,
},
{
name: "positive real and imaginary",
input: complex(3.14, 2.718),
wantReal: 3.14,
wantImag: 2.718,
},
{
name: "negative real and imaginary",
input: complex(-1.5, -2.5),
wantReal: -1.5,
wantImag: -2.5,
},
{
name: "mixed signs",
input: complex(-1.23, 4.56),
wantReal: -1.23,
wantImag: 4.56,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := MakeComplex(tt.input)

// Test Real() method
if got := c.Real(); got != tt.wantReal {
t.Errorf("Complex.Real() = %v, want %v", got, tt.wantReal)
}

// Test Imag() method
if got := c.Imag(); got != tt.wantImag {
t.Errorf("Complex.Imag() = %v, want %v", got, tt.wantImag)
}

// Test Complex128() method
if got := c.Complex128(); got != tt.input {
t.Errorf("Complex.Complex128() = %v, want %v", got, tt.input)
}
})
}
}

func TestComplexZeroValue(t *testing.T) {
// Create a proper zero complex number instead of using zero-value struct
c := MakeComplex(complex(0, 0))

// Test that zero complex behaves correctly
if got := c.Real(); got != 0 {
t.Errorf("Zero Complex.Real() = %v, want 0", got)
}
if got := c.Imag(); got != 0 {
t.Errorf("Zero Complex.Imag() = %v, want 0", got)
}
if got := c.Complex128(); got != 0 {
t.Errorf("Zero Complex.Complex128() = %v, want 0", got)
}
}

func TestComplexNilHandling(t *testing.T) {
var c Complex // zero-value struct with nil pointer
defer func() {
if r := recover(); r == nil {
t.Error("Expected panic for nil pointer access, but got none")
}
}()

// This should panic
_ = c.Real()
}
4 changes: 0 additions & 4 deletions dict.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ func newDict(obj *PyObject) Dict {
return Dict{newObject(obj)}
}

func NewDict(obj *PyObject) Dict {
return newDict(obj)
}

func DictFromPairs(pairs ...any) Dict {
if len(pairs)%2 != 0 {
panic("DictFromPairs requires an even number of arguments")
Expand Down
174 changes: 174 additions & 0 deletions dict_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package gp

import (
"testing"
)

func TestDictFromPairs(t *testing.T) {
// Add panic test case
t.Run("odd number of arguments", func(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("DictFromPairs() with odd number of arguments should panic")
} else if r != "DictFromPairs requires an even number of arguments" {
t.Errorf("Expected panic message 'DictFromPairs requires an even number of arguments', got '%v'", r)
}
}()

DictFromPairs("key1", "value1", "key2") // Should panic
})

tests := []struct {
name string
pairs []any
wantKeys []any
wantVals []any
}{
{
name: "string keys and values",
pairs: []any{"key1", "value1", "key2", "value2"},
wantKeys: []any{"key1", "key2"},
wantVals: []any{"value1", "value2"},
},
{
name: "mixed types",
pairs: []any{"key1", 42, "key2", 3.14},
wantKeys: []any{"key1", "key2"},
wantVals: []any{42, 3.14},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dict := DictFromPairs(tt.pairs...)

// Verify each key-value pair
for i := 0; i < len(tt.wantKeys); i++ {
key := From(tt.wantKeys[i])
val := dict.Get(key)
if !ObjectsAreEqual(val, From(tt.wantVals[i])) {
t.Errorf("DictFromPairs() got value %v for key %v, want %v",
val, tt.wantKeys[i], tt.wantVals[i])
}
}
})
}
}

func TestMakeDict(t *testing.T) {
tests := []struct {
name string
m map[any]any
}{
{
name: "string map",
m: map[any]any{
"key1": "value1",
"key2": "value2",
},
},
{
name: "mixed types map",
m: map[any]any{
"int": 42,
"float": 3.14,
"string": "hello",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dict := MakeDict(tt.m)

// Verify each key-value pair
for k, v := range tt.m {
key := From(k)
got := dict.Get(key)
if !ObjectsAreEqual(got, From(v)) {
t.Errorf("MakeDict() got value %v for key %v, want %v", got, k, v)
}
}
})
}
}

func TestDictSetGet(t *testing.T) {
dict := DictFromPairs()

// Test Set and Get
key := From("test_key")
value := From("test_value")
dict.Set(key, value)

got := dict.Get(key)
if !ObjectsAreEqual(got, value) {
t.Errorf("Dict.Get() got %v, want %v", got, value)
}
}

func TestDictSetGetString(t *testing.T) {
dict := DictFromPairs()

// Test SetString and GetString
value := From("test_value")
dict.SetString("test_key", value)

got := dict.GetString("test_key")
if !ObjectsAreEqual(got, value) {
t.Errorf("Dict.GetString() got %v, want %v", got, value)
}
}

func TestDictDel(t *testing.T) {
dict := DictFromPairs("test_key", "test_value")
key := From("test_key")

// Verify key exists
got := dict.Get(key)
if !ObjectsAreEqual(got, From("test_value")) {
t.Errorf("Before deletion, got %v, want %v", got, "test_value")
}

// Delete the key
dict.Del(key)

// After deletion, Get should return nil object
got = dict.Get(key)
if got.Obj() != nil {
t.Errorf("After deletion, got %v, want nil", got)
}
}

func TestDictForEach(t *testing.T) {
dict := DictFromPairs(
"key1", "value1",
"key2", "value2",
"key3", "value3",
)

count := 0
expectedPairs := map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}

dict.ForEach(func(key, value Object) {
count++
k := key.String()
v := value.String()
if expectedVal, ok := expectedPairs[k]; !ok || expectedVal != v {
t.Errorf("ForEach() unexpected pair: %v: %v", k, v)
}
})

if count != len(expectedPairs) {
t.Errorf("ForEach() visited %d pairs, want %d", count, len(expectedPairs))
}
}

// Helper function to compare Python objects
func ObjectsAreEqual(obj1, obj2 Object) bool {
return obj1.String() == obj2.String()
}
6 changes: 6 additions & 0 deletions float.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package gp
*/
import "C"

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

func (f Float) Float32() float32 {
return float32(C.PyFloat_AsDouble(f.obj))
}

func (f Float) IsInteger() Bool {
fn := Cast[Func](f.Attr("is_integer"))
return Cast[Bool](fn.callNoArgs())
Expand Down
Loading

0 comments on commit 581c896

Please sign in to comment.