@@ -248,6 +248,117 @@ def __init__(self):
248248 export type AliasedBaseU = BaseU;
249249%s
250250}
251+ """
252+
253+ _ns3_union_spec = """\
254+ namespace ns3
255+ struct A
256+ union
257+ a1 A1
258+ a2 A2
259+ a String
260+ struct A1 extends A
261+ b Boolean
262+ struct A2 extends A
263+ c Boolean
264+ union M
265+ e Boolean
266+ f String
267+ union B
268+ w Boolean
269+ x A
270+ y M
271+ z A2
272+ """
273+
274+ _ns3_union_spec_types = """{
275+ export interface A {
276+ a: string;
277+ }
278+
279+ /**
280+ * Reference to the A polymorphic type. Contains a .tag property to let you
281+ * discriminate between possible subtypes.
282+ */
283+ export interface AReference extends A {
284+ /**
285+ * Tag identifying the subtype variant.
286+ */
287+ '.tag': "a1"|"a2";
288+ }
289+
290+ export interface A1 extends A {
291+ b: boolean;
292+ }
293+
294+ /**
295+ * Reference to the A1 type, identified by the value of the .tag property.
296+ */
297+ export interface A1Reference extends A1 {
298+ /**
299+ * Tag identifying this subtype variant. This field is only present when
300+ * needed to discriminate between multiple possible subtypes.
301+ */
302+ '.tag': 'a1';
303+ }
304+
305+ export interface A2 extends A {
306+ c: boolean;
307+ }
308+
309+ /**
310+ * Reference to the A2 type, identified by the value of the .tag property.
311+ */
312+ export interface A2Reference extends A2 {
313+ /**
314+ * Tag identifying this subtype variant. This field is only present when
315+ * needed to discriminate between multiple possible subtypes.
316+ */
317+ '.tag': 'a2';
318+ }
319+
320+ export interface BW {
321+ '.tag': 'w';
322+ w: boolean;
323+ }
324+
325+ export interface BX {
326+ '.tag': 'x';
327+ x: A1Reference|A2Reference|AReference;
328+ }
329+
330+ export interface BY {
331+ '.tag': 'y';
332+ y: M;
333+ }
334+
335+ export interface BZ extends A2 {
336+ '.tag': 'z';
337+ }
338+
339+ export interface BOther {
340+ '.tag': 'other';
341+ }
342+
343+ export type B = BW | BX | BY | BZ | BOther;
344+
345+ export interface ME {
346+ '.tag': 'e';
347+ e: boolean;
348+ }
349+
350+ export interface MF {
351+ '.tag': 'f';
352+ f: string;
353+ }
354+
355+ export interface MOther {
356+ '.tag': 'other';
357+ }
358+
359+ export type M = ME | MF | MOther;
360+ %s
361+ }
251362"""
252363
253364 _timestamp_mapping = 'type Timestamp = string'
@@ -256,6 +367,7 @@ def __init__(self):
256367
257368 @classmethod
258369 def get_ns_spec (cls ):
370+ """Returns a test namespace which imports another namespace (`ns2`)."""
259371 return cls ._ns_spec
260372
261373 @classmethod
@@ -266,6 +378,7 @@ def get_ns_types_as_declaration(cls):
266378
267379 @classmethod
268380 def get_ns2_spec (cls ):
381+ """Returns a simple namespace."""
269382 return cls ._ns2_spec
270383
271384 @classmethod
@@ -280,6 +393,21 @@ def get_all_types_as_namespace(cls):
280393 ("\n namespace ns2 " + cls ._ns2_spec_types ) % "" ) + "\n \n "
281394 return types
282395
396+ @classmethod
397+ def get_ns3_spec_for_union (cls ):
398+ """
399+ Returns a test namespace which has a union field with all possible types of
400+ members a union can have. It includes (1) primitive, (2) struct, (3) enumerated
401+ subtypes, and (4) a union. This spec is useful in validating the auto-generated
402+ code for a union type defined in a namespace.
403+ """
404+ return cls ._ns3_union_spec
405+
406+ @classmethod
407+ def get_ns3_types_as_declaration (cls ):
408+ return (("\n declare module 'ns3' " + cls ._ns3_union_spec_types
409+ ) % cls ._timestamp_def_formatted ) + "\n \n "
410+
283411
284412class TestTSDTypesE2E (unittest .TestCase ):
285413
@@ -363,6 +491,37 @@ def test_tsd_types_namespace_output(self):
363491 expected_output = SpecHelper .get_all_types_as_namespace ()
364492 self ._verify_generated_output ('output/{}' .format (output_file_name ), expected_output )
365493
494+ def test_tsd_types_for_union (self ):
495+ """
496+ Test tsd types generated for a union which has all possible data types as
497+ members including primitive, struct, enumerated sub types and unions.
498+ """
499+ # Sanity check: stone must be importable for the compiler to work
500+ __import__ ('stone' )
501+
502+ # Compile spec by calling out to stone
503+ p = subprocess .Popen (
504+ [sys .executable ,
505+ '-m' ,
506+ 'stone.cli' ,
507+ 'tsd_types' ,
508+ self .stone_output_directory ,
509+ '--' ,
510+ self .template_file_name ,
511+ '--exclude_error_types' ,
512+ '-i=0' ],
513+ stdin = subprocess .PIPE ,
514+ stderr = subprocess .PIPE )
515+ _ , stderr = p .communicate (
516+ input = (SpecHelper .get_ns3_spec_for_union ()).encode ('utf-8' ))
517+ if p .wait () != 0 :
518+ raise AssertionError ('Could not execute stone tool: %s' %
519+ stderr .decode ('utf-8' ))
520+
521+ # one file must be generated per namespace
522+ expected_ns_output = SpecHelper .get_ns3_types_as_declaration ()
523+ self ._verify_generated_output ('output/ns3.d.ts' , expected_ns_output )
524+
366525
367526if __name__ == '__main__' :
368527 unittest .main ()
0 commit comments