1Code.require_file("../test_helper.exs", __DIR__) 2 3defmodule Kernel.ImportTest do 4 use ExUnit.Case, async: true 5 6 # This should not warn due to the empty only 7 import URI, only: [] 8 9 defmodule ImportAvailable do 10 defmacro flatten do 11 [flatten: 1] 12 end 13 end 14 15 test "multi-call" do 16 assert [List, String] = import(Elixir.{List, unquote(:String)}) 17 assert keymember?([a: 1], :a, 0) 18 assert valid?("ø") 19 end 20 21 test "blank multi-call" do 22 assert [] = import(List.{}) 23 # Buggy local duplicate is untouched 24 assert duplicate([1], 2) == [1] 25 end 26 27 test "multi-call with options" do 28 assert [List] = import(Elixir.{List}, only: []) 29 # Buggy local duplicate is untouched 30 assert duplicate([1], 2) == [1] 31 end 32 33 test "import all" do 34 assert :lists = import(:lists) 35 assert flatten([1, [2], 3]) == [1, 2, 3] 36 end 37 38 test "import except none" do 39 import :lists, except: [] 40 assert flatten([1, [2], 3]) == [1, 2, 3] 41 end 42 43 test "import except one" do 44 import :lists, except: [duplicate: 2] 45 assert flatten([1, [2], 3]) == [1, 2, 3] 46 # Buggy local duplicate is untouched 47 assert duplicate([1], 2) == [1] 48 end 49 50 test "import only via macro" do 51 require ImportAvailable 52 import :lists, only: ImportAvailable.flatten() 53 assert flatten([1, [2], 3]) == [1, 2, 3] 54 end 55 56 defmacrop dynamic_opts do 57 [only: [flatten: 1]] 58 end 59 60 test "import with options via macro" do 61 import :lists, dynamic_opts() 62 assert flatten([1, [2], 3]) == [1, 2, 3] 63 end 64 65 test "import with double except" do 66 import :lists, except: [duplicate: 2] 67 import :lists, except: [each: 2] 68 assert append([1], [2, 3]) == [1, 2, 3] 69 # Buggy local duplicate is untouched 70 assert duplicate([1], 2) == [1] 71 end 72 73 test "import except none respects previous import with except" do 74 import :lists, except: [duplicate: 2] 75 import :lists, except: [] 76 assert append([1], [2, 3]) == [1, 2, 3] 77 # Buggy local duplicate is untouched 78 assert duplicate([1], 2) == [1] 79 end 80 81 test "import except none respects previous import with only" do 82 import :lists, only: [append: 2] 83 import :lists, except: [] 84 assert append([1], [2, 3]) == [1, 2, 3] 85 # Buggy local duplicate is untouched 86 assert duplicate([1], 2) == [1] 87 end 88 89 defmodule Underscored do 90 def hello(x), do: x 91 def __underscore__(x), do: x 92 end 93 94 defmodule ExplicitUnderscored do 95 def __underscore__(x), do: x * 2 96 end 97 98 test "import only with underscore" do 99 import Underscored, only: [__underscore__: 1] 100 assert __underscore__(3) == 3 101 end 102 103 test "import non-underscored" do 104 import ExplicitUnderscored, only: [__underscore__: 1] 105 import Underscored 106 assert hello(2) == 2 107 assert __underscore__(3) == 6 108 end 109 110 defmodule MessedBitwise do 111 defmacro bnot(x), do: x 112 defmacro bor(x, _), do: x 113 end 114 115 import Bitwise, only: :functions 116 117 test "conflicting imports with only and except" do 118 import Bitwise, only: :functions, except: [bnot: 1] 119 import MessedBitwise, only: [bnot: 1] 120 assert bnot(0) == 0 121 assert bor(0, 1) == 1 122 end 123 124 # This test is asserting that the imports in the 125 # test above do not affect this test. 126 test "imports from other functions do not leak" do 127 assert band(1, 1) == 1 128 assert bor(0, 1) == 1 129 assert bnot(0) == -1 130 end 131 132 test "import ambiguous" do 133 # Simply make sure that we can indeed import functions with 134 # the same name and arity from different modules without the 135 # import itself causing any errors. 136 import List 137 import String 138 end 139 140 test "import many" do 141 [import(List), import(String)] 142 assert capitalize("foo") == "Foo" 143 assert flatten([1, [2], 3]) == [1, 2, 3] 144 end 145 146 defmodule ModuleWithSigils do 147 def sigil_i(string, []), do: String.to_integer(string) 148 149 defmacro sigil_I(string, []) do 150 quote do 151 String.to_integer(unquote(string)) 152 end 153 end 154 155 def sigil_w(_string, []), do: [] 156 157 def bnot(x), do: x 158 defmacro bor(x, _), do: x 159 end 160 161 test "import only sigils" do 162 import Kernel, except: [sigil_w: 2] 163 import ModuleWithSigils, only: :sigils 164 165 # Ensure that both function and macro sigils are imported 166 assert ~i'10' == 10 167 assert ~I'10' == 10 168 assert ~w(abc def) == [] 169 170 # Ensure that non-sigil functions and macros from ModuleWithSigils were not loaded 171 assert bnot(0) == -1 172 assert bor(0, 1) == 1 173 end 174 175 test "import only sigils with except" do 176 import ModuleWithSigils, only: :sigils, except: [sigil_w: 2] 177 178 assert ~i'10' == 10 179 assert ~I'10' == 10 180 assert ~w(abc def) == ["abc", "def"] 181 end 182 183 test "import only removes the non-import part" do 184 import List 185 import List, only: :macros 186 # Buggy local duplicate is used because we asked only for macros 187 assert duplicate([1], 2) == [1] 188 end 189 190 test "import lexical on if" do 191 if false do 192 import List 193 flatten([1, [2], 3]) 194 flunk() 195 else 196 # Buggy local duplicate is untouched 197 assert duplicate([1], 2) == [1] 198 end 199 end 200 201 test "import lexical on case" do 202 case true do 203 false -> 204 import List 205 flatten([1, [2], 3]) 206 flunk() 207 208 true -> 209 # Buggy local duplicate is untouched 210 assert duplicate([1], 2) == [1] 211 end 212 end 213 214 test "import lexical on for" do 215 for x <- [1, 2, 3], x > 10 do 216 import List 217 flatten([1, [2], 3]) 218 flunk() 219 end 220 221 # Buggy local duplicate is untouched 222 assert duplicate([1], 2) == [1] 223 end 224 225 test "import lexical on with" do 226 with true <- false do 227 import List 228 flatten([1, [2], 3]) 229 flunk() 230 end 231 232 # Buggy local duplicate is untouched 233 assert duplicate([1], 2) == [1] 234 end 235 236 test "import lexical on try" do 237 try do 238 import List 239 flatten([1, [2], 3]) 240 flunk() 241 catch 242 _, _ -> 243 # Buggy local duplicate is untouched 244 assert duplicate([1], 2) == [1] 245 end 246 247 # Buggy local duplicate is untouched 248 assert duplicate([1], 2) == [1] 249 end 250 251 defp duplicate(list, _), do: list 252end 253