From f1b771187049bb5f7dbc5aad9b3f7697ff1ce142 Mon Sep 17 00:00:00 2001 From: Martin Kealey Date: Tue, 2 Mar 2010 18:45:59 +1300 Subject: [PATCH] Bugfix - FPQ_ITEMS() raised divide-by-zero before size was set (get rid of modulus operations) Changed Integer coercion to return .elements() Added .capacity() to return (apparent) allocated size More tests, with better descriptions More unification of the 3 different source files --- src/pmc/fixedpmcqueue.pmc | 71 +++++++++++++++++++++++---------- src/pmc/fixedpmcqueue2.pmc | 75 ++++++++++++++++++++++++----------- src/pmc/fixedpmcqueue3.pmc | 81 ++++++++++++++++++++++++++------------ t/pmc/fixedpmcqueue.t | 36 ++++++++++++----- t/pmc/fixedpmcqueue2.t | 38 +++++++++++++----- t/pmc/fixedpmcqueue3.t | 36 ++++++++++++----- 6 files changed, 239 insertions(+), 98 deletions(-) diff --git a/src/pmc/fixedpmcqueue.pmc b/src/pmc/fixedpmcqueue.pmc index 22a8885..3448216 100644 --- a/src/pmc/fixedpmcqueue.pmc +++ b/src/pmc/fixedpmcqueue.pmc @@ -75,7 +75,8 @@ pmclass FixedPMCQueue dynpmc auto_attrs provides queue { VTABLE void visit(PMC *info) { FPQ_DECL_ATTRS(SELF); PMC ** const storage = self.storage; - FPQ_ITERATE(i, VISIT_PMC(INTERP, info, storage[i])); + if (storage) + FPQ_ITERATE(i, VISIT_PMC(INTERP, info, storage[i])); } /* Size the queue. Cannot shrink the queue smaller than the number of items @@ -85,53 +86,56 @@ pmclass FixedPMCQueue dynpmc auto_attrs provides queue { const INTVAL start = self.queue_start; const INTVAL end = self.queue_end; const INTVAL size = self.size; - if (newsize < FPQ_ITEMS()) + const INTVAL items = FPQ_ITEMS(); + + if (newsize < items) Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, "FixedPMCQueue: Cannot shrink size with items in queue"); - if (newsize != size) + if (newsize != size) { if (start == 0) { FPQ_REALLOCATE(self.storage, newsize); self.size = newsize; } else { - INTVAL ptr = start; PMC ** const oldstorage = self.storage; PMC ** newstorage = FPQ_ALLOCATE(newsize); - INTVAL i = 0; - while (ptr != end) { - newstorage[i] = oldstorage[ptr]; - FPQ_IDX_INCR(ptr); - i++; + if ( start > end ) { + mem_sys_memmove( &newstorage[0], &oldstorage[start], (size - start) * sizeof(PMC*)); + mem_sys_memmove( &newstorage[size - start], &oldstorage[0], end * sizeof(PMC*)); + } else { + mem_sys_memmove( &newstorage[0], &oldstorage[start], (end - start) * sizeof(PMC*)); } if (oldstorage) mem_sys_free(oldstorage); self.storage = newstorage; self.size = newsize; self.queue_start = 0; - self.queue_end = i; + self.queue_end = items; } + } } /* Push an item onto the queue */ VTABLE void push_pmc(PMC *item) { FPQ_DECL_ATTRS(SELF); - if (self.size == self.items) + + if (FPQ_FULL()) Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, "FixedPMCQueue: Pushed too many items"); self.storage[self.queue_end] = item; - FPQ_IDX_INCR(self.queue_end); - self.items++; + FPQ_IDXF_INCR(queue_end); + FPQ_ITEMS()++; } /* Pull an item off the queue */ VTABLE PMC* shift_pmc() { FPQ_DECL_ATTRS(SELF); PMC * first_item; - if(!self.items) - Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, - "FixedPMCQueue: No items to shift"); + + if (FPQ_EMPTY()) + return PMCNULL; first_item = self.storage[self.queue_start]; - FPQ_IDX_INCR(self.queue_start); - self.items--; + FPQ_ITEMS()--; + FPQ_IDXF_INCR(queue_start); return first_item; } @@ -146,18 +150,36 @@ pmclass FixedPMCQueue dynpmc auto_attrs provides queue { FPQ_DECL_ATTRS(SELF); return FPQ_ITEMS(); } + VTABLE INTVAL get_integer() { + FPQ_DECL_ATTRS(SELF); + return FPQ_ITEMS(); + } + + VTABLE INTVAL isnull() { + FPQ_DECL_ATTRS(SELF); + return self.size <= 0; + } /* Total amount of allocated storage slots in the queue */ - VTABLE INTVAL get_integer() { + METHOD capacity() { FPQ_DECL_ATTRS(SELF); - return(self.size); + PMC * result; + if (self.size <= 0) + result = PMCNULL; + else { + result = Parrot_pmc_new(INTERP, + Parrot_get_ctx_HLL_type(INTERP, + enum_class_Integer)); + VTABLE_set_integer_native(INTERP, result, self.size); + } + RETURN(PMC* result); } /* Convert the queue to a FixedPMCArray. The array will have the same length as the queue, all additional spaces will contain PMCNULL */ METHOD to_array() { - PMC * newarray = Parrot_pmc_new(INTERP, enum_class_FixedPMCArray); FPQ_DECL_ATTRS(SELF); + PMC * newarray = Parrot_pmc_new(INTERP, enum_class_FixedPMCArray); const INTVAL size = self.size; PMC ** const s = self.storage; INTVAL i = 0; @@ -196,3 +218,10 @@ pmclass FixedPMCQueue dynpmc auto_attrs provides queue { FPQ_ITEMS() = 0; } } + +/* + * Local variables: + * c-file-style: "parrot" + * End: + * vim: expandtab shiftwidth=4: + */ diff --git a/src/pmc/fixedpmcqueue2.pmc b/src/pmc/fixedpmcqueue2.pmc index a079629..2c9035e 100644 --- a/src/pmc/fixedpmcqueue2.pmc +++ b/src/pmc/fixedpmcqueue2.pmc @@ -5,10 +5,11 @@ #define FPQ_IDX_DIFF(x, y) (((x) + self.size - (y)) % self.size) #define FPQ_IDX_INCR(x) (x) = FPQ_IDX_ADD((x), 1) #define FPQ_IDXF_INCR(f) FPQ_IDX_INCR(self.f) -#define FPQ_ITEMS() FPQ_IDX_DIFF(self.queue_end, self.queue_start) +#define FPQ_ITEMS() (self.size > 0 ? FPQ_IDX_DIFF(self.queue_end, self.queue_start) : 0) #define FPQ_EMPTY() (self.queue_start == self.queue_end) -#define FPQ_FULL() ((self.queue_end + 1) % self.size == self.queue_start) +#define FPQ_FULL() (self.queue_end + 1 - self.queue_start == 0 || self.queue_end + 1 - self.queue_start == self.size) // (self.queue_start == self.queue_end+1 || self.queue_start == 0 && self.queue_end == self.size-1) + // ((self.queue_end + 1) % self.size == self.queue_start) #define FPQ_ALLOCATE(len) mem_allocate_n_typed(len, PMC *) #define FPQ_REALLOCATE(p, len) mem_realloc_n_typed(p, len, PMC *) #define FPQ_ITERATE(index,func) { \ @@ -83,33 +84,40 @@ pmclass FixedPMCQueue2 dynpmc auto_attrs provides queue { const INTVAL start = self.queue_start; const INTVAL end = self.queue_end; const INTVAL size = self.size; - INTVAL items = FPQ_ITEMS(); + const INTVAL items = FPQ_ITEMS(); + if (newsize < items) Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, "FixedPMCQueue2: Cannot shrink size with items in queue"); ++newsize; /* reserve one more slot than actually used, so that 0 <= items < size */ if (newsize != size) { - PMC ** const oldstorage = self.storage; - PMC ** newstorage = FPQ_ALLOCATE(newsize); - if ( start > end ) { - mem_sys_memmove( &newstorage[0], &oldstorage[start], (size - start) * sizeof(PMC*)); - mem_sys_memmove( &newstorage[size - start], &oldstorage[0], end * sizeof(PMC*)); - } else if ( start < end ) { - mem_sys_memmove( &newstorage[0], &oldstorage[start], (end - start) * sizeof(PMC*)); + if (start == 0) { + FPQ_REALLOCATE(self.storage, newsize); + self.size = newsize; + } else { + PMC ** const oldstorage = self.storage; + PMC ** newstorage = FPQ_ALLOCATE(newsize); + if ( start > end ) { + mem_sys_memmove( &newstorage[0], &oldstorage[start], (size - start) * sizeof(PMC*)); + mem_sys_memmove( &newstorage[size - start], &oldstorage[0], end * sizeof(PMC*)); + } else { + mem_sys_memmove( &newstorage[0], &oldstorage[start], (end - start) * sizeof(PMC*)); + } + if (oldstorage) + mem_sys_free(oldstorage); + self.storage = newstorage; + self.size = newsize; + self.queue_start = 0; + self.queue_end = items; } - if (oldstorage) - mem_sys_free(oldstorage); - self.storage = newstorage; - self.size = newsize; - self.queue_start = 0; - self.queue_end = items; } } /* Push an item onto the queue */ VTABLE void push_pmc(PMC *item) { FPQ_DECL_ATTRS(SELF); + if (FPQ_FULL()) Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, "FixedPMCQueue2: Pushed too many items"); @@ -121,9 +129,9 @@ pmclass FixedPMCQueue2 dynpmc auto_attrs provides queue { VTABLE PMC* shift_pmc() { FPQ_DECL_ATTRS(SELF); PMC * first_item; - if(FPQ_EMPTY()) - Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, - "FixedPMCQueue2: No items to shift"); + + if (FPQ_EMPTY()) + return PMCNULL; first_item = self.storage[self.queue_start]; FPQ_IDXF_INCR(queue_start); return first_item; @@ -140,11 +148,24 @@ pmclass FixedPMCQueue2 dynpmc auto_attrs provides queue { FPQ_DECL_ATTRS(SELF); return FPQ_ITEMS(); } + VTABLE INTVAL get_integer() { + FPQ_DECL_ATTRS(SELF); + return FPQ_ITEMS(); + } /* Total amount of allocated storage slots in the queue */ - VTABLE INTVAL get_integer() { + METHOD capacity() { FPQ_DECL_ATTRS(SELF); - return(self.size); + PMC * result; + if (self.size <= 0) + result = PMCNULL; + else { + result = Parrot_pmc_new(INTERP, + Parrot_get_ctx_HLL_type(INTERP, + enum_class_Integer)); + VTABLE_set_integer_native(INTERP, result, self.size-1); // available size is one less than allocate space + } + RETURN(PMC* result); } /* Convert the queue to a FixedPMCArray. The array will have the same @@ -152,12 +173,13 @@ pmclass FixedPMCQueue2 dynpmc auto_attrs provides queue { METHOD to_array() { FPQ_DECL_ATTRS(SELF); PMC * newarray = Parrot_pmc_new(INTERP, enum_class_FixedPMCArray); + const INTVAL size = self.size; PMC ** const s = self.storage; INTVAL i = 0; - VTABLE_set_integer_native(INTERP, newarray, self.size); + VTABLE_set_integer_native(INTERP, newarray, size); FPQ_ITERATE(ptr, VTABLE_set_pmc_keyed_int(INTERP, newarray, i++, s[ptr])); - while (i < self.size) VTABLE_set_pmc_keyed_int(INTERP, newarray, i++, PMCNULL); + while (i < size) VTABLE_set_pmc_keyed_int(INTERP, newarray, i++, PMCNULL); RETURN(PMC* newarray); } @@ -188,3 +210,10 @@ pmclass FixedPMCQueue2 dynpmc auto_attrs provides queue { self.queue_end = 0; } } + +/* + * Local variables: + * c-file-style: "parrot" + * End: + * vim: expandtab shiftwidth=4: + */ diff --git a/src/pmc/fixedpmcqueue3.pmc b/src/pmc/fixedpmcqueue3.pmc index 2c8d417..d16ad76 100644 --- a/src/pmc/fixedpmcqueue3.pmc +++ b/src/pmc/fixedpmcqueue3.pmc @@ -5,10 +5,11 @@ #define FPQ_IDX_DIFF(x, y) (((x) + self.size - (y)) % self.size) #define FPQ_IDX_INCR(x) (x) = FPQ_IDX_ADD((x), 1) #define FPQ_IDXF_INCR(f) FPQ_IDX_INCR(self.f) -#define FPQ_ITEMS() FPQ_IDX_DIFF(self.queue_end, self.queue_start) +#define FPQ_ITEMS() (self.size > 0 ? FPQ_IDX_DIFF(self.queue_end, self.queue_start) : 0) #define FPQ_EMPTY() (self.queue_start == self.queue_end) -#define FPQ_FULL() ((self.queue_end + 1) % self.size == self.queue_start) +#define FPQ_FULL() (self.queue_end + 1 - self.queue_start == 0 || self.queue_end + 1 - self.queue_start == self.size) // (self.queue_start == self.queue_end+1 || self.queue_start == 0 && self.queue_end == self.size-1) + // ((self.queue_end + 1) % self.size == self.queue_start) #define FPQ_ALLOCATE(len) mem_allocate_n_typed(len, PMC *) #define FPQ_REALLOCATE(p, len) mem_realloc_n_typed(p, len, PMC *) #define FPQ_ITERATE(index,func) { \ @@ -34,8 +35,11 @@ * * This version omits the "items" field and computes the count as * (queue_end-queue_start)%size + * * It also tries to ensure thread-safety, by having an "owner" thread for * each end of the queue. + * + * TODO: haven't implemented the thread-safety yet!!! */ pmclass FixedPMCQueue3 dynpmc auto_attrs provides queue { ATTR INTVAL size; @@ -87,35 +91,40 @@ pmclass FixedPMCQueue3 dynpmc auto_attrs provides queue { const INTVAL start = self.queue_start; const INTVAL end = self.queue_end; const INTVAL size = self.size; - INTVAL items = FPQ_ITEMS(); + const INTVAL items = FPQ_ITEMS(); + if (newsize < items) Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, "FixedPMCQueue3: Cannot shrink size with items in queue"); - /* TODO: add locking to make this thread-safe */ - + /* TODO: THREADSAFE */ ++newsize; /* reserve one more slot than actually used, so that 0 <= items < size */ if (newsize != size) { - PMC ** const oldstorage = self.storage; - PMC ** newstorage = FPQ_ALLOCATE(newsize); - if ( start > end ) { - mem_sys_memmove( &newstorage[0], &oldstorage[start], (size - start) * sizeof(PMC*)); - mem_sys_memmove( &newstorage[size - start], &oldstorage[0], end * sizeof(PMC*)); + if (start == 0) { + FPQ_REALLOCATE(self.storage, newsize); + self.size = newsize; } else { - mem_sys_memmove( &newstorage[0], &oldstorage[start], (end - start) * sizeof(PMC*)); + PMC ** const oldstorage = self.storage; + PMC ** newstorage = FPQ_ALLOCATE(newsize); + if ( start > end ) { + mem_sys_memmove( &newstorage[0], &oldstorage[start], (size - start) * sizeof(PMC*)); + mem_sys_memmove( &newstorage[size - start], &oldstorage[0], end * sizeof(PMC*)); + } else { + mem_sys_memmove( &newstorage[0], &oldstorage[start], (end - start) * sizeof(PMC*)); + } + if (oldstorage) + mem_sys_free(oldstorage); + self.storage = newstorage; + self.size = newsize; + self.queue_start = 0; + self.queue_end = items; } - if (oldstorage) - mem_sys_free(oldstorage); - self.storage = newstorage; - self.size = newsize; - self.queue_start = 0; - self.queue_end = items; } } /* Push an item onto the queue */ VTABLE void push_pmc(PMC *item) { FPQ_DECL_ATTRS(SELF); - /* TODO: remove race condition to make this thread-safe */ + /* TODO: THREADSAFE */ if (FPQ_FULL()) Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, "FixedPMCQueue3: Pushed too many items"); @@ -127,10 +136,9 @@ pmclass FixedPMCQueue3 dynpmc auto_attrs provides queue { VTABLE PMC* shift_pmc() { FPQ_DECL_ATTRS(SELF); PMC * first_item; - /* TODO: remove race condition to make this thread-safe */ - if(FPQ_EMPTY()) - Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, - "FixedPMCQueue3: No items to shift"); + /* TODO: THREADSAFE */ + if (FPQ_EMPTY()) + return PMCNULL; first_item = self.storage[self.queue_start]; FPQ_IDXF_INCR(queue_start); return first_item; @@ -147,11 +155,24 @@ pmclass FixedPMCQueue3 dynpmc auto_attrs provides queue { FPQ_DECL_ATTRS(SELF); return FPQ_ITEMS(); } + VTABLE INTVAL get_integer() { + FPQ_DECL_ATTRS(SELF); + return FPQ_ITEMS(); + } /* Total amount of allocated storage slots in the queue */ - VTABLE INTVAL get_integer() { + METHOD capacity() { FPQ_DECL_ATTRS(SELF); - return(self.size); + PMC * result; + if (self.size <= 0) + result = PMCNULL; + else { + result = Parrot_pmc_new(INTERP, + Parrot_get_ctx_HLL_type(INTERP, + enum_class_Integer)); + VTABLE_set_integer_native(INTERP, result, self.size-1); // available size is one less than allocate space + } + RETURN(PMC* result); } /* Convert the queue to a FixedPMCArray. The array will have the same @@ -159,12 +180,13 @@ pmclass FixedPMCQueue3 dynpmc auto_attrs provides queue { METHOD to_array() { FPQ_DECL_ATTRS(SELF); PMC * newarray = Parrot_pmc_new(INTERP, enum_class_FixedPMCArray); + const INTVAL size = self.size; PMC ** const s = self.storage; INTVAL i = 0; - VTABLE_set_integer_native(INTERP, newarray, self.size); + VTABLE_set_integer_native(INTERP, newarray, size); FPQ_ITERATE(ptr, VTABLE_set_pmc_keyed_int(INTERP, newarray, i++, s[ptr])); - while (i < self.size) VTABLE_set_pmc_keyed_int(INTERP, newarray, i++, PMCNULL); + while (i < size) VTABLE_set_pmc_keyed_int(INTERP, newarray, i++, PMCNULL); RETURN(PMC* newarray); } @@ -195,3 +217,10 @@ pmclass FixedPMCQueue3 dynpmc auto_attrs provides queue { self.queue_end = 0; } } + +/* + * Local variables: + * c-file-style: "parrot" + * End: + * vim: expandtab shiftwidth=4: + */ diff --git a/t/pmc/fixedpmcqueue.t b/t/pmc/fixedpmcqueue.t index 41cfc67..a2b5669 100644 --- a/t/pmc/fixedpmcqueue.t +++ b/t/pmc/fixedpmcqueue.t @@ -4,7 +4,7 @@ MAIN(); sub MAIN () { load_test_more(); - plan(23); + plan(27); load_linalg_group(); op_new(); @@ -18,6 +18,7 @@ sub MAIN () { vtable_elements(); vtable_get_bool(); vtable_get_integer(); + method_capacity(); method_to_array(); method_total_mem_size(); method_clear(); @@ -37,6 +38,7 @@ sub load_linalg_group() { .local pmc pds pds = loadlib "./dynext/pds_group" if pds goto has_pds_group + say "Missing dynext/pds_group" exit 1 has_pds_group: }; @@ -63,7 +65,7 @@ sub op_does() { $I0 = does $P0, 'queue' is($I0, 1, "Does 'queue'") $I0 = does $P0, "jibbajabba" - is($I0, 0, "Doesn't do 'jibbajabba'") + is($I0, 0, " ... but not 'jibbajabba'") } } @@ -142,14 +144,9 @@ sub vtable_shift_pmc_underflow() { Q:PIR { $P0 = new ['FixedPMCQueue'] $P0 = 5 - $P1 = box 1 - $I0 = 1 - push_eh shift_pmc_underflow $P2 = shift $P0 - $I0 = 0 - shift_pmc_underflow: - pop_eh - ok($I0, "Can't shift from empty queue (throws exception)") + $I0 = isnull $P2 + ok($I0, "Shift on empty queue returns Null") } } @@ -203,6 +200,27 @@ sub vtable_get_integer() { $P0 = 5 $I0 = $P0 + is($I0, 0, " ... still empty after setting capacity") + + $P1 = box 1 + push $P0, $P1 + $I0 = $P0 + is($I0, 1, " ... is 1 after pushing 1 item") + + $P2 = shift $P0 + $I0 = $P0 + is($I0, 0, " ... is 0 after shifting all items") + } +} + +sub method_capacity() { + Q:PIR { + $P0 = new ['FixedPMCQueue'] + $P1 = $P0.'capacity'() + $I0 = isnull $P1 + ok($I0, ".capacity() initially null") + $P0 = 5 + $I0 = $P0.'capacity'() is($I0, 5, " ... changes to reflect capacity") } } diff --git a/t/pmc/fixedpmcqueue2.t b/t/pmc/fixedpmcqueue2.t index 7e0b92b..632ce3f 100644 --- a/t/pmc/fixedpmcqueue2.t +++ b/t/pmc/fixedpmcqueue2.t @@ -4,7 +4,7 @@ MAIN(); sub MAIN () { load_test_more(); - plan(23); + plan(27); load_linalg_group(); op_new(); @@ -18,6 +18,7 @@ sub MAIN () { vtable_elements(); vtable_get_bool(); vtable_get_integer(); + method_capacity(); method_to_array(); method_total_mem_size(); method_clear(); @@ -37,6 +38,7 @@ sub load_linalg_group() { .local pmc pds pds = loadlib "./dynext/pds_group" if pds goto has_pds_group + say "Missing dynext/pds_group" exit 1 has_pds_group: }; @@ -63,7 +65,7 @@ sub op_does() { $I0 = does $P0, 'queue' is($I0, 1, "Does 'queue'") $I0 = does $P0, "jibbajabba" - is($I0, 0, "Doesn't do 'jibbajabba'") + is($I0, 0, " ... but not 'jibbajabba'") } } @@ -142,14 +144,9 @@ sub vtable_shift_pmc_underflow() { Q:PIR { $P0 = new ['FixedPMCQueue2'] $P0 = 5 - $P1 = box 1 - $I0 = 1 - push_eh shift_pmc_underflow $P2 = shift $P0 - $I0 = 0 - shift_pmc_underflow: - pop_eh - ok($I0, "Can't shift from empty queue (throws exception)") + $I0 = isnull $P2 + ok($I0, "Shift on empty queue returns Null") } } @@ -197,12 +194,33 @@ sub vtable_get_bool() { sub vtable_get_integer() { Q:PIR { - $P0 = new ['FixedPMCQueue2'] + $P0 = new ['FixedPMCQueue'] $I0 = $P0 is($I0, 0, "Integer initially 0") $P0 = 5 $I0 = $P0 + is($I0, 0, " ... still empty after setting capacity") + + $P1 = box 1 + push $P0, $P1 + $I0 = $P0 + is($I0, 1, " ... is 1 after pushing 1 item") + + $P2 = shift $P0 + $I0 = $P0 + is($I0, 0, " ... is 0 after shifting all items") + } +} + +sub method_capacity() { + Q:PIR { + $P0 = new ['FixedPMCQueue'] + $P1 = $P0.'capacity'() + $I0 = isnull $P1 + ok($I0, ".capacity() initially null") + $P0 = 5 + $I0 = $P0.'capacity'() is($I0, 5, " ... changes to reflect capacity") } } diff --git a/t/pmc/fixedpmcqueue3.t b/t/pmc/fixedpmcqueue3.t index 8855076..bebeff2 100644 --- a/t/pmc/fixedpmcqueue3.t +++ b/t/pmc/fixedpmcqueue3.t @@ -4,7 +4,7 @@ MAIN(); sub MAIN () { load_test_more(); - plan(23); + plan(27); load_linalg_group(); op_new(); @@ -18,6 +18,7 @@ sub MAIN () { vtable_elements(); vtable_get_bool(); vtable_get_integer(); + method_capacity(); method_to_array(); method_total_mem_size(); method_clear(); @@ -37,6 +38,7 @@ sub load_linalg_group() { .local pmc pds pds = loadlib "./dynext/pds_group" if pds goto has_pds_group + say "Missing dynext/pds_group" exit 1 has_pds_group: }; @@ -63,7 +65,7 @@ sub op_does() { $I0 = does $P0, 'queue' is($I0, 1, "Does 'queue'") $I0 = does $P0, "jibbajabba" - is($I0, 0, "Doesn't do 'jibbajabba'") + is($I0, 0, " ... but not 'jibbajabba'") } } @@ -142,14 +144,9 @@ sub vtable_shift_pmc_underflow() { Q:PIR { $P0 = new ['FixedPMCQueue3'] $P0 = 5 - $P1 = box 1 - $I0 = 1 - push_eh shift_pmc_underflow $P2 = shift $P0 - $I0 = 0 - shift_pmc_underflow: - pop_eh - ok($I0, "Can't shift from empty queue (throws exception)") + $I0 = isnull $P2 + ok($I0, "Shift on empty queue returns Null") } } @@ -203,6 +200,27 @@ sub vtable_get_integer() { $P0 = 5 $I0 = $P0 + is($I0, 0, " ... still empty after setting capacity") + + $P1 = box 1 + push $P0, $P1 + $I0 = $P0 + is($I0, 1, " ... is 1 after pushing 1 item") + + $P2 = shift $P0 + $I0 = $P0 + is($I0, 0, " ... is 0 after shifting all items") + } +} + +sub method_capacity() { + Q:PIR { + $P0 = new ['FixedPMCQueue3'] + $P1 = $P0.'capacity'() + $I0 = isnull $P1 + ok($I0, ".capacity() initially null") + $P0 = 5 + $I0 = $P0.'capacity'() is($I0, 5, " ... changes to reflect capacity") } }