mirage-on-thin 3.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/.simplecov +6 -0
  5. data/.travis.yml +3 -0
  6. data/Gemfile +29 -0
  7. data/Gemfile.lock +151 -0
  8. data/HISTORY +22 -0
  9. data/README.md +156 -0
  10. data/Rakefile +10 -0
  11. data/VERSION +1 -0
  12. data/bin/mirage +14 -0
  13. data/features/.nav +29 -0
  14. data/features/client/clear.feature +78 -0
  15. data/features/client/configure.feature +72 -0
  16. data/features/client/model.feature +95 -0
  17. data/features/client/preview_responses.feature +33 -0
  18. data/features/client/prime.feature +32 -0
  19. data/features/client/put.feature +111 -0
  20. data/features/client/readme.md +3 -0
  21. data/features/client/requests.feature +20 -0
  22. data/features/client/running.feature +51 -0
  23. data/features/client/save_and_revert.feature +39 -0
  24. data/features/client/start.feature +46 -0
  25. data/features/client/stop.feature +53 -0
  26. data/features/commandline_interface/help.feature +17 -0
  27. data/features/commandline_interface/readme.md +1 -0
  28. data/features/commandline_interface/start.feature +18 -0
  29. data/features/commandline_interface/stop.feature +42 -0
  30. data/features/logging.feature +6 -0
  31. data/features/prime.feature +35 -0
  32. data/features/readme.md +7 -0
  33. data/features/requests/delete.feature +48 -0
  34. data/features/requests/get.feature +36 -0
  35. data/features/save_and_revert.feature +35 -0
  36. data/features/step_definitions/my_steps.rb +98 -0
  37. data/features/step_definitions/observation_steps.rb +103 -0
  38. data/features/support/command_line.rb +33 -0
  39. data/features/support/env.rb +22 -0
  40. data/features/support/hooks.rb +26 -0
  41. data/features/support/mirage.rb +12 -0
  42. data/features/support/web.rb +20 -0
  43. data/features/templates/delete.feature +45 -0
  44. data/features/templates/get.feature +54 -0
  45. data/features/templates/path_wildcards.feature +10 -0
  46. data/features/templates/preview.feature +18 -0
  47. data/features/templates/put.feature +77 -0
  48. data/features/templates/put_with_substitutions.feature +22 -0
  49. data/features/templates/readme.md +4 -0
  50. data/features/templates/required_content.feature +113 -0
  51. data/features/web_user_interface.feature +44 -0
  52. data/full_build.sh +100 -0
  53. data/lib/mirage/client.rb +10 -0
  54. data/lib/mirage/client/cli_bridge.rb +30 -0
  55. data/lib/mirage/client/client.rb +73 -0
  56. data/lib/mirage/client/error.rb +22 -0
  57. data/lib/mirage/client/helpers/method_builder.rb +19 -0
  58. data/lib/mirage/client/request.rb +26 -0
  59. data/lib/mirage/client/requests.rb +13 -0
  60. data/lib/mirage/client/runner.rb +103 -0
  61. data/lib/mirage/client/template.rb +56 -0
  62. data/lib/mirage/client/template/configuration.rb +44 -0
  63. data/lib/mirage/client/template/model.rb +48 -0
  64. data/lib/mirage/client/template/model/common_methods.rb +24 -0
  65. data/lib/mirage/client/template/model/instance_methods.rb +95 -0
  66. data/lib/mirage/client/templates.rb +50 -0
  67. data/mirage-on-thin.gemspec +175 -0
  68. data/mirage_server.rb +35 -0
  69. data/server/app.rb +4 -0
  70. data/server/binary_data_checker.rb +15 -0
  71. data/server/extensions/hash.rb +10 -0
  72. data/server/extensions/object.rb +5 -0
  73. data/server/helpers.rb +3 -0
  74. data/server/helpers/http_headers.rb +31 -0
  75. data/server/helpers/template_requirements.rb +33 -0
  76. data/server/mock_response.rb +242 -0
  77. data/server/server.rb +184 -0
  78. data/spec/client/cli_bridge_spec.rb +63 -0
  79. data/spec/client/client_spec.rb +179 -0
  80. data/spec/client/helpers/method_builder_spec.rb +40 -0
  81. data/spec/client/request_spec.rb +39 -0
  82. data/spec/client/requests_spec.rb +9 -0
  83. data/spec/client/runner_spec.rb +138 -0
  84. data/spec/client/template/configuration_spec.rb +32 -0
  85. data/spec/client/template/model/common_methods_spec.rb +25 -0
  86. data/spec/client/template/model/instance_methods_spec.rb +169 -0
  87. data/spec/client/template/model_spec.rb +119 -0
  88. data/spec/client/template_spec.rb +146 -0
  89. data/spec/client/templates_spec.rb +197 -0
  90. data/spec/resources/binary.file +0 -0
  91. data/spec/server/binary_data_checker_spec.rb +21 -0
  92. data/spec/server/helpers/http_headers_spec.rb +20 -0
  93. data/spec/server/helpers/template_requirements_spec.rb +34 -0
  94. data/spec/server/mock_response_spec.rb +577 -0
  95. data/spec/server/server_spec.rb +156 -0
  96. data/spec/spec_helper.rb +85 -0
  97. data/tasks/application.rake +7 -0
  98. data/tasks/packaging.rake +28 -0
  99. data/tasks/tests.rake +25 -0
  100. data/views/index.haml +16 -0
  101. data/views/response.haml +46 -0
  102. metadata +337 -0
@@ -0,0 +1,22 @@
1
+ module Mirage
2
+ class MirageError < ::Exception
3
+ attr_reader :code
4
+
5
+ def initialize message, code
6
+ super message
7
+ @code = message, code
8
+ end
9
+ end
10
+
11
+ class InternalServerException < MirageError
12
+ end
13
+
14
+ class TemplateNotFound < ::Exception
15
+ end
16
+
17
+ class ClientError < ::Exception
18
+ def initialize message
19
+ super message
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ module Mirage
2
+ module Helpers
3
+ module MethodBuilder
4
+ def builder_methods *method_names
5
+
6
+ method_names.each do |method_name|
7
+ method_name = method_name.to_sym
8
+ define_method method_name do |arg=nil|
9
+ return instance_variable_get("@#{method_name}".to_sym) if arg.nil?
10
+ instance_variable_set("@#{method_name}".to_sym, arg)
11
+ self
12
+ end
13
+ end
14
+
15
+ end
16
+ alias builder_method builder_methods
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ require 'hashie/mash'
2
+ module Mirage
3
+ class Request
4
+ include HTTParty
5
+
6
+ class << self
7
+ alias_method :backedup_get, :get
8
+ def get url
9
+ result = Hashie::Mash.new(backedup_get(url, format: :json))
10
+ request = new
11
+ request.parameters = result.parameters
12
+ request.headers = result.headers
13
+ request.request_url = result.request_url
14
+ request.body = result.body
15
+ request.id = result.id
16
+ request
17
+ end
18
+ end
19
+
20
+ attr_accessor :parameters, :headers, :body, :request_url, :id
21
+
22
+ def delete
23
+ self.class.delete(id)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ module Mirage
2
+ class Requests
3
+ include HTTParty
4
+
5
+ def initialize base_url
6
+ @url = "#{base_url}/requests"
7
+ end
8
+
9
+ def delete_all
10
+ self.class.delete(@url)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,103 @@
1
+ require 'thor'
2
+ require 'waitforit'
3
+ require 'childprocess'
4
+ require 'uri'
5
+ require 'httparty'
6
+ module Mirage
7
+ class << self
8
+
9
+ # Start Mirage locally on a given port
10
+ # Example Usage:
11
+ #
12
+ # Mirage.start :port => 9001 -> Configured MirageClient ready to use.
13
+ def start options={}
14
+ options={:port => 7001}.merge(options)
15
+ Runner.new.invoke(:start, [], options)
16
+ Mirage::Client.new(options)
17
+ end
18
+
19
+ # Stop locally running instance(s) of Mirage
20
+ #
21
+ # Example Usage:
22
+ # Mirage.stop -> Will stop mirage if there is only instance running. Can be running on any port.
23
+ # Mirage.stop :port => port -> stop mirage on a given port
24
+ # Mirage.stop :port => [port1, port2...] -> stops multiple running instances of Mirage
25
+ def stop options={:port => []}
26
+ options = {:port => :all} if options == :all
27
+
28
+ if options[:port]
29
+ options[:port] = [options[:port]] unless options[:port].is_a?(Array)
30
+ end
31
+
32
+ Runner.new.invoke(:stop, [], options)
33
+ rescue ClientError => e
34
+ raise ClientError.new("Mirage is running multiple ports, please specify the port(s) see api/tests for details")
35
+ end
36
+
37
+
38
+ # Detect if Mirage is running on a URL or a local port
39
+ #
40
+ # Example Usage:
41
+ # Mirage.running? -> boolean indicating whether Mirage is running on *locally* on port 7001
42
+ # Mirage.running? :port => port -> boolean indicating whether Mirage is running on *locally* on the given port
43
+ # Mirage.running? url -> boolean indicating whether Mirage is running on the given URL
44
+ def running? options_or_url = {:port => 7001}
45
+ url = options_or_url.kind_of?(Hash) ? "http://localhost:#{options_or_url[:port]}" : options_or_url
46
+ HTTParty.get(url) and return true
47
+ rescue Errno::ECONNREFUSED
48
+ return false
49
+ end
50
+
51
+ end
52
+
53
+ class Runner < Thor
54
+ include CLIBridge
55
+ RUBY_CMD = ChildProcess.jruby? ? 'jruby' : 'ruby'
56
+
57
+ desc "start", "Starts mirage"
58
+ method_option :port, :aliases => "-p", :type => :numeric, :default => 7001, :desc => "port that mirage should be started on"
59
+ method_option :defaults, :aliases => "-d", :type => :string, :default => 'mirage', :desc => "location to load default responses from"
60
+ method_option :debug, :type => :boolean, :default => false, :desc => "run in debug mode"
61
+
62
+ def start
63
+ port = options[:port]
64
+ process_ids = mirage_process_ids([port])
65
+ unless process_ids.empty?
66
+ warn "Mirage is already running: #{process_ids.values.join(",")}"
67
+ return
68
+ end
69
+
70
+ mirage_server_file = "#{File.dirname(__FILE__)}/../../../mirage_server.rb"
71
+
72
+ if ChildProcess.windows?
73
+ command = ["cmd", "/C", "start", "mirage server port #{port}", RUBY_CMD, mirage_server_file]
74
+ else
75
+ command = [RUBY_CMD, mirage_server_file]
76
+ end
77
+
78
+
79
+ command = command.concat(options.to_a).flatten.collect { |arg| arg.to_s }
80
+ ChildProcess.build(*command).start
81
+
82
+ wait_until(:timeout_after => 30.seconds) { Mirage.running?(options) }
83
+
84
+ begin
85
+ Mirage::Client.new(options).prime
86
+ rescue Mirage::InternalServerException => e
87
+ puts "WARN: #{e.message}"
88
+ end
89
+ end
90
+
91
+ desc "stop", "Stops mirage"
92
+ method_option :port, :aliases => "-p", :type => :array, :default => [], :banner => "[port_1 port_2|all]", :desc => "port(s) of mirage instance(s). ALL stops all running instances"
93
+
94
+ def stop
95
+ ports = options[:port].collect{|port| port=~/\d+/ ? port.to_i : port}
96
+ process_ids = mirage_process_ids(ports)
97
+ raise ClientError.new("Mirage is running on ports #{process_ids.keys.sort.join(", ")}. Please run mirage stop -p [PORT(s)] instead") if (process_ids.size > 1 && ports.empty?)
98
+ process_ids.values.each { |process_id| kill process_id }
99
+ wait_until { mirage_process_ids(options[:port]).empty? }
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,56 @@
1
+ require 'ostruct'
2
+ require 'json'
3
+ require 'httparty'
4
+ require 'hashie/mash'
5
+
6
+ require 'client/template/configuration'
7
+ require 'client/template/model'
8
+
9
+ module Mirage
10
+
11
+ class Template
12
+
13
+ include HTTParty
14
+ include Model::InstanceMethods
15
+ include Model::CommonMethods
16
+
17
+ class << self
18
+ alias_method :backedup_get, :get
19
+
20
+ def get url
21
+ response = backedup_get(url, :format => :json)
22
+ raise TemplateNotFound if response.code == 404
23
+ response_hashie = Hashie::Mash.new response
24
+
25
+ response_config = response_hashie.response
26
+ request_config = response_hashie.request
27
+
28
+ template = new(response_hashie.endpoint, Base64.decode64(response_config.body))
29
+
30
+ template.id response_hashie.id
31
+ template.default response_config['default']
32
+ template.delay response_config.delay
33
+ template.content_type response_config.content_type
34
+ template.status response_config.status
35
+ template.headers response_config.headers
36
+
37
+ template.required_parameters request_config.parameters
38
+ template.required_body_content request_config.body_content
39
+ template.http_method request_config.http_method
40
+ template.url url
41
+ template.requests_url response_hashie.requests_url
42
+ template.required_headers request_config.headers
43
+
44
+ template
45
+ end
46
+ end
47
+
48
+ def initialize *args
49
+ endpoint = args.first
50
+
51
+ raise ArgumentError, "You must specify a string endpoint as the first argument" unless endpoint && endpoint.is_a?(String)
52
+ super *args
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,44 @@
1
+ require 'client/helpers/method_builder'
2
+
3
+ module Mirage
4
+ class Template
5
+ class Configuration
6
+ extend Helpers::MethodBuilder
7
+ builder_methods :http_method, :status, :delay, :content_type, :default
8
+ attr_accessor :caller_binding
9
+ DEFAULT_HTTP_METHOD=:get
10
+ DEFAULT_STATUS=200
11
+ DEFAULT_DELAY=0
12
+ DEFAULT_CONTENT_TYPE="text/plain"
13
+ DEFAULT_DEFAULT=false
14
+
15
+ def initialize
16
+ reset
17
+ end
18
+
19
+ def reset
20
+ @http_method = DEFAULT_HTTP_METHOD
21
+ @status = DEFAULT_STATUS
22
+ @delay = DEFAULT_DELAY
23
+ @content_type = DEFAULT_CONTENT_TYPE
24
+ @default = DEFAULT_DEFAULT
25
+ end
26
+
27
+
28
+ def method_missing(method, *args, &block)
29
+ @caller_binding.send method, *args, &block if @caller_binding
30
+ end
31
+
32
+ def == config
33
+ config.is_a?(Configuration) &&
34
+ http_method == config.http_method &&
35
+ status == config.status &&
36
+ delay == config.delay &&
37
+ content_type == config.content_type &&
38
+ default == config.default
39
+
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,48 @@
1
+ require 'client/helpers/method_builder'
2
+ require 'client/template/model/common_methods'
3
+ require 'client/template/model/instance_methods'
4
+
5
+ module Mirage
6
+ class Template
7
+ module Model
8
+
9
+ class << self
10
+ def extended clazz
11
+ clazz.extend(CommonMethods)
12
+ clazz.extend(Helpers::MethodBuilder)
13
+ clazz.send(:include, HTTParty)
14
+ clazz.send(:include, CommonMethods)
15
+ clazz.send(:include, InstanceMethods)
16
+
17
+
18
+ mod = Module.new do
19
+ def initialize *args
20
+
21
+ super *args
22
+ [:content_type,
23
+ :http_method,
24
+ :default,
25
+ :status,
26
+ :delay,
27
+ :required_parameters,
28
+ :required_body_content,
29
+ :required_headers,
30
+ :headers,
31
+ :endpoint, :delay].each do |attribute|
32
+ eval("#{attribute} self.class.#{attribute} if self.class.#{attribute}")
33
+ end
34
+
35
+
36
+ end
37
+ end
38
+
39
+ clazz.send(:include, mod)
40
+
41
+ clazz.format :json
42
+ clazz
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,24 @@
1
+ module Mirage
2
+
3
+ class Template
4
+ module Model
5
+ module CommonMethods
6
+ extend Helpers::MethodBuilder
7
+
8
+ builder_methods :content_type,
9
+ :http_method,
10
+ :default,
11
+ :status,
12
+ :delay,
13
+ :required_parameters,
14
+ :required_body_content,
15
+ :required_headers,
16
+ :headers,
17
+ :endpoint,
18
+ :body
19
+ end
20
+
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,95 @@
1
+ module Mirage
2
+ class Template
3
+ module Model
4
+ module InstanceMethods
5
+ extend Helpers::MethodBuilder
6
+ include CommonMethods
7
+
8
+ attr_accessor :caller_binding
9
+
10
+ def initialize *args
11
+ if args.last.is_a?(Template::Configuration)
12
+ default_config = args.delete_at(-1)
13
+ else
14
+ default_config = Template::Configuration.new
15
+ end
16
+
17
+ @endpoint, @body = *args
18
+ @content_type = default_config.content_type
19
+ @http_method = default_config.http_method
20
+ @status = default_config.status
21
+ @delay = default_config.delay
22
+ @required_parameters = {}
23
+ @required_headers = {}
24
+ @required_body_content = []
25
+ @headers = {}
26
+ @default = default_config.default
27
+ end
28
+
29
+ builder_method :id,
30
+ :url,
31
+ :requests_url
32
+
33
+
34
+ def create
35
+ @id = self.class.put("#{@endpoint}", :body => self.to_json, :headers => {'content-type' => 'application/json'})['id']
36
+ self
37
+ end
38
+
39
+ def delete
40
+ self.class.delete(url)
41
+ Request.delete requests_url
42
+ end
43
+
44
+
45
+ def to_json
46
+ {
47
+ :response => {
48
+ :body => Base64.encode64(body),
49
+ :status => status,
50
+ :default => default,
51
+ :content_type => content_type,
52
+ :headers => headers,
53
+ :delay => delay
54
+ },
55
+ :request => {
56
+ :parameters => encode_regexs(required_parameters),
57
+ :headers => encode_regexs(required_headers),
58
+ :body_content => encode_regexs(required_body_content),
59
+ :http_method => http_method,
60
+ }
61
+ }.to_json
62
+ end
63
+
64
+
65
+ def encode_regexs hash_or_array
66
+ case hash_or_array
67
+ when Array
68
+ hash_or_array.collect { |value| encode(value) }
69
+ else
70
+ encoded = {}
71
+ hash_or_array.each do |key, value|
72
+ encoded[key] = encode(value)
73
+ end
74
+ encoded
75
+ end
76
+ end
77
+
78
+ def encode(value)
79
+ value.is_a?(Regexp) ? "%r{#{value.source}}" : value
80
+ end
81
+
82
+ def method_missing(method, *args, &block)
83
+
84
+ if @caller_binding
85
+ @caller_binding.send method, *args, &block
86
+ else
87
+ super method, *args, &block
88
+ end
89
+
90
+ end
91
+ end
92
+
93
+ end
94
+ end
95
+ end