2 # Copyright (C) 2007-2008, Parrot Foundation.
7 t/pmc/class.t - test the Class PMC
24 load_bytecode 'Test/More.pbc'
25 .local pmc exporter, test_ns
26 test_ns = get_namespace [ 'Test'; 'More' ]
27 exporter = new ['Exporter']
28 exporter.'import'( test_ns :named('source'), 'plan ok is isa_ok todo' :named('globals') )
44 'new with init hash'()
52 # L<PDD15/Class PMC API/=item new>
58 ok(1, "$P0 = new ['Class']")
59 isa_ok(class, 'Class')
63 # L<PDD15/Class PMC API/'Class PMCs also have the "I am a class" flag set on them.'>
65 .local pmc class, class_flags_pmc
66 .local int class_flags, class_flag_set
67 .const int POBJ_IS_CLASS_FLAG = 536870912 # 1 << 29
70 class_flags_pmc = inspect class, 'flags'
71 class_flags = class_flags_pmc
72 class_flag_set = class_flags & POBJ_IS_CLASS_FLAG
73 ok(class_flag_set, 'Class PMC has "I am a class" flag set')
78 # L<PDD15/Class PMC API/=item name>
80 .local pmc class, result
83 result = class.'name'()
84 is(result, '', 'name() with no args returns class name, which is empty at first')
87 result = class.'name'()
88 is(result, 'Alex', 'name() with args sets class name')
90 $I0 = 1 # hack for testing exceptions
91 push_eh t_too_many_args
92 class.'name'('Alice', 'Bob')
97 ok($I0, 'name() with too many args fails')
99 result = class.'get_namespace'()
100 is(result, 'Alex', 'name() with args sets namespace too')
104 # L<PDD15/Class PMC API/=item new>
106 .local pmc class, result, attrib
107 .local int isa_object
108 class = new ['Class']
109 result = class.'new'()
111 isa_ok(result, 'Object')
114 push_eh t_non_attribute_key
115 result = class.'new'('abc' => '123' )
120 ok($I0, 'new() with non-attribute key fails')
123 class = new ['Class']
124 class.'add_attribute'('foo')
125 class.'add_attribute'('bar')
126 result = class.'new'('foo' => 1, 'bar' => 2)
127 attrib = getattribute result, 'foo'
128 if attrib != 1 goto nok_3
129 attrib = getattribute result, 'bar'
130 if attrib != 2 goto nok_3
135 ok($I0, 'new() with key/value pairs sets attributes')
139 # L<PDD15/Class PMC API/=item attributes>
141 .local pmc class, attribs
143 class = new ['Class']
144 attribs = class.'attributes'()
145 test_val = isa attribs, 'Hash'
147 ok(test_val, 'attributes() returns a Hash')
150 is(test_val, 0, 'New Class PMC has no attributes')
153 push_eh ok_ro_accessor
154 attribs = class.'attributes'( 'foo' )
159 ok($I0, 'attributes() is read-only accessor')
163 # L<PDD15/Class PMC API/=item add_attribute>
165 .local pmc class, attribs
167 class = new ['Class']
171 class.'add_attribute'()
176 ok($I0, 'add_attribute() with no args fails')
178 class.'add_attribute'( 'foo' )
179 attribs = class.'attributes'()
181 is(test_val, 1, 'add_attribute() with valid single arg adds an attribute')
183 class.'add_attribute'( 'bar', 'Integer' )
184 attribs = class.'attributes'()
186 is(test_val, 2, 'add_attribute() with valid args adds an attribute')
189 push_eh t_existing_attribute
190 class.'add_attribute'( 'foo', 'String' )
194 t_existing_attribute:
195 ok($I0, 'add_attribute() with existing attribute name fails')
199 # L<PDD15/Class PMC API>
200 .sub 'set_attr/get_attr'
201 .local pmc class, class_instance, attrib_in, attrib_out
202 class = new ['Class']
204 class.'add_attribute'("foo")
205 ok(1, 'created a class with one attribute')
207 class_instance = class.'new'()
208 ok(1, 'instantiated the class')
210 attrib_in = new ['Integer']
212 setattribute class_instance, "foo", attrib_in
213 ok(1, 'set an attribute')
215 attrib_out = getattribute class_instance, "foo"
216 is(attrib_out, 42, 'got an attribute')
220 # L<PDD15/Class PMC API/=item add_method>
222 .local pmc class, attribs, test_attr_val, obj_inst
224 class = new ['Class']
233 ok($I0, 'add_method() with no args fails')
237 class.'add_method'( 'foo' )
242 ok($I0, 'add_method() with valid single arg fails')
244 # note this test depends on 'add_attribute' and 'attributes'
245 class.'add_attribute'( 'foo', 'String' )
246 attribs = class.'attributes'()
247 attribs['foo'] = 'bar'
249 .const 'Sub' meth_to_add = 'foo'
251 class.'add_method'( 'foo', meth_to_add )
252 attribs = class.'methods'()
254 is(test_val, 1, 'add_method() one method added')
256 test_val = exists attribs['foo']
257 ok(test_val, 'add_method() method has correct name')
259 test_val = defined attribs['foo']
260 ok(test_val, 'add_method() method is defined')
262 test_attr_val = attribs['foo']
263 isa_ok(test_attr_val, 'Sub', 'add_method() with valid args adds a method')
265 .local string test_string_val
269 test_string_val = class.'foo'()
273 is(test_string_val, 'bar', 'add_method() invoking method added to class works')
275 todo(0, 'add_method() invoking method added to class works', "classes don't seem to call methods yet")
277 obj_inst = class.'new'()
278 test_string_val = obj_inst.'foo'()
279 is(test_string_val, 'bar', 'add_method() invoking method added to class through instance works')
283 push_eh t_existing_method
284 class.'add_method'( 'foo' )
289 ok($I0, 'add_method() with existing method name fails')
297 # L<PDD15/Class PMC API/=item parents>
299 .local pmc class, parents
300 .local int isa_parent
301 class = new ['Class']
302 parents = class.'parents'()
304 ## XXX is this really what's expected?
305 isa_ok(parents, 'ResizablePMCArray', 'parents() returns a ResizablePMCArray')
307 ## NOTE test that accessor is read-only
308 ## NOTE figure out what parents the base Class has by default (if any)
309 ## A: It has no parents by default. (Note, the parents stored in the 'parents'
310 # attribute aren't the parents of Class, they're the parents of the class object
311 # that is an instance of Class.)
317 # L<PDD15/Class PMC API/=item roles>
319 .local pmc class, array
321 class = new ['Class']
322 array = class.'roles'()
324 ## XXX is this really what's expected?
325 isa_ok(array, 'ResizablePMCArray', 'roles() returns a ResizablePMCArray')
327 ## NOTE test that accessor is read-only
328 ## NOTE figure out what roles the base Class has by default (if any)
329 # A: None. See comment for parents().
335 # L<PDD15/Class PMC API/=item inspect>
337 .local pmc class, result
340 class = new ['Class']
342 class.'add_attribute'('a')
344 result = class.'inspect'()
345 ok(1, 'inspect() with no args called returns successfully')
347 test_val = elements result
348 is(test_val, 7, 'inspect() returns correctly sized value')
350 result = class.'inspect'('name')
351 is(result, 'foo', 'inspect() "name" param returns expected value')
353 result = class.'inspect'('attributes')
354 test_val = elements result
355 is(test_val, 1, 'inspect() "attributes" param returns correctly sized value')
361 .local pmc attrs, class, class_instance, test_pmc
362 .local string test_name
366 attrs['name'] = 'Monkey'
367 class = new ['Class'], attrs
368 class.'add_attribute'('banana')
369 class_instance = class.'new'()
370 ok(1, 'clone() created class Monkey and instantiated it')
372 class_instance = clone class
373 ok(1, 'cloned class Monkey')
375 test_name = class_instance.'inspect'('name')
376 is(test_name, '', 'clone() name is empty')
378 test_pmc = class_instance.'inspect'('namespace')
379 $I0 = isnull test_pmc
380 ok($I0, 'clone() namespace is null')
382 test_pmc = class_instance.'inspect'('attributes')
383 test_val = elements test_pmc
384 is(test_val, 1, 'clone() attribute survived cloning')
386 class_instance.'add_attribute'('jungle')
387 ok(1, 'clone() can modify cloned class')
392 .local pmc class, class_instance, monkey, mandrill, test_ns
393 .local string test_string_val
397 class['name'] = 'Monkey2'
398 class_instance = new ['Class'], class
399 class_instance.'add_attribute'('banana')
400 monkey = class_instance.'new'()
401 ok(1, 'clone_pmc() created class Monkey and instantiated it')
404 class['name'] = 'Mandrill'
405 mandrill = clone class_instance, class
406 ok(1, 'clone_pmc() cloned class Monkey with Hash argument')
408 test_string_val = mandrill.'inspect'('name')
409 is(test_string_val, 'Mandrill', 'clone_pmc() name is new one set in the Hash')
411 test_ns = mandrill.'inspect'('namespace')
412 test_string_val = test_ns
413 is(test_string_val, 'Mandrill', 'clone_pmc() namespace is Mandrill too')
415 test_ns = mandrill.'inspect'('attributes')
416 num_elems = elements test_ns
417 is(num_elems, 1, 'clone_pmc() attribute survived cloning')
419 mandrill.'add_attribute'('jungle')
420 ok(1, 'clone_pmc() can modify cloned class')
424 .sub 'new with init hash'
425 .local pmc class, init_hash, attrs, methods, meth_to_add, class_instance
426 .local pmc attr_val, result
427 init_hash = new ['Hash']
429 # We'll have some attributes...
430 attrs = new ['ResizablePMCArray']
433 init_hash['attributes'] = attrs
436 methods = new ['Hash']
437 meth_to_add = get_global 'add'
438 methods['add'] = meth_to_add
439 init_hash['methods'] = methods
441 class = new ['Class'], init_hash
442 ok(1, 'new() created new class with attributes and methods supplied')
444 # Instantiate and try setting each attribute.
445 class_instance = class.'new'()
446 attr_val = new ['Integer']
448 setattribute class_instance, 'x', attr_val
449 ok(1, 'new() set first attribute')
451 attr_val = new ['Integer']
453 setattribute class_instance, 'y', attr_val
454 ok(1, 'new() set second attribute')
457 result = class_instance.'add'()
458 is(result, 42, 'new() added method returns expected value')
462 $P0 = getattribute self, "x"
463 $P1 = getattribute self, "y"
464 $P2 = new ['Integer']
470 # L<PDD15/Class PMC API/=item isa>
473 class = new ['Class']
475 test_isa( class, 'Class', 1 )
476 test_isa( class, 'Hash', 0 )
477 test_isa( class, 'Foo', 0 )
485 .local string message
490 isa_class = obj.'isa'( class )
491 if isa_class goto is_class
492 message .= "The object isn't a "
498 message .= "The object is a "
502 is($I0, expected, message)
507 # L<PDD15/Class PMC API/=item does>
513 .local pmc red, green, blue
514 attrs['name'] = 'Red'
515 red = new ['Role'], attrs
517 attrs['name'] = 'Green'
518 green = new ['Role'], attrs
520 attrs['name'] = 'Blue'
521 blue = new ['Role'], attrs
523 green.'add_role'( blue )
526 color = new ['Class']
528 test_does( color, 'Red', 0 )
530 color.'add_role'( red )
531 test_does( color, 'Red', 1 )
533 color.'add_role'( green )
534 test_does( color, 'Green', 1 )
535 test_does( color, 'Blue', 1 )
537 test_does( color, 'Class', 1 )
542 .param string role_name
544 .local int does_a_role
545 .local string message
550 does_a_role = obj.'does'( role_name )
551 if does_a_role goto does_role
552 message .= "The object doesn't "
558 message .= "The object does "
562 is($I0, expected, message)
567 # L<PDD15/Class PMC API/=item does>
568 .sub 'more does' # RT #42974
572 .local pmc red, green, blue
573 attrs['name'] = 'Red'
574 red = new ['Role'], attrs
576 attrs['name'] = 'Green'
577 green = new ['Role'], attrs
579 attrs['name'] = 'Blue'
580 blue = new ['Role'], attrs
582 green.'add_role'( blue )
585 color = new ['Class']
588 $I0 = color.'does'($S0)
589 is($I0, 0, 'does not Red')
591 color.'add_role'( red )
592 $I0 = color.'does'($S0)
593 is($I0, 1, 'does Red')
602 ok(1, 'inheritance of two different anonymous classes works')
609 # vim: expandtab shiftwidth=4 ft=pir: