From 9f8face671530d662168a5482c5946397e5e7986 Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Fri, 7 Aug 2015 14:31:35 -0700 Subject: [PATCH 01/11] Custom Go bindings for Class. Add hand-coded binding for FetchClass. Override GetMethods to return `[]Method` rather than `[]interface{}`. --- runtime/go/build.go | 4 ++++ runtime/go/clownfish/clownfish.go | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/runtime/go/build.go b/runtime/go/build.go index d7bb7a04..e509dbaa 100644 --- a/runtime/go/build.go +++ b/runtime/go/build.go @@ -144,6 +144,10 @@ func specMethods(parcel *cfc.Parcel) { errBinding.SpecMethod("", "Error() string") errBinding.Register() + classBinding := cfc.NewGoClass(parcel, "Clownfish::Class") + classBinding.SpecMethod("Get_Methods", "GetMethods() []Method") + classBinding.Register() + stringBinding := cfc.NewGoClass(parcel, "Clownfish::String") stringBinding.SpecMethod("Code_Point_At", "CodePointAt(uintptr) rune") stringBinding.SpecMethod("Code_Point_From", "CodePointFrom(uintptr) rune") diff --git a/runtime/go/clownfish/clownfish.go b/runtime/go/clownfish/clownfish.go index 34b6f5f4..f6dfb270 100644 --- a/runtime/go/clownfish/clownfish.go +++ b/runtime/go/clownfish/clownfish.go @@ -123,6 +123,25 @@ type ObjIMP struct { ref uintptr } +func FetchClass(className string) Class { + nameCF := (*C.cfish_String)(GoToString(className)) + defer C.cfish_decref(unsafe.Pointer(nameCF)) + class := C.cfish_Class_fetch_class(nameCF) + return WRAPClass(unsafe.Pointer(class)) +} + +func (c *ClassIMP) GetMethods() []Method { + self := (*C.cfish_Class)(unsafe.Pointer(c.TOPTR())) + methsVec := C.CFISH_Class_Get_Methods(self) + size := C.CFISH_Vec_Get_Size(methsVec) + meths := make([]Method, 0, int(size)) + for i := C.size_t(0); i < size; i++ { + meths = append(meths, WRAPMethod(unsafe.Pointer(C.CFISH_Vec_Fetch(methsVec, i)))) + } + C.cfish_decref(unsafe.Pointer(methsVec)) + return meths +} + func NewString(goString string) String { str := C.CString(goString) len := C.size_t(len(goString)) From 172822e62b8ce190dd58f5889bdce2185e037df2 Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Fri, 7 Aug 2015 17:52:43 -0700 Subject: [PATCH 02/11] Tests for Class Go bindings. --- runtime/go/clownfish/class_test.go | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 runtime/go/clownfish/class_test.go diff --git a/runtime/go/clownfish/class_test.go b/runtime/go/clownfish/class_test.go new file mode 100644 index 00000000..81f3e2ea --- /dev/null +++ b/runtime/go/clownfish/class_test.go @@ -0,0 +1,43 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package clownfish + +import "testing" + +func TestClassGetName(t *testing.T) { + className := "Clownfish::Hash" + class := FetchClass(className) + if got := class.GetName(); got != className { + t.Errorf("Expected %s, got %s", className, got) + } +} + +func TestClassGetParent(t *testing.T) { + hashClass := FetchClass("Clownfish::Hash") + parent := hashClass.GetParent(); + if parentName := parent.GetName(); parentName != "Clownfish::Obj" { + t.Errorf("Expected Clownfish::Obj, got %s", parentName) + } +} + +func TestClassGetObjAllocSize(t *testing.T) { + intClass := FetchClass("Clownfish::Integer") + classClass := FetchClass("Clownfish::Class") + if intClass.GetObjAllocSize() >= classClass.GetObjAllocSize() { + t.Error("Unexpected result for GetObjAllocSize") + } +} From e68fe4bda0d30a7659f744e9dabab297e1fb180d Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Fri, 7 Aug 2015 17:53:14 -0700 Subject: [PATCH 03/11] Implement Meth_Host_Name for Go. Takes Upper_Snake_Case and removes the underscores. --- runtime/go/ext/clownfish.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/runtime/go/ext/clownfish.c b/runtime/go/ext/clownfish.c index 75453881..27cd4a0e 100644 --- a/runtime/go/ext/clownfish.c +++ b/runtime/go/ext/clownfish.c @@ -29,6 +29,7 @@ #include "Clownfish/Blob.h" #include "Clownfish/Boolean.h" #include "Clownfish/ByteBuf.h" +#include "Clownfish/CharBuf.h" #include "Clownfish/Class.h" #include "Clownfish/Err.h" #include "Clownfish/Hash.h" @@ -186,7 +187,18 @@ Class_To_Host_IMP(Class *self) { String* Method_Host_Name_IMP(Method *self) { - return (String*)INCREF(self->name); + StringIterator *iter = StrIter_new(self->name, 0); + CharBuf *charbuf = CB_new(Str_Get_Size(self->name)); + int32_t code_point; + while (STRITER_DONE != (code_point = StrIter_Next(iter))) { + if (code_point != '_') { + CB_Cat_Char(charbuf, code_point); + } + } + String *host_name = CB_Yield_String(charbuf); + DECREF(charbuf); + DECREF(iter); + return host_name; } /******************************** Err **************************************/ From f8c60c4fbb203a7b14548ed3d33bc39b812310f8 Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Fri, 7 Aug 2015 18:02:31 -0700 Subject: [PATCH 04/11] Mark subroutines as unimplemented for Go. * `Obj_To_Host` * `Class_Foster_Obj` * `Class_find_parent_class --- runtime/go/ext/clownfish.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/runtime/go/ext/clownfish.c b/runtime/go/ext/clownfish.c index 27cd4a0e..56682d45 100644 --- a/runtime/go/ext/clownfish.c +++ b/runtime/go/ext/clownfish.c @@ -126,7 +126,7 @@ cfish_dec_refcount(void *vself) { void* Obj_To_Host_IMP(Obj *self) { UNUSED_VAR(self); - THROW(ERR, "TODO"); + THROW(ERR, "Unimplemented for Go"); UNREACHABLE_RETURN(void*); } @@ -153,7 +153,7 @@ Obj* Class_Foster_Obj_IMP(Class *self, void *host_obj) { UNUSED_VAR(self); UNUSED_VAR(host_obj); - THROW(ERR, "TODO"); + THROW(ERR, "Unimplemented for Go"); UNREACHABLE_RETURN(Obj*); } @@ -172,14 +172,14 @@ Class_fresh_host_methods(String *class_name) { String* Class_find_parent_class(String *class_name) { UNUSED_VAR(class_name); - THROW(ERR, "TODO"); + THROW(ERR, "Unimplemented for Go"); UNREACHABLE_RETURN(String*); } void* Class_To_Host_IMP(Class *self) { UNUSED_VAR(self); - THROW(ERR, "TODO"); + THROW(ERR, "Unimplemented for Go"); UNREACHABLE_RETURN(void*); } From a3ce8dd881b57cb9a9d4b63bc03c6da0f725076a Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Fri, 7 Aug 2015 18:22:55 -0700 Subject: [PATCH 05/11] Method ctor Go binding. Accepts an `unsafe.Pointer` for the `cfish_method_t` implementing function. --- runtime/go/clownfish/clownfish.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/runtime/go/clownfish/clownfish.go b/runtime/go/clownfish/clownfish.go index f6dfb270..be966554 100644 --- a/runtime/go/clownfish/clownfish.go +++ b/runtime/go/clownfish/clownfish.go @@ -142,6 +142,14 @@ func (c *ClassIMP) GetMethods() []Method { return meths } +func NewMethod(name string, callbackFunc unsafe.Pointer, offset uint32) Method { + nameCF := (*C.cfish_String)(GoToString(name)) + defer C.cfish_decref(unsafe.Pointer(nameCF)) + methCF := C.cfish_Method_new(nameCF, C.cfish_method_t(callbackFunc), + C.uint32_t(offset)); + return WRAPMethod(unsafe.Pointer(methCF)) +} + func NewString(goString string) String { str := C.CString(goString) len := C.size_t(len(goString)) From 7073bd06c9ce58f83a910d78d9f665e268902069 Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Fri, 7 Aug 2015 17:54:26 -0700 Subject: [PATCH 06/11] Tests for Method Go bindings. --- runtime/go/clownfish/method_test.go | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 runtime/go/clownfish/method_test.go diff --git a/runtime/go/clownfish/method_test.go b/runtime/go/clownfish/method_test.go new file mode 100644 index 00000000..3e3d1f63 --- /dev/null +++ b/runtime/go/clownfish/method_test.go @@ -0,0 +1,51 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package clownfish + +import "testing" +import "unsafe" + +func TestMethodGetName(t *testing.T) { + meth := NewMethod("Do_Stuff", unsafe.Pointer(nil), 32) + if name := meth.GetName(); name != "Do_Stuff" { + t.Errorf("Expected \"Do_Stuff\", got %s", name) + } +} + +func TestMethodGetHostAlias(t *testing.T) { + meth := NewMethod("Do_Stuff", unsafe.Pointer(nil), 32) + alias := "GetStuffDone" + meth.SetHostAlias(alias) + if got := meth.GetHostAlias(); got != alias { + t.Errorf("Expected %v, got %v", alias, got) + } +} + +func TestMethodHostName(t *testing.T) { + meth := NewMethod("Do_Stuff", unsafe.Pointer(nil), 32) + expected := "DoStuff" + if hostName := meth.HostName(); hostName != expected { + t.Errorf("Expected %v, got %v", expected, hostName) + } +} + +func TestMethodIsExcludedFromHost(t *testing.T) { + meth := NewMethod("Do_Stuff", unsafe.Pointer(nil), 32) + if meth.IsExcludedFromHost() { + t.Errorf("Meth should not be excluded") + } +} From 647ef88ba585aa0b3802b4bf6952e26fa7008e68 Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Sat, 8 Aug 2015 17:31:44 -0700 Subject: [PATCH 07/11] Custom Go binding for StrIter_new. --- runtime/go/build.go | 4 ++++ runtime/go/clownfish/clownfish.go | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/runtime/go/build.go b/runtime/go/build.go index e509dbaa..3807d875 100644 --- a/runtime/go/build.go +++ b/runtime/go/build.go @@ -154,6 +154,10 @@ func specMethods(parcel *cfc.Parcel) { stringBinding.SpecMethod("Swap_Chars", "SwapChars(rune, rune) string") stringBinding.Register() + stringIterBinding := cfc.NewGoClass(parcel, "Clownfish::StringIterator") + stringIterBinding.SetSuppressCtor(true) + stringIterBinding.Register() + blobBinding := cfc.NewGoClass(parcel, "Clownfish::Blob") blobBinding.SpecMethod("", "GetBuf() uintptr") blobBinding.Register() diff --git a/runtime/go/clownfish/clownfish.go b/runtime/go/clownfish/clownfish.go index be966554..065c9d0f 100644 --- a/runtime/go/clownfish/clownfish.go +++ b/runtime/go/clownfish/clownfish.go @@ -157,6 +157,12 @@ func NewString(goString string) String { return WRAPString(unsafe.Pointer(cfObj)) } +func NewStringIterator(str String, offset uintptr) StringIterator { + strCF := (*C.cfish_String)(unsafe.Pointer(str.TOPTR())) + iter := C.cfish_StrIter_new(strCF, C.size_t(offset)) + return WRAPStringIterator(unsafe.Pointer(iter)) +} + func NewVector(size int) Vector { if (size < 0 || uint64(size) > ^uint64(0)) { panic(NewErr(fmt.Sprintf("Param 'size' out of range: %d", size))) From cd8ca2cfeabcfa7cce242f7be07250a6d1e90c14 Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Sat, 8 Aug 2015 17:33:15 -0700 Subject: [PATCH 08/11] Tests for StringIterator Go bindings. --- runtime/go/clownfish/string_test.go | 114 ++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/runtime/go/clownfish/string_test.go b/runtime/go/clownfish/string_test.go index 7cb7fadf..1347b197 100644 --- a/runtime/go/clownfish/string_test.go +++ b/runtime/go/clownfish/string_test.go @@ -201,3 +201,117 @@ func TestStringTopTail(t *testing.T) { t.Error("Tail iter returned", got) } } + +func TestStrIterNextPrev(t *testing.T) { + iter := NewStringIterator(NewString("abc"), 1) + if got := iter.Next(); got != 'b' { + t.Errorf("Expected 'b', got %d", got) + } + if got := iter.Prev(); got != 'b' { + t.Errorf("Expected 'b', got %d", got) + } +} + +func TestStrIterHasNextHasPrev(t *testing.T) { + iter := NewStringIterator(NewString("a"), 0) + if iter.HasPrev() { + t.Error("HasPrev at top") + } + if !iter.HasNext() { + t.Error("HasNext at top") + } + iter.Next() + if !iter.HasPrev() { + t.Error("HasPrev at end") + } + if iter.HasNext() { + t.Error("HasNext at end") + } +} + +func TestStrIterClone(t *testing.T) { + iter := NewStringIterator(NewString("abc"), 0) + iter.Next() + clone := iter.Clone().(StringIterator) + if got := clone.Next(); got != 'b' { + t.Errorf("Expected 'b', got %d", got) + } +} + +func TestStrIterAssign(t *testing.T) { + abc := NewString("abc") + xyz := NewString("xyz") + iter := NewStringIterator(abc, 1) + iter.Assign(NewStringIterator(xyz, 1)) + if got := iter.Next(); got != 'y' { + t.Errorf("Expected 'y', got %d", got) + } +} + +func TestStrIterEquals(t *testing.T) { + iter := NewStringIterator(NewString("abc"), 0) + iter.Next() + clone := iter.Clone().(StringIterator) + if !iter.Equals(clone) { + t.Error("Equals should succeed") + } + clone.Next() + if iter.Equals(clone) { + t.Error("Equals should fail") + } +} + +func TestStrIterCompareTo(t *testing.T) { + iter := NewStringIterator(NewString("abc"), 0) + other := iter.Clone().(StringIterator) + if got := iter.CompareTo(other); got != 0 { + t.Errorf("Expected 0, got %d", got) + } + iter.Next() + if got := iter.CompareTo(other); got <= 0 { + t.Errorf("More advanced iterator should be greater than: %d", got) + } + if got := other.CompareTo(iter); got >= 0 { + t.Errorf("Less advanced iterator should be less than: %d", got) + } +} + +func TestStrIterAdvanceRecede(t *testing.T) { + iter := NewStringIterator(NewString("abcde"), 0) + if got := iter.Advance(3); got != 3 { + t.Errorf("Expected Advance to return 3, got %d", got) + } + if got := iter.Recede(2); got != 2 { + t.Errorf("Expected Recede to return 2, got %d", got) + } +} + +func TestStrIterStartsWithEndsWith(t *testing.T) { + iter := NewStringIterator(NewString("abcd"), 2) + if !iter.StartsWith("cd") { + t.Error("StartsWith should succeed") + } + if iter.StartsWith("cde") { + t.Error("StartsWith should fail") + } + if !iter.EndsWith("ab") { + t.Error("EndsWith should succeed") + } + if iter.EndsWith("abc") { + t.Error("EndsWith should fail") + } +} + +func TestStrIterSkipWhite(t *testing.T) { + iter := NewStringIterator(NewString("foo bar"), 0) + if got := iter.SkipNextWhitespace(); got != 0 { + t.Error("No whitespace to skip") + } + iter.Advance(3) + if got := iter.SkipNextWhitespace(); got != 2 || !iter.StartsWith("bar") { + t.Error("Skip forward 2 spaces") + } + if got := iter.SkipPrevWhitespace(); got != 2 || !iter.EndsWith("foo") { + t.Error("Skip backwards 2 spaces") + } +} From 7ef5eaf34d1caa8a3c6569599425da67ca5e26f0 Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Sat, 8 Aug 2015 18:08:38 -0700 Subject: [PATCH 09/11] Tests for CharBuf Go bindings. --- runtime/go/clownfish/charbuf_test.go | 77 ++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 runtime/go/clownfish/charbuf_test.go diff --git a/runtime/go/clownfish/charbuf_test.go b/runtime/go/clownfish/charbuf_test.go new file mode 100644 index 00000000..1ade2f22 --- /dev/null +++ b/runtime/go/clownfish/charbuf_test.go @@ -0,0 +1,77 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package clownfish + +import "testing" + +func TestCharBufCat(t *testing.T) { + cb := NewCharBuf(0) + cb.Cat("foo") + if got := cb.ToString(); got != "foo" { + t.Errorf("Expected foo, got %v", got) + } +} + +func TestCharBufMimic(t *testing.T) { + cb := NewCharBuf(0) + other := NewCharBuf(0) + other.Cat("foo") + cb.Mimic(other) + if got := cb.ToString(); got != "foo" { + t.Errorf("Expected foo, got %v", got) + } +} + +func TestCharBufCatChar(t *testing.T) { + cb := NewCharBuf(0) + cb.CatChar('x') + if got := cb.ToString(); got != "x" { + t.Errorf("Expected x, got %v", got) + } +} + +func TestCharBufSetSizeGetSize(t *testing.T) { + cb := NewCharBuf(0) + cb.Cat("abc") + cb.SetSize(2) + if got := cb.GetSize(); got != 2 { + t.Errorf("Size should be 2 but got %d", got) + } + if got := cb.ToString(); got != "ab" { + t.Errorf("Expected ab, got %v", got) + } +} + +func TestCharBufClone(t *testing.T) { + cb := NewCharBuf(0) + cb.Cat("foo") + clone := cb.Clone() + if got := clone.ToString(); got != "foo" { + t.Errorf("Expected foo, got %v", got) + } +} + +func TestCharBufYieldString(t *testing.T) { + cb := NewCharBuf(0) + cb.Cat("foo") + if got := cb.YieldString(); got != "foo" { + t.Errorf("Should yield foo, got %v", got) + } + if got := cb.YieldString(); got != "" { + t.Errorf("Should yield empty string, got %v", got) + } +} From 26bb983745f01bc58e54e4717c3c31cfcb09c98d Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Sat, 8 Aug 2015 19:18:38 -0700 Subject: [PATCH 10/11] Change BB_Cat to take Blob arg. This is analogous to having CharBuf's Cat take a String. --- runtime/core/Clownfish/ByteBuf.c | 4 ++-- runtime/core/Clownfish/ByteBuf.cfh | 2 +- runtime/core/Clownfish/Test/TestByteBuf.c | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/runtime/core/Clownfish/ByteBuf.c b/runtime/core/Clownfish/ByteBuf.c index f32fa2c4..210ed180 100644 --- a/runtime/core/Clownfish/ByteBuf.c +++ b/runtime/core/Clownfish/ByteBuf.c @@ -159,8 +159,8 @@ BB_Cat_Bytes_IMP(ByteBuf *self, const void *bytes, size_t size) { } void -BB_Cat_IMP(ByteBuf *self, ByteBuf *other) { - SI_cat_bytes(self, other->buf, other->size); +BB_Cat_IMP(ByteBuf *self, Blob *blob) { + SI_cat_bytes(self, Blob_Get_Buf(blob), Blob_Get_Size(blob)); } static void diff --git a/runtime/core/Clownfish/ByteBuf.cfh b/runtime/core/Clownfish/ByteBuf.cfh index 43d67102..02357410 100644 --- a/runtime/core/Clownfish/ByteBuf.cfh +++ b/runtime/core/Clownfish/ByteBuf.cfh @@ -99,7 +99,7 @@ final class Clownfish::ByteBuf nickname BB inherits Clownfish::Obj { * original ByteBuf. Allocate more memory as needed. */ void - Cat(ByteBuf *self, ByteBuf *other); + Cat(ByteBuf *self, Blob *blob); /** Assign more memory to the ByteBuf, if it doesn't already have enough * room to hold `size` bytes. Cannot shrink the allocation. diff --git a/runtime/core/Clownfish/Test/TestByteBuf.c b/runtime/core/Clownfish/Test/TestByteBuf.c index c393450b..ddaabd73 100644 --- a/runtime/core/Clownfish/Test/TestByteBuf.c +++ b/runtime/core/Clownfish/Test/TestByteBuf.c @@ -25,6 +25,7 @@ #include "Clownfish/Test.h" #include "Clownfish/TestHarness/TestBatchRunner.h" #include "Clownfish/TestHarness/TestUtils.h" +#include "Clownfish/Blob.h" #include "Clownfish/Class.h" TestByteBuf* @@ -125,16 +126,16 @@ static void test_Cat(TestBatchRunner *runner) { ByteBuf *wanted = BB_new_bytes("foobar", 6); ByteBuf *got = BB_new_bytes("foo", 3); - ByteBuf *scratch = BB_new_bytes("bar", 3); + Blob *blob = BB_new_bytes("bar", 3); - BB_Cat(got, scratch); + BB_Cat(got, blob); TEST_TRUE(runner, BB_Equals(wanted, (Obj*)got), "Cat"); BB_Mimic_Bytes(wanted, "foobarbaz", 9); BB_Cat_Bytes(got, "baz", 3); TEST_TRUE(runner, BB_Equals(wanted, (Obj*)got), "Cat_Bytes"); - DECREF(scratch); + DECREF(blob); DECREF(got); DECREF(wanted); } From e1ae4b1309fccf6332fc82bb5f03615d3d34db5e Mon Sep 17 00:00:00 2001 From: Marvin Humphrey Date: Sat, 8 Aug 2015 19:19:41 -0700 Subject: [PATCH 11/11] Tests for ByteBuf Go bindings. --- runtime/go/clownfish/bytebuf_test.go | 107 +++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 runtime/go/clownfish/bytebuf_test.go diff --git a/runtime/go/clownfish/bytebuf_test.go b/runtime/go/clownfish/bytebuf_test.go new file mode 100644 index 00000000..0854f8dc --- /dev/null +++ b/runtime/go/clownfish/bytebuf_test.go @@ -0,0 +1,107 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package clownfish + +import "testing" +import "reflect" + +func TestByteBufCat(t *testing.T) { + bb := NewByteBuf(0) + content := []byte("foo") + bb.Cat(content) + if got := bb.YieldBlob(); !reflect.DeepEqual(got, content) { + t.Errorf("Expected %v, got %v", content, got) + } +} + +func TestByteBufSetSizeGetSize(t *testing.T) { + bb := NewByteBuf(0) + content := []byte("abc") + bb.Cat(content) + bb.SetSize(2) + if got := bb.GetSize(); got != 2 { + t.Errorf("Expected size 2, got %d", got) + } + expected := []byte("ab") + if got := bb.YieldBlob(); !reflect.DeepEqual(got, expected) { + t.Errorf("Expected %v, got %v", expected, got) + } +} + +func TestByteBufGetCapacity(t *testing.T) { + bb := NewByteBuf(5) + if cap := bb.GetCapacity(); cap < 5 { + t.Errorf("Expected at least 5, got %d", cap) + } +} + +func TestByteBufMimic(t *testing.T) { + bb := NewByteBuf(0) + content := []byte("foo") + bb.Cat(content) + other := NewByteBuf(0) + other.Mimic(bb) + if got := other.YieldBlob(); !reflect.DeepEqual(got, content) { + t.Errorf("Expected %v, got %v", content, got) + } +} + +func TestByteBufEquals(t *testing.T) { + bb := NewByteBuf(0) + other := NewByteBuf(0) + content := []byte("foo") + bb.Cat(content) + other.Cat(content) + if !bb.Equals(other) { + t.Errorf("Equals against equal ByteBuf") + } + other.SetSize(2) + if bb.Equals(other) { + t.Errorf("Equals against non-equal ByteBuf") + } + if bb.Equals(42) { + t.Errorf("Equals against arbitrary Go type") + } +} + +func TestByteBufClone(t *testing.T) { + content := []byte("foo") + bb := NewByteBuf(0) + bb.Cat(content) + clone := bb.Clone().(ByteBuf) + if got := clone.YieldBlob(); !reflect.DeepEqual(got, content) { + t.Errorf("Expected %v, got %v", content, got) + } +} + +func TestByteBufCompareTo(t *testing.T) { + bb := NewByteBuf(0) + other := NewByteBuf(0) + content := []byte("foo") + bb.Cat(content) + other.Cat(content) + if got := bb.CompareTo(other); got != 0 { + t.Errorf("CompareTo equal, got %d", got) + } + other.SetSize(2) + if got := bb.CompareTo(other); got <= 0 { + t.Errorf("CompareTo lesser, got %d", got) + } + if got := other.CompareTo(bb); got >= 0 { + t.Errorf("CompareTo greater, got %d", got) + } +}