File: info_test.exs

package info (click to toggle)
elixir-lang 1.18.3.dfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 14,436 kB
  • sloc: erlang: 11,996; sh: 324; makefile: 277
file content (260 lines) | stat: -rw-r--r-- 8,414 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
Code.require_file("../test_helper.exs", __DIR__)

defmodule IEx.InfoTest do
  use ExUnit.Case

  import ExUnit.CaptureLog

  alias IEx.Info

  defmodule Foo do
    defstruct [:foo]
  end

  test "tuples" do
    assert Info.info({:ok, "good!"}) == [{"Data type", "Tuple"}, {"Reference modules", "Tuple"}]
  end

  describe "atoms" do
    test "loaded module (without docs)" do
      info = Info.info(Foo)
      assert get_key(info, "Data type") == "Atom"

      assert get_key(info, "Description") ==
               "Call IEx.InfoTest.Foo.module_info() to access metadata."

      assert get_key(info, "Raw representation") == ~s(:"Elixir.IEx.InfoTest.Foo")
    end

    @tag :requires_source
    test "loaded module (with source)" do
      info = Info.info(Foo)
      assert get_key(info, "Source") == Path.relative_to_cwd(__ENV__.file)
    end

    test "loaded module (with docs)" do
      info = Info.info(List)

      description = """
      Use h(List) to access its documentation.
      Call List.module_info() to access metadata.\
      """

      assert get_key(info, "Description") == description
    end

    test "module that is also a protocol" do
      info = Info.info(String.Chars)
      protocol_info = get_key(info, "Protocol")
      assert protocol_info =~ "This module is a protocol"
      assert protocol_info =~ "Atom"
      assert protocol_info =~ "BitString"
    end

    test "module-like atom (Foo)" do
      info = Info.info(NonexistentModuleAtom)
      assert get_key(info, "Raw representation") == ~s(:"Elixir.NonexistentModuleAtom")
    end

    test "regular atom" do
      assert Info.info(:foo) == [{"Data type", "Atom"}, {"Reference modules", "Atom"}]
    end

    test "do not log errors if module exists with different casing" do
      assert capture_log(fn -> Info.info(Datetime) end) == ""
    end
  end

  describe "lists" do
    test "charlists" do
      info = Info.info(~c"foo")
      assert get_key(info, "Description") =~ "This is a list of integers that is printed"
      assert get_key(info, "Raw representation") == "[102, 111, 111]"
    end

    test "keyword lists" do
      info = Info.info(a: 1, b: 2)
      assert get_key(info, "Description") =~ "This is what is referred to as a \"keyword list\""
    end

    test "regular lists" do
      assert get_key(Info.info([]), "Reference modules") == "List"
      assert get_key(Info.info([:foo, :bar, :baz]), "Reference modules") == "List"
    end
  end

  describe "bitstring" do
    test "strings" do
      info = Info.info("føø")
      assert get_key(info, "Byte size") == 5
      assert get_key(info, "Description") =~ "This is a string: a UTF-8 encoded binary"
      assert get_key(info, "Raw representation") == "<<102, 195, 184, 195, 184>>"
    end

    test "non-printable string" do
      info = Info.info(<<"foo", 0, "bar">>)
      description = get_key(info, "Description")

      assert get_key(info, "Byte size") == 7
      assert description =~ "This is a string"
      assert description =~ "It's printed with the `<<>>`"
      assert description =~ "the first non-printable code point being\n`<<0>>`"
    end

    test "binary" do
      info = Info.info(<<255, 255>>)
      assert get_key(info, "Description") =~ "This is a binary: a collection of bytes"
    end

    test "bitstring" do
      info = Info.info(<<1::1>>)
      assert get_key(info, "Bits size") == 1
      assert get_key(info, "Description") =~ "This is a bitstring"
    end
  end

  test "integers" do
    assert Info.info(99) == [{"Data type", "Integer"}, {"Reference modules", "Integer"}]
  end

  test "float" do
    assert Info.info(3.14) == [{"Data type", "Float"}, {"Reference modules", "Float"}]
  end

  describe "functions" do
    test "named function" do
      info = Info.info(&String.length/1)
      assert get_key(info, "Type") == "external"
      assert get_key(info, "Arity") == 1
    end

    test "anonymous function" do
      info = Info.info(fn -> :ok end)
      assert get_key(info, "Type") == "local"
      assert get_key(info, "Arity") == 0
      assert get_key(info, "Description") == "This is an anonymous function."
    end
  end

  test "PIDs" do
    pid = spawn_link(fn -> Process.sleep(1000) end)

    info = Info.info(pid)
    assert get_key(info, "Alive") == true
    assert get_key(info, "Name") == "not registered"
    assert get_key(info, "Links") == inspect(self())
    assert get_key(info, "Message queue length") == 0

    Process.register(pid, :iex_info_registered_pid)
    Process.unlink(pid)
    send(pid, :oops)
    info = Info.info(pid)
    assert get_key(info, "Name") == ":iex_info_registered_pid"
    assert get_key(info, "Links") == "none"
    assert get_key(info, "Message queue length") == 1

    Process.exit(pid, :kill)
    assert get_key(Info.info(pid), "Alive") == false
  end

  test "ports" do
    {:ok, port} = :gen_udp.open(0)
    assert get_key(Info.info(port), "Open") == true
    :ok = :gen_udp.close(port)
    assert get_key(Info.info(port), "Open") == false
  end

  test "references" do
    assert Info.info(make_ref()) == [{"Data type", "Reference"}]
  end

  describe "calendar types" do
    test "date" do
      {:ok, date} = Date.new(2017, 1, 1)
      info = Info.info(date)
      assert get_key(info, "Data type") == "Date"

      assert get_key(info, "Raw representation") ==
               "%Date{year: 2017, month: 1, day: 1, calendar: Calendar.ISO}"

      assert get_key(info, "Reference modules") == "Date, Calendar, Map"
      assert get_key(info, "Description") =~ "a date"
      assert get_key(info, "Description") =~ "`~D`"
    end

    test "time" do
      {:ok, time} = Time.new(23, 59, 59)
      info = Info.info(time)
      assert get_key(info, "Data type") == "Time"

      assert get_key(info, "Raw representation") ==
               "%Time{hour: 23, minute: 59, second: 59, microsecond: {0, 0}, calendar: Calendar.ISO}"

      assert get_key(info, "Reference modules") == "Time, Calendar, Map"
      assert get_key(info, "Description") =~ "a time"
      assert get_key(info, "Description") =~ "`~T`"
    end

    test "datetime" do
      {:ok, date} = Date.new(2017, 1, 1)
      {:ok, time} = Time.new(23, 59, 59)
      {:ok, date_time} = DateTime.new(date, time)
      info = Info.info(date_time)
      assert get_key(info, "Data type") == "DateTime"

      assert get_key(info, "Raw representation") ==
               "%DateTime{year: 2017, month: 1, day: 1, hour: 23, minute: 59, second: 59, time_zone: \"Etc/UTC\", zone_abbr: \"UTC\", utc_offset: 0, std_offset: 0, microsecond: {0, 0}, calendar: Calendar.ISO}"

      assert get_key(info, "Reference modules") == "DateTime, Calendar, Map"
      assert get_key(info, "Description") =~ "a datetime"
      assert get_key(info, "Description") =~ "`~U`"
    end

    test "naive datetime" do
      {:ok, time} = NaiveDateTime.new(2017, 1, 1, 23, 59, 59)
      info = Info.info(time)
      assert get_key(info, "Data type") == "NaiveDateTime"

      assert get_key(info, "Raw representation") ==
               "%NaiveDateTime{year: 2017, month: 1, day: 1, hour: 23, minute: 59, second: 59, microsecond: {0, 0}, calendar: Calendar.ISO}"

      assert get_key(info, "Reference modules") == "NaiveDateTime, Calendar, Map"

      assert get_key(info, "Description") =~
               ~S{a "naive" datetime (that is, a datetime without a time zone)}

      assert get_key(info, "Description") =~ "`~N`"
    end
  end

  test "Regex" do
    info = Info.info(~r/(ab)+c/)
    assert get_key(info, "Data type") == "Regex"
    assert get_key(info, "Description")
    assert get_key(info, "Raw representation") =~ "%Regex{re_pattern: {:re_pattern, "
    assert get_key(info, "Reference modules") == "Regex, :re"
  end

  test "Range" do
    info = Info.info(1..10//2)
    assert get_key(info, "Data type") == "Range"
    assert get_key(info, "Description")
    assert get_key(info, "Raw representation") == "%Range{first: 1, last: 10, step: 2}"
    assert get_key(info, "Reference modules") == "Range"
  end

  test "structs" do
    info = Info.info(%Foo{})
    assert get_key(info, "Data type") == "IEx.InfoTest.Foo"

    assert get_key(info, "Description") ==
             "This is a struct. Structs are maps with a __struct__ key."

    assert get_key(info, "Reference modules") == "IEx.InfoTest.Foo, Map"
  end

  defp get_key(info, key) do
    {^key, value} = List.keyfind(info, key, 0)
    value
  end
end