File: check.rb

package info (click to toggle)
ruby-ae 1.8.2-1
  • links: PTS, VCS
  • area: main
  • in suites: buster, jessie, jessie-kfreebsd, stretch
  • size: 208 kB
  • ctags: 172
  • sloc: ruby: 936; makefile: 2
file content (151 lines) | stat: -rw-r--r-- 3,150 bytes parent folder | download | duplicates (2)
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
module AE

  # The Ok mixin is a reusable assertion helper that
  # makes it easy to construct parameterized assertions
  # with an elegant syntax.
  #
  module Check

    # The Check::Proc class encapsulates a labeled procedure 
    # for making assertions using the `ok`/`no` methods.
    #
    class Proc
      # Setup new check procedure.
      def initialize(options={}, &check)
        @name    = options[:name]
        @message = options[:message] || @name
        @check   = check
      end

      #
      def message(&block)
        if block
          @message = message
        end
        @message
      end
    
      #
      def message=(msg)
        @message = msg
      end

      # Call check procedure.
      def call(*args)
        @check.call(*args)
      end

      #
      def to_s(*args)
        case @message
        when nil
          @name.to_s
        when ::Proc
          @message.call(*args)
        else
          # TODO: count %\S and apply `% args.map{|a|a.inspect}[0,count]`
          @message.to_s
        end
      end

      #
      def ok!(*args)
        assert(call(*args), to_s(*args))
      end

      #
      def no!(*args)
        refute(call(*args), to_s(*args))
      end
    end

    # TODO: Better way to customize error message so it can have
    # arguments in the messages ?

    # Built-in check procedures.
    TABLE = {
      :equality       => Check::Proc.new(:message=>"should be equal"){|h| h.any?{|a,b| b==a}},
      :case_equality  => Check::Proc.new(:message=>"should be equal"){|h| h.any?{|a,b| b===a}}
    }

    #
    def self.table
      @table ||= TABLE.dup
    end

    # Define a univerally available ok/no check.
    #
    #   AE::Check.define(:palindrome) do |x|
    #     x.reverse == x
    #   end
    #
    def self.define(name, &block)
      table[name] = Check::Proc.new(name, &block)
    end

    #
    def check_table
      Check.table
    end

    # Define an ok/no check procedure. A one-off procedure is defined
    # with a block.
    #
    #   check do |x, y|
    #     x == y
    #   end
    #
    #   ok 1,1
    #   no 1,2
    #
    # The check method can also be used to define reusable checks.
    #
    #   check(:palindrome) do |x|
    #     x.reverse == x
    #   end
    #
    # This will also cause the current check to be set.
    # Later in the code, the check procedure can be restored
    # by just passing the symbolic name.
    #
    #   check :palindrome
    #
    #   ok 'abracarba'
    #   no 'foolishness'
    #
    def check(name=nil, &block)
      if name
        if block
          check_table[name] = Check::Proc.new(:name=>name, &block)
        end
        @__check__ = check_table[name]
      else
        #raise ArgumentError if block.arity == 0
        @__check__ = Check::Proc.new(&block)
      end
    end

    #
    def ok(*args)
      __check__.ok!(*args)
    end

    #
    def no(*args)
      __check__.no!(*args)
    end

    # Returns the current check.
    def __check__
      @__check__ || check_table[:equality]
    end

  end

end

module AE::World
  # It's upto the test framework to include where needed.
  include AE::Check
end