fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / t / pmc / namespace.t
blob0a14ab6593d8baedc16ebf6896349b90832b144c
1 #!./parrot
2 # Copyright (C) 2006-2010, Parrot Foundation.
3 # $Id$
5 =head1 NAME
7 t/pmc/namepspace.t - test NameSpace PMC
9 =head1 SYNOPSIS
11     % prove t/pmc/namespace.t
13 =head1 DESCRIPTION
15 Tests the NameSpace PMC. Some things that it tests specifically:
17 =over 4
19 =item* Creating new NameSpace PMCs
21 =item* Verify that things which are supposed to return a NameSpace actually
22 do.
24 =item* Various forms of get_global opcode
26 =item* Finding and calling Subs which are stored in the NameSpace
28 =item* Methods on the NameSpace PMC
30 =item* Building NameSpace hierarchies on the fly
32 =item* HLL NameSpaces
34 =back
36 Items that need to be tested according to PDD21, or the current source code
37 of the NameSpace PMC:
39 =over 4
41 =item* methods: add_sub, del_sub, del_var, del_namespace
43 =item* Typed and Untyped interfaces
45 =item* Subclassing NameSpace (If it's possible)
47 =item* .'export_to'()
49 Although NameSpace.'export_to'() is used in test_more.pir.
51 =back
53 =cut
55 .namespace []
57 .sub main :main
58     .include 'test_more.pir'
59     plan(74)
61     create_namespace_pmc()
62     verify_namespace_type()
63     get_namespace_class()
64     keyed_namespace_lookup()
65     get_global_opcode()
66     get_sub_from_namespace_hash()
67     access_sub_in_namespace()
68     get_namespace_from_sub()
69     build_namespaces_at_runtime()
70     hll_namespaces()
71     anon_function_namespace()
72     find_name_opcode()
73     namespace_methods()
74     export_to_method()
75 .end
77 # L<PDD21/Namespace PMC API/=head4 Untyped Interface>
78 .sub 'create_namespace_pmc'
79     push_eh eh1
80     $P0 = new ['NameSpace']
81     ok(1, "Create new Namespace PMC")
82     goto _end
83   eh1:
84     ok(0, "Could not create Namespace PMC")
85   _end:
86     pop_eh
87 .end
89 .sub 'verify_namespace_type'
90     $P0 = get_global "Foo"
91     typeof $S0, $P0
92     is($S0, "NameSpace", "A NameSpace is a NameSpace")
94     # root namespace
95     $P0 = get_root_namespace
96     typeof $S0, $P0
97     is($S0, "NameSpace", "Root NameSpace is a NameSpace")
99     # While we're here. Prove that the root namespace stringifies to ""
100     $S0 = $P0
101     is($S0, "", "Root NameSpace stringifies to empty string")
103     # parrot namespace
104     $P1 = $P0["parrot"]
105     typeof $S0, $P1
106     is($S0, "NameSpace", "::parrot NameSpace is a NameSpace")
108     # get_namespace with no args
109     $P0 = get_namespace
110     typeof $S0, $P1
111     is($S0, "NameSpace", "Current NameSpace is a NameSpace")
113     # Prove that HLL namespace names are mangled to lower-case
114     $P0 = get_root_namespace ["MyHLL"]
115     $I0 = isnull $P0
116     is($I0, 1, "HLL NameSpace names are stored lowercase")
118     $P0 = get_root_namespace ["myhll"]
119     $I0 = isnull $P0
120     is($I0, 0, "HLL NameSpaces are name-mangled lowercase")
122     # Get an HLL namespace and verify that it's a NameSpace PMC
123     $P0 = get_root_namespace ["myhll"]
124     $S0 = typeof $P0
125     is($S0, "NameSpace", "HLL NameSpaces are NameSpaces too")
127 .end
129 .sub 'get_namespace_class'
130     # First, prove that we don't have a class until it's created
131     $P0 = get_global "Foo"
132     $P1 = get_class $P0
133     $I0 = isnull $P1
134     is($I0, 1, "NameSpace doesn't have a Class till it's created")
136     # Can create a new class from a NameSpace
137     $P1 = newclass $P0
138     $I0 = isnull $P1
139     is($I0, 0, "Create Class from NameSpace")
141     # New Class is a Class
142     $S0 = typeof $P1
143     is($S0, "Class", "get_class on a NameSpace returns a Class")
145     # Class has same name as namespace
146     $S0 = $P0
147     $S1 = $P1
148     is($S0, $S1, "Class has same name as NameSpace")
150     # Now, we do have a class
151     $P1 = get_class $P0
152     $I0 = isnull $P1
153     is($I0, 0, "get_class on a NameSpace returns something")
155     # Create object from class from NameSpace
156     push_eh eh
157     $P2 = new $P1
158     ok(1, "Can create a new object from a namespace")
159     goto pmc_is_created
160   eh:
161     ok(0, "Cannot create a new object from a namespace")
162   pmc_is_created:
163     pop_eh
165     # Object from Class from NameSpace has right type
166     $S0 = typeof $P2
167     is($S0, "Foo", "Object created from class has name of NameSpace")
169 .end
171 .sub keyed_namespace_lookup
172     # Tests to verify behavior of TT #1449
173     $P0 = get_root_namespace
175     # Keyed lookup
176     $P1 = $P0["parrot";"Foo";"Bar"]
177     $I0 = isnull $P1
178     is($I0, 0, "can lookup nested namespace by Key")
179     # TODO: Get the function from this namespace and call it to verify we have
180     #       the correct one.
182     # Array lookup
183     $P1 = new ['ResizableStringArray']
184     $P1[0] = "parrot"
185     $P1[1] = "Foo"
186     $P1[2] = "Bar"
187     $P1[3] = "Baz"
188     $P2 = $P0[$P1]
189     $I0 = isnull $P1
190     is($I0, 0, "can lookup nested namespace by RSA")
191     # TODO: Get the function from this namespace and call it to verify we have
192     #       the correct one.
194     # String lookup
195     $P1 = $P0["parrot"]
196     $P2 = $P1["Foo"]
197     $I0 = isnull $P1
198     is($I0, 0, "can lookup namespace by string")
199     $I0 = isnull $P2
200     is($I0, 0, "can lookup namespace by string")
201     # TODO: Get the function from this namespace and call it to verify we have
202     #       the correct one.
203 .end
205 # L<PDD21//>
206 .sub 'get_global_opcode'
207   test1:
208     push_eh eh1
209     $P0 = get_global "baz"
210     $S0 = $P0()
211     is($S0, "", "Can get_global a .sub")
212     goto end_test1
213   eh1:
214     ok(0, "Cannot get_global a .sub")
215   end_test1:
216     pop_eh
218   test2:
219     push_eh eh2
220     $P0 = get_global ["Foo"], "baz"
221     $S0 = $P0()
222     is($S0, "Foo", "Get Sub from NameSpace")
223     goto end_test2
224   eh2:
225     ok(0, "Cannot get Sub from NameSpace Foo")
226   end_test2:
227     pop_eh
229   test3:
230     push_eh eh3
231     $P0 = get_global ["Foo";"Bar"], "baz"
232     $S0 = $P0()
233     is($S0, "Foo::Bar", "Get Sub from nested NameSpace")
234     goto end_test3
235   eh3:
236     ok(0, "Cannot get Sub from NameSpace Foo::Bar")
237   end_test3:
238     pop_eh
240   test4:
241     throws_substring( <<'CODE', 'Null PMC access in invoke', 'Invoking a non-existent sub')
242         .sub main
243             $P0 = get_global ["Foo"], "SUB_THAT_DOES_NOT_EXIST"
244             $P0()
245         .end
246 CODE
248   test5:
249     # this used to behave differently from the previous case.
250     throws_substring( <<'CODE', 'Null PMC access in invoke', 'Invoking a non-existent sub')
251         .sub main
252             $P0 = get_global ["Foo";"Bar"], "SUB_THAT_DOES_NOT_EXIST"
253             $P0()
254         .end
255 CODE
257   test6:
258     push_eh eh6
259     $P0 = get_global [ iso-8859-1:"Fran\x{E7}ois" ], "baz"
260     $S0 = $P0()
261     is($S0, iso-8859-1:"Fran\x{E7}ois", "Found sub in ISO-8859 NameSpace")
262     goto end_test6
263   eh6:
264     ok(0, "Cannot find sub in ISO-8859 NameSpace")
265   end_test6:
266     pop_eh
268   test7:
269     push_eh eh7
270     $P0 = get_global [ "Foo";iso-8859-1:"Fran\x{E7}ois" ], "baz"
271     $S0 = $P0()
272     is($S0, iso-8859-1:"Foo::Fran\x{E7}ois", "Found sub in nested ISO-8859 NameSpace")
273     goto end_test7
274   eh7:
275     ok(0, "Cannot find sub in ISO-8859 NameSpace")
276   end_test7:
277     pop_eh
279   test8:
280     push_eh eh8
281     $P0 = get_global [ unicode:"Fran\x{00E7}ois" ], "baz"
282     $I0 = isnull $P0
283     is($I0, 0, "Find Sub in an ISO-8859-1 NameSpace looked up by a Unicode name")
284     $S0 = $P0()
285     is($S0, iso-8859-1:"Fran\x{E7}ois", "ISO-8859 NameSpace with Unicode name")
286     goto end_test8
287   eh8:
288     ok(0, "Cannot find ISO-8859 NameSpace using Unicode name")
289   end_test8:
290     pop_eh
292   test9:
293     push_eh eh9
294     $P0 = get_global [ unicode:"\x{20AC}uros" ], "baz"
295     $S0 = $P0()
296     is($S0, unicode:"\x{20AC}uros", "Found sub in Unicode NameSpace")
297     goto end_test9
298   eh9:
299     ok(0, "Cannot find sub in Unicode NameSpace")
300   end_test9:
301     pop_eh
303   test10:
304     push_eh eh10
305     $P0 = get_global [ "Foo";unicode:"\x{20AC}uros" ], "baz"
306     $S0 = $P0()
307     is($S0, unicode:"Foo::\x{20AC}uros", "Found sub in nested Unicode NameSpace")
308     goto end_test10
309   eh10:
310     ok(0, "Cannot find sub in nested Unicode NameSpace")
311   end_test10:
312     pop_eh
314 .end
316 .sub 'get_sub_from_namespace_hash'
317     #See that a NameSpace does Hash
318     $P0 = get_global "Foo"
319     $I0 = does $P0, 'hash'
320     ok($I0, "Namespace does hash")
322     # Use a hash key to get a Sub in a namespace
323     $P1 = $P0["baz"]
324     $S0 = $P1()
325     is($S0, "Foo", "Get the Sub from the NameSpace as a Hash")
327     # Use hash keys to get Subs and nested NameSpaces in NameSpaces
328     $P1 = $P0["Bar"]
329     $P2 = $P1["baz"]
330     $S0 = $P2()
331     is($S0, "Foo::Bar", "Get the Sub from the nested NameSpace as a Hash")
333     # Use nested keys to access nested NameSpaces
334     $P1 = $P0[ "Bar";"baz" ]
335     $S0 = $P1()
336     is($S0, "Foo::Bar", "Get Sub from nested NameSpace with multi-key")
338     # Alias a namespace and access it by Key
339     $P1 = $P0["Bar"]
340     set_global "TopBar", $P1
341     $P2 = get_global ["TopBar"], "baz"
342     is($S0, "Foo::Bar", "Alias namespace")
344     # Get nested NameSpace with ISO-8859 name
345     $P1 = $P0[ iso-8859-1:"Fran\x{E7}ois" ]
346     $P2 = $P1["baz"]
347     $S0 = $P2()
348     is($S0, iso-8859-1:"Foo::Fran\x{E7}ois", "Hash-get nested ISO-8859 NameSpace")
350     $P1 = $P0[ iso-8859-1:"Fran\x{E7}ois";"baz" ]
351     $S0 = $P1()
352     is($S0, iso-8859-1:"Foo::Fran\x{E7}ois", "Hash-get nested ISO-8859 NameSpace Sub")
354     $P0 = get_global iso-8859-1:"Fran\x{E7}ois"
355     $P1 = $P0[ "baz" ]
356     $S0 = $P1()
357     is($S0, iso-8859-1:"Fran\x{E7}ois", "Hash-get ISO-8859 NameSpace")
358 .end
360 .sub 'access_sub_in_namespace'
361     # Direct access of sub that does exist in current namespace
362     $S0 = baz()
363     $P0 = get_global "baz"
364     $S1 = $P0()
365     is($S0, $S1, "Direct and Indirect Sub calls")
367     # Direct access of sub that doesn't exist in current namespace
368     push_eh eh
369     'SUB_AINT_THERE'()
370     ok(0, "Directly called a sub that doesn't exist")
371     goto _end
372   eh:
373     ok(1, "Can't direct call a sub that doesn't exist")
374   _end:
375     pop_eh
376 .end
378 .sub 'get_namespace_from_sub'
379     # root namespace is "parrot"
380     $P0 = get_global "baz"
381     $P1 = $P0."get_namespace"()
382     $S0 = $P1
383     is($S0, "parrot", "Get the root namespace from a sub in the root namespace")
385     # Get an explicit namespace
386     $P0 = get_global ["Foo"], "baz"
387     $P1 = $P0."get_namespace"()
388     $S0 = $P1
389     is($S0, "Foo", "Get the namespace from a Sub in the NameSpace")
391     # Get namespace from the current sub
392     .include 'interpinfo.pasm'
393     $P0 = interpinfo .INTERPINFO_CURRENT_SUB
394     $P1 = $P0."get_namespace"()
395     $S0 = $P1
396     is($S0, "parrot", "Get namespace from current sub")
398     # Now get the current sub again
399     $P2 = $P1["get_namespace_from_sub"]
400     $S0 = typeof $P2
401     is($S0, "Sub", "Get the current sub from namespace from current sub")
402 .end
404 .sub 'build_namespaces_at_runtime'
405     $P0 = get_root_namespace
406     $P1 = $P0["parrot"]
407     $P3 = new ['NameSpace']
408     $P1["Temp1"] = $P3
409     $P2 = $P3.'get_name'()
410     $S0 = join '::', $P2
411     is($S0, "parrot::Temp1", "Add a NameSpace with a given name")
413     # test VTABLE_get_string while we are here
414     $S0 = $P1
415     is($S0, "parrot", "get_string on HLL NameSpace")
417     $S0 = $P3
418     is($S0, "Temp1", "get_string on NameSpace")
419 .end
421 .sub 'hll_namespaces'
422     # Fetch HLL Global using an RSA. Current HLL == parrot
423     $P4 = new ['FixedStringArray']
424     $P4 = 1
425     $P4[0] = 'Foo'
426     $P0 = get_hll_namespace $P4
427     $P2 = $P0.'get_name'()
428     $S0 = join '::', $P2
429     is($S0, "parrot::Foo", "get_hll_namespace_p")
431     # Get an HLL namespace using a key. Current HLL == parrot
432     $P2 = get_hll_namespace ["Foo"]
433     $P2 = $P2.'get_name'()
434     $S0 = join '::', $P2
435     is($S0, "parrot::Foo", "get_hll_namespace_kc")
437     # Get a sub from an HLL Namespace using a key. Current HLL == parrot
438     $P0 = get_hll_namespace ["Foo"]
439     $P1 = $P0["baz"]
440     $S0 = $P1()
441     is($S0, "Foo", "get a Sub from a HLL namespace")
443     # find something an a different .HLL
444     push_eh eh1
445     $P0 = get_root_namespace ["myhll"]
446     $P1 = $P0["baz"]
447     $S0 = $P1()
448     is($S0, "MyHLL", "Found Sub in HLL namespace by key")
449     goto end_test1
450   eh1:
451     ok(0, "Cannot find sub in HLL NameSpace by key")
452   end_test1:
453     pop_eh
455     # get_root_namespace won't return something not a namespace
456     $P0 = get_root_namespace ["myhll";"baz"]
457     $I0 = isnull $P0
458     is($I0, 1, "get_root_namespace only returns NameSpace PMCs")
459 .end
461 .sub 'anon_function_namespace'
463     $S0 = <<"CODE"
464         .namespace ["anon_test_internal_ns"]
465         .sub anon_test_internal :main :anon
466             $P0 = get_namespace
467             .return($P0)
468         .end
469 CODE
470     $P0 = compreg "PIR"
471     $P1 = $P0($S0)
472     $P2 = $P1()
473     $S0 = typeof $P2
474     is($S0, "NameSpace", "get_namespace from anon sub")
475     $P3 = $P2.'get_name'()
476     $S0 = join "::", $P3
477     is($S0, "parrot::anon_test_internal_ns", "get_namespace name from anon sub")
478 .end
480 .sub 'find_name_opcode'
482     $S0 = <<'CODE'
483         .namespace ['pugs';'main']
484         .sub 'main' :main
485             push_eh just_in_case
486             $P0 = find_name "&say"
487             $P0()
488             $I0 = 1
489             goto the_end
490           just_in_case:
491             $I0 = 0
492           the_end:
493             pop_eh
494             .return($I0)
495         .end
497         .sub "&say"
498             noop
499         .end
500 CODE
501     $P0 = compreg "PIR"
502     $P1 = $P0($S0)
503     $I0 = $P1()
504     is($I0, 1, "find_name sub with sigil in namespace")
505 .end
507 .sub 'namespace_methods'
508     $P0 = get_namespace
510     # make_namespace returns the existing namespace if it exists
511     $P1 = $P0.'make_namespace'("Foo")
512     $P2 = $P1["baz"]
513     $S0 = $P2()
514     is($S0, "Foo", "make_namespace does not overwrite existing NS")
516     # First we don't have it...
517     $P1 = $P0["NewNamespace1"]
518     $I0 = isnull $P1
519     is($I0, 1, "something that doesn't exist really doesn't")
521     # ...now we do!
522     $P1 = $P0.'make_namespace'("NewNamespace1")
523     $P2 = $P1["baz"]
524     $I0 = isnull $P2
525     is($I0, 1, "make_namespace also creates new namespaces")
527     $P1 = new ["NameSpace"]
528     $P0.'add_namespace'("NewNamespace2", $P1)
529     $P2 = $P0["NewNamespace2"]
530     is($P1, $P2, "add_namespace adds a new namespace")
532     # test add_sub
534     $P1 = new 'Integer'
535     $P1 = 25
536     $P0.'add_var'("My_Integer", $P1)
537     $P2 = $P0["My_Integer"]
538     is($P1, $P2, "add_var adds a variable to the namespace")
540     # We've already tested NameSpace."get_name" elsewhere in this file
542     $P1 = $P0.'find_namespace'("Foo")
543     $P2 = $P1["baz"]
544     $S0 = $P2()
545     is($S0, "Foo", "find_namespace finds a .namespace constant")
547     $P1 = $P0.'find_namespace'("NewNamespace1")
548     $S0 = typeof $P1
549     is($S0, "NameSpace", "find_namespace finds a namespace added at runtime")
551     $P1 = $P0.'find_sub'("baz")
552     $S0 = $P1()
553     is($S0, "", "find_sub finds a sub like it should")
555     $P1 = $P0.'find_sub'("NewNamespace1")
556     $I0 = isnull $P1
557     is($I0, 1, "find_sub won't find a non-sub")
559     $P1 = $P0.'find_sub'("DOESNT EXIST")
560     $I0 = isnull $P1
561     is($I0, 1, "find_sub won't find something that doesn't exist")
563     $P1 = $P0.'find_var'("My_Integer")
564     $I0 = $P1
565     is($I0, 25, "find_var finds a variable we've saved in a namespace")
567     $P1 = $P0.'find_var'("ALSO DOESNT EXIST")
568     $I0 = isnull $P1
569     is($I0, 1, "find_var won't find something that doesn't exist")
571     $P1 = $P0.'find_var'("baz")
572     $S0 = typeof $P1
573     is($S0, "Sub", "find_var also finds subs")
574     $S0 = $P1()
575     is($S0, "", "find_var finds the correct sub")
577     # Test del_namespace. Test that it deletes an existing namespace, and that
578     # it won't delete something that isn't a namespace
580     # Test del_sub. Test that it deletes an existing sub and that it
581     # won't delete something that isn't a sub
583     # Test del_var. It will delete any type of thing
584 .end
586 .sub 'export_to_method'
587     .local string errormsg, description
589     errormsg = "destination namespace not specified"
590     description = "export_to() Null NameSpace"
591     throws_substring(<<"CODE", errormsg, description)
592         .sub 'test' :main
593             .local pmc nsa, nsb, ar
595             ar = new ['ResizableStringArray']
596             push ar, 'baz'
597             nsa = new ['Null']
598             nsb = get_namespace ['Foo']
599             nsb.'export_to'(nsa, ar)
600         .end
601 CODE
603     errormsg = "exporting default object set not yet implemented"
604     description = 'export_to() with null exports default object set !!!UNSPECIFIED!!!'
605     throws_substring(<<'CODE', errormsg, description)
606         .sub 'test' :main
607             .local pmc nsa, nsb, ar
609             ar = new ['Null']
610             nsa = get_namespace
611             nsb = get_namespace ['Foo']
612             nsb.'export_to'(nsa, ar)
613         .end
614 CODE
617     errormsg = "exporting default object set not yet implemented"
618     description = 'export_to() with empty array exports default object set !!!UNSPECIFIED!!!'
619     throws_substring(<<'CODE', errormsg, description)
620         .sub 'test' :main
621             .local pmc nsa, nsb, ar
623             ar = new ['ResizableStringArray']
624             nsa = get_namespace
625             nsb = get_namespace ['Foo']
626             nsb.'export_to'(nsa, ar)
627         .end
628 CODE
630     errormsg = "exporting default object set not yet implemented"
631     description = 'export_to() with empty hash exports default object set !!!UNSPECIFIED!!!'
632     throws_substring(<<'CODE', errormsg, description)
633         .sub 'test' :main
634             .local pmc nsa, nsb, ar
636             ar = new ['Hash']
637             nsa = get_namespace
638             nsb = get_namespace ['Foo']
639             nsb.'export_to'(nsa, ar)
640         .end
641 CODE
643 # Things to add: successful export_to with non-empty array, successful
644 # export_to with non-empty hash. both of these things across HLL boundaries
646 .end
648 ##### TEST NAMESPACES AND FUNCTIONS #####
649 # These functions and namespaces are used for the tests above
651 # The current namespace
652 .namespace []
653 .sub 'baz'
654     .return("")
655 .end
657 # NameSpace "Foo"
658 .namespace ["Foo"]
659 .sub 'baz'
660     .return("Foo")
661 .end
663 # NameSpace "Foo";"Bar". Nested namespace
664 .namespace ["Foo";"Bar"]
665 .sub 'baz'
666     .return("Foo::Bar")
667 .end
669 # Namespace "Foo";"Bar";"Baz". Nested namespace
670 .namespace ["Foo";"Bar";"Baz"]
671 .sub 'widget'
672     .return("Foo::Bar::Baz")
673 .end
675 # Namespace specified in ISO-8859-1
676 .namespace [ iso-8859-1:"Fran\x{E7}ois" ]
677 .sub 'baz'
678     .return(iso-8859-1:"Fran\x{E7}ois")
679 .end
681 # Nested namespace specified in ISO-8859
682 .namespace [ "Foo"; iso-8859-1:"Fran\x{E7}ois" ]
683 .sub 'baz'
684     .return(iso-8859-1:"Foo::Fran\x{E7}ois")
685 .end
687 # Namesace specified in Unicode
688 .namespace [ unicode:"\x{20AC}uros" ]
689 .sub 'baz'
690     .return(unicode:"\x{20AC}uros")
691 .end
693 # Nested namespace specified in Unicode
694 .namespace [ "Foo";unicode:"\x{20AC}uros" ]
695 .sub 'baz'
696     .return(unicode:"Foo::\x{20AC}uros")
697 .end
699 .HLL "MyHLL"
700 .sub 'baz'
701     .return("MyHLL")
702 .end
704 # Local Variables:
705 #   mode: pir
706 #   fill-column: 100
707 # End:
708 # vim: expandtab shiftwidth=4 ft=pir: