@@ -1509,6 +1509,139 @@ defmodule Module.Types.DescrTest do
15091509 |> equal? ( integer ( ) )
15101510 end
15111511
1512+ test "map_to_list" do
1513+ assert map_to_list ( :term ) == :badmap
1514+ assert map_to_list ( integer ( ) ) == :badmap
1515+ assert map_to_list ( union ( open_map ( ) , integer ( ) ) ) == :badmap
1516+ assert map_to_list ( none ( ) ) == :badmap
1517+
1518+ # A non existent map type is refused
1519+ assert open_map ( )
1520+ |> difference ( open_map ( a: if_set ( term ( ) ) , c: if_set ( term ( ) ) ) )
1521+ |> map_to_list ( ) == :badmap
1522+
1523+ assert map_to_list ( empty_map ( ) ) == { :ok , empty_list ( ) }
1524+ assert map_to_list ( open_map ( ) ) == { :ok , list ( tuple ( [ term ( ) , term ( ) ] ) ) }
1525+
1526+ assert map_to_list ( closed_map ( a: integer ( ) ) ) ==
1527+ { :ok , non_empty_list ( tuple ( [ atom ( [ :a ] ) , integer ( ) ] ) ) }
1528+
1529+ assert map_to_list ( closed_map ( a: integer ( ) , b: atom ( ) ) ) ==
1530+ { :ok ,
1531+ non_empty_list (
1532+ tuple ( [ atom ( [ :a ] ) , integer ( ) ] )
1533+ |> union ( tuple ( [ atom ( [ :b ] ) , atom ( ) ] ) )
1534+ ) }
1535+
1536+ assert map_to_list ( union ( closed_map ( a: float ( ) ) , closed_map ( b: pid ( ) ) ) ) ==
1537+ { :ok ,
1538+ non_empty_list (
1539+ tuple ( [ atom ( [ :a ] ) , float ( ) ] )
1540+ |> union ( tuple ( [ atom ( [ :b ] ) , pid ( ) ] ) )
1541+ ) }
1542+
1543+ # Test with domain keys
1544+ assert map_to_list ( closed_map ( [ { domain_key ( :integer ) , binary ( ) } ] ) ) ==
1545+ { :ok , list ( tuple ( [ integer ( ) , binary ( ) ] ) ) }
1546+
1547+ assert map_to_list ( closed_map ( [ { domain_key ( :tuple ) , binary ( ) } ] ) ) ==
1548+ { :ok , list ( tuple ( [ tuple ( ) , binary ( ) ] ) ) }
1549+
1550+ # Test with both atom keys and domain keys
1551+ map_with_both =
1552+ closed_map ( [
1553+ { :a , atom ( [ :ok ] ) } ,
1554+ { :b , float ( ) } ,
1555+ { domain_key ( :integer ) , binary ( ) } ,
1556+ { domain_key ( :tuple ) , pid ( ) }
1557+ ] )
1558+
1559+ assert map_to_list ( map_with_both ) ==
1560+ { :ok ,
1561+ non_empty_list (
1562+ tuple ( [ atom ( [ :a ] ) , atom ( [ :ok ] ) ] )
1563+ |> union ( tuple ( [ atom ( [ :b ] ) , float ( ) ] ) )
1564+ |> union ( tuple ( [ integer ( ) , binary ( ) ] ) )
1565+ |> union ( tuple ( [ tuple ( ) , pid ( ) ] ) )
1566+ ) }
1567+
1568+ # Test open maps - should return list of key-value tuples
1569+ assert map_to_list ( open_map ( ) ) == { :ok , list ( tuple ( [ term ( ) , term ( ) ] ) ) }
1570+ assert map_to_list ( open_map ( a: integer ( ) ) ) == { :ok , non_empty_list ( tuple ( [ term ( ) , term ( ) ] ) ) }
1571+
1572+ { :ok , list } = map_to_list ( open_map ( [ { domain_key ( :integer ) , binary ( ) } ] ) )
1573+
1574+ assert list (
1575+ Enum . reduce (
1576+ [ binary ( ) , float ( ) , pid ( ) , port ( ) , reference ( ) ] ++
1577+ [ fun ( ) , atom ( ) , tuple ( ) , open_map ( ) , list ( term ( ) , term ( ) ) ] ,
1578+ tuple ( [ integer ( ) , binary ( ) ] ) ,
1579+ fn domain , acc -> union ( acc , tuple ( [ domain , term ( ) ] ) ) end
1580+ )
1581+ )
1582+ |> equal? ( list )
1583+
1584+ # Test with multiple domain keys
1585+ multiple_domains =
1586+ closed_map ( [
1587+ { domain_key ( :integer ) , atom ( [ :int ] ) } ,
1588+ { domain_key ( :float ) , atom ( [ :float ] ) } ,
1589+ { domain_key ( :atom ) , binary ( ) } ,
1590+ { domain_key ( :binary ) , integer ( ) } ,
1591+ { domain_key ( :tuple ) , float ( ) }
1592+ ] )
1593+
1594+ assert map_to_list ( multiple_domains ) ==
1595+ { :ok ,
1596+ list (
1597+ tuple ( [ integer ( ) , atom ( [ :int ] ) ] )
1598+ |> union ( tuple ( [ float ( ) , atom ( [ :float ] ) ] ) )
1599+ |> union ( tuple ( [ atom ( ) , binary ( ) ] ) )
1600+ |> union ( tuple ( [ binary ( ) , integer ( ) ] ) )
1601+ |> union ( tuple ( [ tuple ( ) , float ( ) ] ) )
1602+ ) }
1603+
1604+ # Test dynamic maps
1605+ assert map_to_list ( dynamic ( open_map ( ) ) ) ==
1606+ { :ok , dynamic ( list ( tuple ( [ term ( ) , term ( ) ] ) ) ) }
1607+
1608+ assert map_to_list ( dynamic ( closed_map ( a: integer ( ) ) ) ) ==
1609+ { :ok , dynamic ( non_empty_list ( tuple ( [ atom ( [ :a ] ) , integer ( ) ] ) ) ) }
1610+
1611+ assert map_to_list ( union ( dynamic ( closed_map ( a: integer ( ) ) ) , closed_map ( b: atom ( ) ) ) ) ==
1612+ { :ok ,
1613+ union (
1614+ non_empty_list ( tuple ( [ atom ( [ :b ] ) , atom ( ) ] ) ) ,
1615+ dynamic (
1616+ non_empty_list (
1617+ union (
1618+ tuple ( [ atom ( [ :a ] ) , integer ( ) ] ) ,
1619+ tuple ( [ atom ( [ :b ] ) , atom ( ) ] )
1620+ )
1621+ )
1622+ )
1623+ ) }
1624+
1625+ # A static integer is refused
1626+ assert map_to_list ( union ( dynamic ( open_map ( ) ) , integer ( ) ) ) == :badmap
1627+
1628+ # Test with negations
1629+ assert map_to_list (
1630+ difference ( closed_map ( a: integer ( ) , b: atom ( ) ) , closed_map ( a: integer ( ) ) )
1631+ ) ==
1632+ { :ok ,
1633+ non_empty_list (
1634+ tuple ( [ atom ( [ :a ] ) , integer ( ) ] )
1635+ |> union ( tuple ( [ atom ( [ :b ] ) , atom ( ) ] ) )
1636+ ) }
1637+
1638+ # If a key is removed entirely by a negation, it should not appear in the result
1639+ assert closed_map ( a: if_set ( integer ( ) ) , b: atom ( ) )
1640+ |> difference ( closed_map ( a: integer ( ) , b: term ( ) ) )
1641+ |> map_to_list ( ) ==
1642+ { :ok , non_empty_list ( tuple ( [ atom ( [ :b ] ) , atom ( ) ] ) ) }
1643+ end
1644+
15121645 test "domain_to_args" do
15131646 # take complex tuples, normalize them, and check if they are still equal
15141647 complex_tuples = [
@@ -1803,6 +1936,11 @@ defmodule Module.Types.DescrTest do
18031936 { type , descr , [ ] } = map_update ( dynamic ( open_map ( ) ) , atom ( [ :key1 , :key2 ] ) , integer ( ) )
18041937 assert equal? ( type , dynamic ( ) )
18051938 assert descr == dynamic ( union ( open_map ( key1: integer ( ) ) , open_map ( key2: integer ( ) ) ) )
1939+
1940+ # A non-existing map
1941+ assert open_map ( )
1942+ |> difference ( open_map ( a: if_set ( term ( ) ) , c: if_set ( term ( ) ) ) )
1943+ |> map_update ( atom ( [ :b ] ) , integer ( ) ) == { :error , [ badkey: :b ] }
18061944 end
18071945
18081946 test "with dynamic atom keys" do
@@ -1889,6 +2027,11 @@ defmodule Module.Types.DescrTest do
18892027 assert map_update ( closed_map ( key1: binary ( ) , key2: pid ( ) ) , dynamic ( atom ( ) ) , integer ( ) ) ==
18902028 { union ( binary ( ) , pid ( ) ) ,
18912029 closed_map ( key1: union ( integer ( ) , binary ( ) ) , key2: union ( integer ( ) , pid ( ) ) ) , [ ] }
2030+
2031+ # A non-existing map
2032+ assert open_map ( )
2033+ |> difference ( open_map ( a: if_set ( term ( ) ) , c: if_set ( term ( ) ) ) )
2034+ |> map_update ( binary ( ) , integer ( ) ) == { :error , [ baddomain: binary ( ) ] }
18922035 end
18932036
18942037 test "with mixed keys" do
0 commit comments