File: test_syntax.rb

package info (click to toggle)
ruby-activeldap 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 1,588 kB
  • sloc: ruby: 18,143; sh: 12; makefile: 5
file content (449 lines) | stat: -rw-r--r-- 14,690 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
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
# -*- coding: utf-8 -*-

require 'al-test-utils'

class TestSyntax < Test::Unit::TestCase
  include AlTestUtils
  include ActiveLdap::Helper

  SYNTAXES = \
  [
   "( 1.3.6.1.1.16.1 DESC 'UUID' )",
   "( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
   "( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
   "( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
   "( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
   "( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' " +
     "X-BINARY-TRANSFER-REQUIRED 'TRUE' X-NOT-HUMAN-READABLE 'TRUE' )",
   "( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
   "( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
   "( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
   "( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
   "( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
   "( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
   "( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
   "( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
   "( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' X-NOT-HUMAN-READABLE 'TRUE' )",
   "( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
   "( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
   "( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
   "( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
   "( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
   "( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
   "( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
   "( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
   "( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
   "( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' " +
     "X-BINARY-TRANSFER-REQUIRED 'TRUE' X-NOT-HUMAN-READABLE 'TRUE' )",
   "( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' " +
     "X-BINARY-TRANSFER-REQUIRED 'TRUE' X-NOT-HUMAN-READABLE 'TRUE' )",
   "( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' " +
     "X-BINARY-TRANSFER-REQUIRED 'TRUE' X-NOT-HUMAN-READABLE 'TRUE' )",
   "( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
   "( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
   "( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' X-NOT-HUMAN-READABLE 'TRUE' )",
   "( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' X-NOT-HUMAN-READABLE 'TRUE' )"
  ]

  def setup
    @schema = ActiveLdap::Schema.new("ldapSyntaxes" => SYNTAXES.dup)
    @syntaxes = {}
    @schema.ldap_syntaxes.each do |syntax|
      @syntaxes[syntax.description] = syntax
    end
  end

  def teardown
  end

  priority :must
  def test_id_with_length
    id = "1.3.6.1.4.1.1466.115.121.1.26"

    syntax = ActiveLdap::Schema::Syntax.new(id, @schema)
    assert_equal([id, nil], [syntax.id, syntax.length])

    syntax = ActiveLdap::Schema::Syntax.new("#{id}{128}", @schema)
    assert_equal([id, 128], [syntax.id, syntax.length])
  end

  priority :normal
  def test_bit_string_type_cast
    assert_type_cast_without_validation(nil, nil, 'Bit String')
    assert_type_cast("0101111101", "'0101111101'B", 'Bit String')
  end

  def test_boolean_type_cast
    assert_type_cast_without_validation(nil, nil, 'Boolean')
    assert_type_cast(true, "TRUE", "Boolean")
    assert_type_cast(false, "FALSE", "Boolean")
  end

  def test_boolean_normalize_value
    assert_normalize_value("TRUE", true, 'Boolean')
    assert_normalize_value("TRUE", "1", 'Boolean')
    assert_normalize_value("FALSE", false, 'Boolean')
    assert_normalize_value("FALSE", "0", 'Boolean')
  end

  def test_dn_type_cast
    assert_type_cast_without_validation(nil, nil, 'Distinguished Name')
    assert_dn_type_cast("cn=test", 'Distinguished Name')
  end

  class TestGeneralizedTime < self
    private
    def syntax_name
      "Generalized Time"
    end

    class TestTypeCast < self
      def test_nil
        assert_type_cast_without_validation(nil, nil, syntax_name)
      end

      def test_timezone_none
        assert_type_cast(Time.parse("1994/12/16 10:32:12"),
                         "19941216103212")
      end

      def test_timezone_Z
        assert_type_cast(Time.parse("1994/12/16 10:32:12Z"),
                         "19941216103212Z")
      end

      def test_timezone_difference
        assert_type_cast(Time.parse("1994/12/16 10:32:12.345 +09:00"),
                         "19941216103212.345+0900")
      end

      def test_timezone_difference_with_minutes
        assert_type_cast(Time.parse("2019-02-13 15:54:23 +0530"),
                         "20190213155423+0530")
      end

      def test_year_month_day_hour_minute
        assert_type_cast(Time.parse("2008/01/07 03:46:00"),
                         "200801070346")
      end

      def test_before_posix_time
        time_can_handle_before_posix_time = false
        begin
          Time.utc(1601)
          time_can_handle_before_posix_time = true
        rescue ArgumentError
        end

        if time_can_handle_before_posix_time
          assert_type_cast(Time.utc(1601, 1, 1, 0, 4, 17),
                           "16010101000417.0Z")
        else
          assert_type_cast(Time.at(0),
                           "16010101000417.0Z")
        end
      end

      private
      def assert_type_cast(type_casted_value, original_value)
        super(type_casted_value, original_value, syntax_name)
      end
    end

    class TestValidate < self
      class TestValid < self
        def test_no_timezone
          assert_valid("19941216103201")
        end

        def test_timezone_Z
          assert_valid("19941216103212Z")
        end

        def test_timezone_difference
          assert_valid("19941216103230+0900")
        end

        def test_fraction_separator_period
          assert_valid("20080107034615.0Z")
        end

        def test_fraction_separator_comma
          assert_valid("20080107034615,123-0900")
        end

        def test_year_month_day_hour_minute
          assert_valid("199412161032")
        end

        private
        def assert_valid(value)
          super(value, syntax_name)
        end
      end

      class TestInvalid < self
        def test_year_only
          value = "1994"
          params = [value.inspect, %w(month day hour minute).join(", ")]
          assert_invalid(_("%s has missing components: %s") % params,
                         value)
        end

        def test_year_month_day_hour_only
          value = "1994121610"
          params = [value.inspect, %w(minute).join(", ")]
          assert_invalid(_("%s has missing components: %s") % params,
                         value)
        end

        private
        def assert_invalid(reason, value)
          super(reason, value, syntax_name)
        end
      end
    end
  end

  def test_integer_type_cast
    assert_type_cast_without_validation(nil, nil, "Integer")
    assert_type_cast(1321, "1321", "Integer")
  end

  def test_bit_string_validate
    assert_valid("'0101111101'B", 'Bit String')
    assert_valid("''B", 'Bit String')

    value = "0101111101'B"
    assert_invalid(_("%s doesn't have the first \"'\"") % value.inspect,
                   value, 'Bit String')

    value = "'0101111101'"
    assert_invalid(_("%s doesn't have the last \"'B\"") % value.inspect,
                   value, 'Bit String')

    value = "'0101111101B"
    assert_invalid(_("%s doesn't have the last \"'B\"") % value.inspect,
                   value, 'Bit String')

    value = "'0A'B"
    assert_invalid(_("%s has invalid character '%s'") % [value.inspect, "A"],
                   value, 'Bit String')
  end

  def test_boolean_validate
    assert_valid("TRUE", "Boolean")
    assert_valid("FALSE", "Boolean")

    value = "true"
    assert_invalid(_("%s should be TRUE or FALSE") % value.inspect,
                   value, "Boolean")
  end

  def test_country_string_validate
    assert_valid("ja", "Country String")
    assert_valid("JA", "Country String")

    value = "japan"
    assert_invalid(_("%s should be just 2 printable characters") % value.inspect,
                   value, "Country String")
  end

  def test_dn_validate
    assert_valid("cn=test", 'Distinguished Name')
    assert_valid("CN=Steve Kille,O=Isode Limited,C=GB", 'Distinguished Name')
    assert_valid("OU=Sales+CN=J. Smith,O=Widget Inc.,C=US", 'Distinguished Name')
    assert_valid("CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB",
                 'Distinguished Name')
    assert_valid("CN=Before\\0DAfter,O=Test,C=GB", 'Distinguished Name')
    assert_valid("1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB",
                 'Distinguished Name')
    assert_valid("SN=Lu\\C4\\8Di\\C4\\87", 'Distinguished Name')

    value = "test"
    params = [value, _("attribute value is missing")]
    assert_invalid(_('%s is invalid distinguished name (DN): %s') % params,
                   value, 'Distinguished Name')
  end

  def test_directory_string_validate
    assert_valid("This is a string of DirectoryString containing \#!%\#@",
                 "Directory String")
    assert_valid("これはDirectoryString文字列です。",
                 "Directory String")

    value = "これはDirectoryString文字列です。"
    if value.respond_to?(:encode)
      value = value.encode("euc-jp")
    else
      value = NKF.nkf("-We", value)
    end
    assert_invalid(_("%s has invalid UTF-8 character") % value.inspect,
                   value, "Directory String")
  end

  def test_integer_validate
    assert_valid("1321", "Integer")

    assert_invalid_integer("13.5")
    assert_invalid_integer("string")
  end

  def test_jpeg_validate
    assert_valid([0xffd8].pack("n"), "JPEG")

    assert_invalid(_("invalid JPEG format"), "", "JPEG")
    assert_invalid(_("invalid JPEG format"), "jpeg", "JPEG")
  end

  def test_name_and_optional_uid_validate
    assert_valid("1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B",
                 "Name And Optional UID")
    assert_valid("cn=test", "Name And Optional UID")

    value = "test"
    params = [value, _("attribute value is missing")]
    assert_invalid(_('%s is invalid distinguished name (DN): %s') % params,
                   value, "Name And Optional UID")

    bit_string = "'00x'B"
    params = [bit_string.inspect, "x"]
    assert_invalid(_("%s has invalid character '%s'") % params,
                   "cn=test\##{bit_string}", "Name And Optional UID")
  end

  def test_numeric_string_validate
    assert_valid("1997", "Numeric String")

    assert_invalid_numeric_string("-3")
    assert_invalid_numeric_string("-3.5")
    assert_invalid_numeric_string("string")
  end

  def test_oid_validate
    assert_valid("1.2.3.4", "OID")
    assert_valid("cn", "OID")

    assert_invalid_oid("\#@!", "attribute type is missing")
  end

  def test_other_mailbox_validate
    assert_valid("smtp$bob@example.com", "Other Mailbox")


    value = "smtp"
    assert_invalid(_("%s has no mailbox") % value.inspect,
                   value, "Other Mailbox")

    value = "smtp$"
    assert_invalid(_("%s has no mailbox") % value.inspect,
                   value, "Other Mailbox")

    value = "$bob@example.com"
    assert_invalid(_("%s has no mailbox type") % value.inspect,
                   value, "Other Mailbox")

    value = "!$bob@example.com"
    params = [value.inspect, "!"]
    reason = _("%s has unprintable character in mailbox type: '%s'") % params
    assert_invalid(reason, value, "Other Mailbox")
  end

  def test_postal_address_validate
    assert_valid("1234 Main St.$Anytown, CA 12345$USA", "Postal Address")
    assert_valid("\\241,000,000 Sweepstakes$PO Box 1000000$Anytown, " +
                 "CA 12345$USA", "Postal Address")
    assert_valid("$", "Postal Address")
    assert_valid("1234 Main St.$", "Postal Address")


    assert_invalid(_("empty string"), "", "Postal Address")

    value = "東京"
    if value.respond_to?(:encode)
      value = value.encode("euc-jp")
    else
      value = NKF.nkf("-We", value)
    end
    assert_invalid(_("%s has invalid UTF-8 character") % value.inspect,
                   value, "Postal Address")
  end

  def test_printable_string_validate
    assert_valid("This is a PrintableString", "Printable String")

    assert_invalid(_("empty string"), "", "Printable String")


    value = "abc!def"
    params = [value.inspect, "!"]
    reason = _("%s has unprintable character: '%s'") % params
    assert_invalid(reason, value, "Printable String")

    value = "abcあdef"
    params = [value.inspect, "あ"]
    reason = _("%s has unprintable character: '%s'") % params
    assert_invalid(reason, value, "Printable String")
  end

  def test_telephone_number_validate
    assert_valid("+1 512 305 0280", "Telephone Number")
    assert_valid("", "Telephone Number")

    value = "+1 5!2 305 0280"
    params = [value.inspect, "!"]
    reason = _("%s has unprintable character: '%s'") % params
    assert_invalid(reason, value, "Telephone Number")
  end

  private
  def assert_valid(value, syntax_name)
    assert_nil(@syntaxes[syntax_name].validate(value))
  end

  def assert_invalid(reason, value, syntax_name)
    assert_equal(reason, @syntaxes[syntax_name].validate(value))
  end

  def assert_invalid_integer(value)
    assert_invalid(_("%s is invalid integer format") % value.inspect,
                   value, "Integer")
  end

  def assert_invalid_numeric_string(value)
    assert_invalid(_("%s is invalid numeric format") % value.inspect,
                   value, "Numeric String")
  end

  def assert_invalid_oid(value, reason=nil)
    if reason
      message = _("%s is invalid OID format: %s") % [value.inspect, _(reason)]
    else
      message = _("%s is invalid OID format") % value.inspect
    end
    assert_invalid(message, value, "OID")
  end

  def assert_type_cast_without_validation(type_casted_value, original_value,
                                          syntax_name)
    syntax = @syntaxes[syntax_name]
    assert_equal(type_casted_value, syntax.type_cast(original_value))
    assert_equal(type_casted_value, syntax.type_cast(type_casted_value))
  end

  def assert_type_cast(type_casted_value, original_value, syntax_name)
    assert_type_cast_without_validation(type_casted_value, original_value,
                                        syntax_name)
    assert_valid(type_casted_value, syntax_name)
  end

  def assert_dn_type_cast(original_value, syntax_name)
    assert_type_cast(ActiveLdap::DN.parse(original_value), original_value,
                     syntax_name)
  end

  def assert_normalize_value(normalized_value, original_value, syntax_name)
    syntax = @syntaxes[syntax_name]
    assert_equal(normalized_value, syntax.normalize_value(original_value))
  end
end