summaryrefslogtreecommitdiff
path: root/spec/ruby/core/module/const_defined_spec.rb
blob: 0789a03e1c392c0991c90f2bf386fbc5f097d24b (plain)
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
# encoding: utf-8

require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../../fixtures/constants', __FILE__)
require File.expand_path('../fixtures/constant_unicode', __FILE__)

describe "Module#const_defined?" do
  it "returns true if the given Symbol names a constant defined in the receiver" do
    ConstantSpecs.const_defined?(:CS_CONST2).should == true
    ConstantSpecs.const_defined?(:ModuleA).should == true
    ConstantSpecs.const_defined?(:ClassA).should == true
    ConstantSpecs::ContainerA.const_defined?(:ChildA).should == true
  end

  it "returns true if the constant is defined in the receiver's superclass" do
    # CS_CONST4 is defined in the superclass of ChildA
    ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4).should be_true
  end

  it "returns true if the constant is defined in a mixed-in module of the receiver" do
    # CS_CONST10 is defined in a module included by ChildA
    ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST10).should be_true
  end

  it "returns true if the constant is defined in Object and the receiver is a module" do
    # CS_CONST1 is defined in Object
    ConstantSpecs::ModuleA.const_defined?(:CS_CONST1).should be_true
  end

  it "returns true if the constant is defined in Object and the receiver is a class that has Object among its ancestors" do
    # CS_CONST1 is defined in Object
    ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST1).should be_true
  end

  it "returns false if the constant is defined in the receiver's superclass and the inherit flag is false" do
    ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, false).should be_false
  end

  it "returns true if the constant is defined in the receiver's superclass and the inherit flag is true" do
    ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, true).should be_true
  end

  it "returns true if the given String names a constant defined in the receiver" do
    ConstantSpecs.const_defined?("CS_CONST2").should == true
    ConstantSpecs.const_defined?("ModuleA").should == true
    ConstantSpecs.const_defined?("ClassA").should == true
    ConstantSpecs::ContainerA.const_defined?("ChildA").should == true
  end

  it "returns true when passed a constant name with unicode characters" do
    ConstantUnicodeSpecs.const_defined?("CS_CONSTλ").should be_true
  end

  it "returns true when passed a constant name with EUC-JP characters" do
    str = "CS_CONSTλ".encode("euc-jp")
    ConstantSpecs.const_set str, 1
    ConstantSpecs.const_defined?(str).should be_true
  end

  it "returns false if the constant is not defined in the receiver, its superclass, or any included modules" do
    # The following constant isn't defined at all.
    ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4726).should be_false
    # DETACHED_CONSTANT is defined in ConstantSpecs::Detached, which isn't
    # included by or inherited from ParentA
    ConstantSpecs::ParentA.const_defined?(:DETACHED_CONSTANT).should be_false
  end

  it "does not call #const_missing if the constant is not defined in the receiver" do
    ConstantSpecs::ClassA.should_not_receive(:const_missing)
    ConstantSpecs::ClassA.const_defined?(:CS_CONSTX).should == false
  end

  it "calls #to_str to convert the given name to a String" do
    name = mock("ClassA")
    name.should_receive(:to_str).and_return("ClassA")
    ConstantSpecs.const_defined?(name).should == true
  end

  it "special cases Object and checks it's included Modules" do
    Object.const_defined?(:CS_CONST10).should be_true
  end

  it "returns true for toplevel constant when the name begins with '::'" do
    ConstantSpecs.const_defined?("::Array").should be_true
  end

  it "returns true when passed a scoped constant name" do
    ConstantSpecs.const_defined?("ClassC::CS_CONST1").should be_true
  end

  it "returns true when passed a scoped constant name for a constant in the inheritance hierarchy and the inherited flag is default" do
    ConstantSpecs::ClassD.const_defined?("ClassE::CS_CONST2").should be_true
  end

  it "returns true when passed a scoped constant name for a constant in the inheritance hierarchy and the inherited flag is true" do
    ConstantSpecs::ClassD.const_defined?("ClassE::CS_CONST2", true).should be_true
  end

  it "returns false when passed a scoped constant name for a constant in the inheritance hierarchy and the inherited flag is false" do
    ConstantSpecs::ClassD.const_defined?("ClassE::CS_CONST2", false).should be_false
  end

  it "returns false when the name begins with '::' and the toplevel constant does not exist" do
    ConstantSpecs.const_defined?("::Name").should be_false
  end

  it "raises a NameError if the name does not start with a capital letter" do
    lambda { ConstantSpecs.const_defined? "name" }.should raise_error(NameError)
  end

  it "raises a NameError if the name starts with '_'" do
    lambda { ConstantSpecs.const_defined? "__CONSTX__" }.should raise_error(NameError)
  end

  it "raises a NameError if the name starts with '@'" do
    lambda { ConstantSpecs.const_defined? "@Name" }.should raise_error(NameError)
  end

  it "raises a NameError if the name starts with '!'" do
    lambda { ConstantSpecs.const_defined? "!Name" }.should raise_error(NameError)
  end

  it "returns true or false for the nested name" do
    ConstantSpecs.const_defined?("NotExist::Name").should == false
    ConstantSpecs.const_defined?("::Name").should == false
    ConstantSpecs.const_defined?("::Object").should == true
    ConstantSpecs.const_defined?("ClassA::CS_CONST10").should == true
    ConstantSpecs.const_defined?("ClassA::CS_CONST10_").should == false
  end

  it "raises a NameError if the name contains non-alphabetic characters except '_'" do
    ConstantSpecs.const_defined?("CS_CONSTX").should == false
    lambda { ConstantSpecs.const_defined? "Name=" }.should raise_error(NameError)
    lambda { ConstantSpecs.const_defined? "Name?" }.should raise_error(NameError)
  end

  it "raises a TypeError if conversion to a String by calling #to_str fails" do
    name = mock('123')
    lambda { ConstantSpecs.const_defined? name }.should raise_error(TypeError)

    name.should_receive(:to_str).and_return(123)
    lambda { ConstantSpecs.const_defined? name }.should raise_error(TypeError)
  end
end