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.
- checksums.yaml +7 -0
- data/lib/nec_mock_server.rb +13 -0
- data/lib/nec_mock_server/mock_server.rb +248 -0
- data/lib/nec_mock_server/mock_server_starter.rb +46 -0
- data/lib/nec_mock_server/version.rb +3 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -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,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
|
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: []
|