nec_mock_server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fbf6ba4bd3541234bfd1bc9b98cc95672174c8a2
4
+ data.tar.gz: b079b4358a68b89072d8f12a77cd6c6e28652028
5
+ SHA512:
6
+ metadata.gz: 6f7853a2f37895c03c94490bff7f051b01b4adae4bf9ff9a5cbb2ff7c441c48f70144738fcacee4e104490de241aa8880c7e1a4ef28d96891464df1542dd71f0
7
+ data.tar.gz: eeffd2706f79733a1260febf0ef9e6744596c34de7f68ac3dd40098fbe8cef530c993720b80c8fd67089b93c2f6321fffefd354c16b4e02ae7b708b6fdcf3f66
@@ -0,0 +1,13 @@
1
+ require 'rack'
2
+ require 'rack/server'
3
+ require 'json'
4
+ require 'fileutils'
5
+
6
+ module NEC
7
+
8
+ end
9
+
10
+
11
+ Dir[File.dirname(__FILE__) + '/nec_mock_server/*.rb'].each do |file|
12
+ require(file.gsub('\\', '/').split('/lib/').last[0..-4])
13
+ end
@@ -0,0 +1,248 @@
1
+ module NEC
2
+
3
+ ###
4
+ # Module of Mock Server
5
+ module MockServer
6
+
7
+ ###
8
+ # Server class. Represent main class of module #MockServe
9
+ class Server
10
+
11
+ attr_reader :router, :app
12
+
13
+ ###
14
+ # The method creates new instance of Rack::Server
15
+ #
16
+ # @param [MockServer::Router] router
17
+ # @param [Hash] application_opts
18
+ # @option application_opts [String] :application_name
19
+ # @option opts [Regexp] :matcher Define how to split parts of all request URL. Default is to #MATCHERS[:base]
20
+ # @option opts [Boolean] :only_registered_awid If set to true all requests that wasn't call on registered awid (by sys/iniAppWorkspace) will be rejected
21
+ # @option opts [Hash{TID => Array<AWID>}] :awids
22
+ # @option opts [Hash{TID => Array<ASIDS>}] :asids
23
+ def initialize(router, application_opts = {})
24
+ @router = (router || Router).new(application_opts[:application_name])
25
+ @app = Application.new(@router, application_opts)
26
+ end
27
+
28
+ ###
29
+ # The method stars server of instance
30
+ #
31
+ # @param [Numeric] port
32
+ # @param [String] host Default to 'localhost'
33
+ def run!(port, host = 'localhost')
34
+ @server = Rack::Server.start(app: @app, Port: port, Host: host)
35
+ end
36
+ end
37
+
38
+ ###
39
+ # Class represent trivial application to handle requests by defined router.
40
+ class Application
41
+
42
+ MATCHERS = {
43
+ base: /:\d+(\/(?<product>[\-\w]+)){0,1}(\/(?<tid>\w+)\-(?<awid>\w+)){0,1}(?<resource>(\/\w+)+)(\?(?<parameters>.*)){0,1}/
44
+ }
45
+
46
+ REGISTER_AWID_RESOURCE = '/sys/initAppWorkspace'
47
+
48
+ attr_reader :awids, :asids
49
+
50
+ ###
51
+ # The method create new instance of Application
52
+ #
53
+ # @param [MockServer::Router] router
54
+ # @param [Hash] opts
55
+ # @option opts [Regexp] :matcher Define how to split parts of all request URL. Default is to #MATCHERS[:base]
56
+ # @option opts [Boolean] :only_registered_awid If set to true all requests that wasn't call on registered awid (by sys/iniAppWorkspace) will be rejected
57
+ # @option opts [Hash{TID => Array<AWID>}] :awids
58
+ # @option opts [Hash{TID => Array<ASIDS>}] :asids
59
+ def initialize(router, opts = {})
60
+ @router = router
61
+ @only_registered_awid = opts[:only_registered_awid]
62
+ @url_parts_matcher = opts.fetch(:matcher) {MATCHERS[:base]}
63
+ @awids = opts.fetch(:awids){ {} }
64
+ @asids = opts.fetch(:asids){ {} }
65
+ end
66
+
67
+ ###
68
+ # The method prepare request and process request
69
+ #
70
+ # @param [Hash] env
71
+ def call(env)
72
+ request = Rack::Request.new(env)
73
+ serve_request(request)
74
+ end
75
+
76
+ ###
77
+ # The method handle received request.
78
+ #
79
+ # @param [Rack::Request] request
80
+ def serve_request(request)
81
+ parts = get_url_parts(request.url)
82
+
83
+ begin
84
+ io = request.body
85
+ data = io.read
86
+ ensure
87
+ io.close if io && io.respond_to?(:close) && io.respond_to?(:closed?) && !io.closed?
88
+ end
89
+
90
+ if parts[:resource] && parts[:resource] == REGISTER_AWID_RESOURCE
91
+ process_sys_init_app_workspace(parts, data)
92
+ end
93
+
94
+ if @only_registered_awid
95
+ return @router.no_registered_awid(parts[:tid], parts[:awid]) unless is_registered_resource?(parts[:tid], parts[:awid])
96
+ end
97
+
98
+ @router.route(parts, data)
99
+ end
100
+
101
+ private
102
+
103
+ def is_registered_awid?(tid, awid)
104
+ @awids[tid] && !(@awids[tid] & [awid]).empty?
105
+ end
106
+
107
+ def is_registered_asid?(tid, asid)
108
+ @awids[tid] && !(asids[tid] & [asid]).empty?
109
+ end
110
+
111
+ def is_registered_resource?(tid, awid)
112
+ is_registered_awid?(tid, awid) || is_registered_asid?(tid, awid)
113
+ end
114
+
115
+ def process_sys_init_app_workspace(parts, data)
116
+ hash = data.is_a?(Hash) ? data : JSON.parse(data.to_s, symbolize_names: true)
117
+
118
+ @awids[parts[:tid]] ||= []
119
+ @awids[parts[:tid]] << hash[:awid] if (@awids[parts[:tid]] & [hash[:awid]]).empty?
120
+
121
+ @asids[parts[:tid]] ||= []
122
+ @asids[parts[:tid]] << parts[:awid] if (@awids[parts[:tid]] & [parts[:awid]]).empty?
123
+
124
+ nil
125
+ end
126
+
127
+ ###
128
+ # The method helps to parse request url
129
+ def get_url_parts(path)
130
+ result = path.match(@url_parts_matcher)
131
+ result ? result.names.map {|name| name.to_sym}.zip(result.captures).to_h : {resource: ''}
132
+ end
133
+ end
134
+
135
+ ###
136
+ # Class represents all routes that application can served.
137
+ # For customize own mock application is necessary to create own router class by inheritance of this class
138
+ class Router
139
+
140
+ DEFAULT_APPLICATION_NAME = "Mock Server"
141
+
142
+ CONTENT_TYPES = {
143
+ text: {
144
+ plain: "text/plain"
145
+ },
146
+ application: {
147
+ json: "application/json"
148
+ }
149
+ }
150
+
151
+ DEFAULT_HEADER = {"Content-Type" => CONTENT_TYPES[:text][:plain]}
152
+ JSON_HEADER = {"Content-Type" => CONTENT_TYPES[:application][:json]}
153
+
154
+ ###
155
+ # The method create new instance of router
156
+ #
157
+ # @param [String] application_name
158
+ def initialize(application_name)
159
+ @application_name = application_name || DEFAULT_APPLICATION_NAME
160
+ end
161
+
162
+ ###
163
+ # The method process all operation on defined request URL and return response data
164
+ #
165
+ # @param [Hash] parts All parts find by specified matcher of URL request
166
+ # @param [String] request_data Received data by request
167
+ def route(parts, request_data)
168
+ case parts[:resource]
169
+ when "/", ""
170
+ home
171
+ when "/error"
172
+ error("Application exception")
173
+ else
174
+ not_found(parts[:resource])
175
+ end
176
+ end
177
+
178
+ ###
179
+ # The method represent default home route on "/" or ""
180
+ # Return 200 OK a and #application_name
181
+ def home
182
+ ok(@application_name)
183
+ end
184
+
185
+ ###
186
+ # The method represent base success response, 200 OK
187
+ #
188
+ # @param [Object] body Body of response
189
+ # @param [Hash] headers Headers of response
190
+ #
191
+ # @return [Array] response_data
192
+ def ok(body = nil, headers = DEFAULT_HEADER)
193
+ prepare_response_data(200, headers, body)
194
+ end
195
+
196
+ ###
197
+ # The method represent base not found response, 404 Not Found
198
+ #
199
+ # @param [String] resource Resource is required route part, which was no defined.
200
+ #
201
+ # @return [Array] response_data
202
+ def not_found(resource)
203
+ prepare_response_data(404, DEFAULT_HEADER, "Undefined Mock Server resource '#{resource}' for #{@application_name}")
204
+ end
205
+
206
+ ###
207
+ # The method represent specific not found response for request on no registered pair tid-awid
208
+ #
209
+ # @param [String] tid
210
+ # @param [String] awid
211
+ def no_registered_awid(tid, awid)
212
+ prepare_response_data(404, DEFAULT_HEADER, "Mock Server has no registered TID-AWID '#{tid}-#{awid}' for #{@application_name}")
213
+ end
214
+
215
+ ###
216
+ # The method represent base server error response, 500 Internal Server Error
217
+ #
218
+ # @param [Object] body Body of response
219
+ # @param [Hash] headers Headers of response
220
+ #
221
+ # @return [Array] response_data
222
+ def error(body, headers = DEFAULT_HEADER)
223
+ prepare_response_data(500, headers, body)
224
+ end
225
+
226
+ private
227
+
228
+ ###
229
+ # The method prepare response data as Array
230
+ #
231
+ # @param [String] http_code
232
+ # @param [Hash] headers
233
+ # @param [Object] body
234
+ #
235
+ # @param [Array] response_data
236
+ def prepare_response_data(http_code, headers, body)
237
+ body = body.nil? ? '' : body
238
+ body = body.to_json if body.is_a?(Hash)
239
+ body = body.to_s unless body.is_a?(String)
240
+
241
+ [http_code, headers.nil? ? DEFAULT_HEADER : headers, [body]]
242
+ end
243
+ end
244
+
245
+
246
+ end
247
+
248
+ end
@@ -0,0 +1,46 @@
1
+ module NEC
2
+ class MockServerStarter
3
+
4
+ RUN_SCRIPT_NAME = 'run.rb'
5
+
6
+ ###
7
+ # Create new instance of SubAppUnitTestHelper
8
+ #
9
+ # @param [String] sub_app_dir_path
10
+ # @param [Hash] opts
11
+ # @option opts [String] :run_scrip_name Default is #RUN_SCRIPT_NAME
12
+ def initialize(sub_app_dir_path, opts = {})
13
+ @path = File.expand_path(sub_app_dir_path, File.dirname(__FILE__))
14
+ @run_scrip_name = opts.fetch(:run_scrip_name) {RUN_SCRIPT_NAME}
15
+ end
16
+
17
+ ###
18
+ # The method start another sub application by defined path
19
+ # Sub app will be started in new command line with irb
20
+ #
21
+ def run!
22
+ create_threat
23
+ end
24
+
25
+ ###
26
+ # The method terminate exists thread of sub app
27
+ def stop
28
+ warn('! Method has no function implementation !')
29
+ # fixme how to stop thread with cmd window | some process kill by pid ...
30
+ @thread.terminate if @thread
31
+ end
32
+
33
+ private
34
+
35
+ ###
36
+ # The method create new thread for sub app and start it in new cmd window.
37
+ def create_threat
38
+ stop
39
+
40
+ @thread = Thread.new {
41
+ system("cd #{@path} && start irb -I . -r #{@run_scrip_name}")
42
+ }
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ module NECMockServerHelper
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nec_mock_server
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Marek Filteš
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-01-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.15'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.15'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: NEC helper gem to create Unit Test mock server of sub application
42
+ email:
43
+ - marek.files@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/nec_mock_server.rb
49
+ - lib/nec_mock_server/mock_server.rb
50
+ - lib/nec_mock_server/mock_server_starter.rb
51
+ - lib/nec_mock_server/version.rb
52
+ homepage:
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 2.4.5.2
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: NEC Mock Server
76
+ test_files: []