1+ # frozen_string_literal: true
2+ require 'test/unit'
3+ require 'cgi'
4+ require 'stringio'
5+ require_relative 'update_env'
6+
7+ # Test suite for CGI.new method functionality and documentation validation.
8+ # Ensures the enhanced documentation matches actual implementation behavior.
9+ class CGINewTest < Test ::Unit ::TestCase
10+ include UpdateEnv
11+
12+ def setup
13+ @environ = { }
14+ @original_stdin = $stdin
15+ end
16+
17+ def teardown
18+ ENV . update ( @environ )
19+ $stdin = @original_stdin
20+ end
21+
22+ # Test basic CGI object creation with all documented call sequences
23+ def test_basic_object_creation
24+ update_env (
25+ 'REQUEST_METHOD' => 'GET' ,
26+ 'QUERY_STRING' => '' ,
27+ 'SERVER_SOFTWARE' => 'Apache 2.2.0' ,
28+ 'SERVER_PROTOCOL' => 'HTTP/1.1' ,
29+ )
30+
31+ # CGI.new(options = {}) -> new_cgi
32+ cgi1 = CGI . new ( { } )
33+ assert_instance_of ( CGI , cgi1 )
34+
35+ # CGI.new(tag_maker) -> new_cgi
36+ cgi2 = CGI . new ( 'html5' )
37+ assert_instance_of ( CGI , cgi2 )
38+
39+ # With blocks - should not raise errors
40+ assert_nothing_raised { CGI . new ( { } ) { |name , value | } }
41+ assert_nothing_raised { CGI . new ( 'html5' ) { |name , value | } }
42+ end
43+
44+ # Test tag_maker functionality for all documented HTML versions
45+ def test_tag_maker_functionality
46+ update_env (
47+ 'REQUEST_METHOD' => 'GET' ,
48+ 'QUERY_STRING' => '' ,
49+ 'SERVER_SOFTWARE' => 'Apache 2.2.0' ,
50+ 'SERVER_PROTOCOL' => 'HTTP/1.1' ,
51+ )
52+
53+ html_versions = {
54+ 'html3' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">' ,
55+ 'html4' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' ,
56+ 'html4Tr' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">' ,
57+ 'html4Fr' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">' ,
58+ 'html5' => '<!DOCTYPE HTML>'
59+ }
60+
61+ html_versions . each do |version , expected_doctype |
62+ cgi = CGI . new ( tag_maker : version )
63+ assert_respond_to ( cgi , :doctype , "HTML generation methods should be loaded for #{ version } " )
64+ assert_equal ( expected_doctype , cgi . doctype )
65+ end
66+
67+ # Test that without tag_maker, HTML methods are not loaded
68+ cgi = CGI . new
69+ assert_raise ( NoMethodError ) { cgi . doctype }
70+ end
71+
72+ # Test string tag_maker argument equivalence to hash option
73+ def test_string_tag_maker_equivalent
74+ update_env (
75+ 'REQUEST_METHOD' => 'GET' ,
76+ 'QUERY_STRING' => '' ,
77+ 'SERVER_SOFTWARE' => 'Apache 2.2.0' ,
78+ 'SERVER_PROTOCOL' => 'HTTP/1.1' ,
79+ )
80+
81+ cgi1 = CGI . new ( 'html5' )
82+ cgi2 = CGI . new ( tag_maker : 'html5' )
83+
84+ # Both should have HTML generation methods loaded
85+ assert_respond_to ( cgi1 , :doctype )
86+ assert_respond_to ( cgi2 , :doctype )
87+
88+ # Both should produce the same doctype
89+ assert_equal ( cgi1 . doctype , cgi2 . doctype )
90+ assert_equal ( '<!DOCTYPE HTML>' , cgi1 . doctype )
91+ end
92+
93+ # Test offline mode (when REQUEST_METHOD is not defined)
94+ def test_offline_mode
95+ ENV . delete ( 'REQUEST_METHOD' )
96+ ENV . delete ( 'QUERY_STRING' )
97+ ENV . delete ( 'SERVER_SOFTWARE' )
98+ ENV . delete ( 'SERVER_PROTOCOL' )
99+
100+ # Create test input
101+ test_input = "name=value&test=123"
102+ $stdin = StringIO . new ( test_input )
103+
104+ cgi = CGI . new
105+
106+ # In offline mode, it should read from stdin
107+ assert_equal ( "value" , cgi [ 'name' ] )
108+ assert_equal ( "123" , cgi [ 'test' ] )
109+ end
110+
111+ # Test that all documented options are accepted without errors
112+ def test_options_acceptance
113+ update_env (
114+ 'REQUEST_METHOD' => 'GET' ,
115+ 'QUERY_STRING' => '' ,
116+ 'SERVER_SOFTWARE' => 'Apache 2.2.0' ,
117+ 'SERVER_PROTOCOL' => 'HTTP/1.1' ,
118+ )
119+
120+ # Test accept_charset option
121+ assert_nothing_raised { CGI . new ( accept_charset : 'EUC-JP' ) }
122+ assert_nothing_raised { CGI . new ( accept_charset : Encoding ::UTF_8 ) }
123+
124+ # Test max_multipart_length options
125+ assert_nothing_raised { CGI . new ( max_multipart_length : 1024 * 1024 ) }
126+ assert_nothing_raised { CGI . new ( max_multipart_length : -> { 2 * 1024 * 1024 } ) }
127+
128+ # Test combined options
129+ assert_nothing_raised do
130+ CGI . new (
131+ accept_charset : 'ISO-8859-1' ,
132+ max_multipart_length : 64 * 1024 * 1024 ,
133+ tag_maker : 'html5'
134+ )
135+ end
136+ end
137+
138+ # Test basic object structure and public methods
139+ def test_object_structure
140+ update_env (
141+ 'REQUEST_METHOD' => 'GET' ,
142+ 'QUERY_STRING' => 'foo=bar' ,
143+ 'SERVER_SOFTWARE' => 'Apache 2.2.0' ,
144+ 'SERVER_PROTOCOL' => 'HTTP/1.1' ,
145+ )
146+
147+ cgi = CGI . new
148+
149+ # Test documented instance variables and methods exist
150+ assert_kind_of ( Hash , cgi . cookies )
151+ assert_kind_of ( Hash , cgi . params )
152+ assert_equal ( false , cgi . multipart? )
153+ assert_equal ( "bar" , cgi [ 'foo' ] ) # Verify param parsing works
154+ end
155+
156+ # Test accept_charset method behavior (HTTP header vs configuration)
157+ def test_accept_charset_method_behavior
158+ update_env (
159+ 'REQUEST_METHOD' => 'GET' ,
160+ 'QUERY_STRING' => '' ,
161+ 'SERVER_SOFTWARE' => 'Apache 2.2.0' ,
162+ 'SERVER_PROTOCOL' => 'HTTP/1.1' ,
163+ )
164+
165+ # Test without HTTP_ACCEPT_CHARSET header - method should return nil
166+ cgi1 = CGI . new ( accept_charset : 'EUC-JP' )
167+ assert_nil ( cgi1 . accept_charset , "accept_charset method should return HTTP header, not config" )
168+ assert_equal ( 'EUC-JP' , cgi1 . instance_variable_get ( :@accept_charset ) )
169+
170+ # Test with HTTP_ACCEPT_CHARSET header - method should return header value
171+ update_env ( 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1' )
172+ cgi2 = CGI . new ( accept_charset : 'UTF-8' )
173+ assert_equal ( 'ISO-8859-1' , cgi2 . accept_charset , "accept_charset method should return HTTP header" )
174+ assert_equal ( 'UTF-8' , cgi2 . instance_variable_get ( :@accept_charset ) )
175+ end
176+
177+ # Test encoding error block handling
178+ def test_encoding_error_block_handling
179+ # Test that a block can be provided (even if encoding errors don't occur in this simple case)
180+ test_input = "name=value"
181+ update_env (
182+ 'REQUEST_METHOD' => 'POST' ,
183+ 'CONTENT_TYPE' => 'application/x-www-form-urlencoded' ,
184+ 'CONTENT_LENGTH' => test_input . length . to_s ,
185+ 'SERVER_SOFTWARE' => 'Apache 2.2.0' ,
186+ 'SERVER_PROTOCOL' => 'HTTP/1.1' ,
187+ )
188+
189+ $stdin = StringIO . new ( test_input )
190+
191+ encoding_errors = { }
192+ assert_nothing_raised do
193+ cgi = CGI . new ( accept_charset : 'UTF-8' ) do |name , value |
194+ encoding_errors [ name ] = value
195+ end
196+ assert_equal ( "value" , cgi [ 'name' ] )
197+ end
198+ end
199+
200+ # Test class vs instance charset behavior
201+ def test_class_vs_instance_charset
202+ update_env (
203+ 'REQUEST_METHOD' => 'GET' ,
204+ 'QUERY_STRING' => '' ,
205+ 'SERVER_SOFTWARE' => 'Apache 2.2.0' ,
206+ 'SERVER_PROTOCOL' => 'HTTP/1.1' ,
207+ )
208+
209+ # Class default should be UTF-8
210+ assert_equal ( Encoding ::UTF_8 , CGI . accept_charset )
211+
212+ # Instance with no option should use class default internally
213+ cgi = CGI . new
214+ assert_equal ( Encoding ::UTF_8 , cgi . instance_variable_get ( :@accept_charset ) )
215+ end
216+
217+ # Test max_multipart_length configuration (no public getter available)
218+ def test_max_multipart_length_configuration
219+ update_env (
220+ 'REQUEST_METHOD' => 'GET' ,
221+ 'QUERY_STRING' => '' ,
222+ 'SERVER_SOFTWARE' => 'Apache 2.2.0' ,
223+ 'SERVER_PROTOCOL' => 'HTTP/1.1' ,
224+ )
225+
226+ # Test with integer value - should not raise error
227+ custom_size = 1024 * 1024 # 1 MB
228+ cgi = CGI . new ( max_multipart_length : custom_size )
229+ assert_equal ( custom_size , cgi . instance_variable_get ( :@max_multipart_length ) )
230+
231+ # Test with lambda - should not raise error
232+ check_lambda = -> { 2 * 1024 * 1024 } # 2 MB
233+ cgi = CGI . new ( max_multipart_length : check_lambda )
234+ assert_equal ( check_lambda , cgi . instance_variable_get ( :@max_multipart_length ) )
235+ end
236+
237+ # Test that configuration options don't interfere with each other
238+ def test_option_assignment
239+ update_env (
240+ 'REQUEST_METHOD' => 'GET' ,
241+ 'QUERY_STRING' => '' ,
242+ 'SERVER_SOFTWARE' => 'Apache 2.2.0' ,
243+ 'SERVER_PROTOCOL' => 'HTTP/1.1' ,
244+ )
245+
246+ # Create CGI instances with different combinations of options
247+ cgi1 = CGI . new ( accept_charset : 'EUC-JP' )
248+ cgi2 = CGI . new ( max_multipart_length : 512 * 1024 )
249+ cgi3 = CGI . new ( tag_maker : 'html4' )
250+ cgi4 = CGI . new (
251+ accept_charset : 'ISO-8859-1' ,
252+ max_multipart_length : 256 * 1024 ,
253+ tag_maker : 'html5'
254+ )
255+
256+ # Verify each has the expected configuration
257+ assert_equal ( 'EUC-JP' , cgi1 . instance_variable_get ( :@accept_charset ) )
258+ assert_equal ( 512 * 1024 , cgi2 . instance_variable_get ( :@max_multipart_length ) )
259+ assert_respond_to ( cgi3 , :doctype )
260+
261+ assert_equal ( 'ISO-8859-1' , cgi4 . instance_variable_get ( :@accept_charset ) )
262+ assert_equal ( 256 * 1024 , cgi4 . instance_variable_get ( :@max_multipart_length ) )
263+ assert_respond_to ( cgi4 , :doctype )
264+ assert_equal ( '<!DOCTYPE HTML>' , cgi4 . doctype )
265+ end
266+ end
0 commit comments