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,77 @@
1
+ Feature: Creating a Template
2
+ Mirage can be configured with Templates. Templates describe the characteristics of responses that should be returned to a client. In addition to this a templates also describe the conditions under which a template may be used to generate a response.
3
+
4
+ On setting a template, a unique id is returned. This is a key that can be used to manage the Template.
5
+
6
+ Templates can be configured to respond to either, GET, POST, PUT, or DELETE.
7
+
8
+ More than one Template can be placed at the same resource address as long as they have different request contraints. In this case they are given different IDs. For example if two templates are configured to respond to request using different HTTP methods then they will not overwrite each other but both be stored.
9
+
10
+ Requirements can be specified as required when configuring a Template:
11
+ * request parameters
12
+ * body content
13
+ * HTTP Headers
14
+ * HTTP Method
15
+
16
+ The following attributes of a response can be configured
17
+ * HTTP status code
18
+ * Whether this template is to be treated as the default response if a match is not found for a sub URI
19
+ * A delay before the response is returned to the client. This is in seconds and floats are accepted
20
+ * Content-Type
21
+
22
+ Things to note:
23
+ ---------------
24
+ The body attribute of the response should be Base64 encoded. This is so that you may specify binary data if that is what you would like to send back to clients.
25
+
26
+
27
+ Scenario: Setting a Template on Mirage
28
+ Given the following Template JSON:
29
+ """
30
+ {
31
+ "request":{
32
+ "parameters":{},
33
+ "http_method":"get",
34
+ "headers": {},
35
+ "body_content":[]
36
+ },
37
+ "response":{
38
+ "default":false,
39
+ "body":"SGVsbG8=",
40
+ "delay":0,
41
+ "content_type":"text/plain",
42
+ "status":200
43
+ }
44
+ }
45
+ """
46
+ When the template is sent using PUT to '/templates/greeting'
47
+ Then '{"id":1}' should be returned
48
+
49
+ When GET is sent to '/responses/greeting'
50
+ Then 'Hello' should be returned
51
+ And a 200 should be returned
52
+
53
+
54
+ Scenario: Template defaults
55
+ Given the following Template JSON:
56
+ """
57
+ {}
58
+ """
59
+ When the template is sent using PUT to '/templates/greeting'
60
+ Then the template request specification should have the following set:
61
+ | Setting | Default |
62
+ | parameters | none |
63
+ | body content | none |
64
+ | headers | none |
65
+ | HTTP method | GET |
66
+ And the template response specification should have the following set:
67
+ | Setting | Default |
68
+ | default | false |
69
+ | body | none |
70
+ | content_type | text/plain |
71
+ | delay | 0 |
72
+ | status | 200 |
73
+
74
+ Scenario: Making a request that is unmatched
75
+ When GET is sent to '/responses/unmatched'
76
+ Then a 404 should be returned
77
+
@@ -0,0 +1,22 @@
1
+ Feature: Substituting values from requests in to a template
2
+ Parts of a response can be substituted for values found in the request body or query string.
3
+ This allows dynamic content to be sent back to a client.
4
+
5
+ To do this, substitution, matchers must be put in the the response value.
6
+
7
+ Either a string literal or a regex can be used in between ${} to find a match
8
+
9
+ Scenario: A response template populated from matches found in the request body using a regex
10
+ Given the following template template:
11
+ """
12
+ {
13
+ "response":{
14
+ "body":"Hello ${name}"
15
+ }
16
+ }
17
+ """
18
+ And 'response.body' is base64 encoded
19
+ And the template is sent using PUT to '/templates/greeting'
20
+ When I send GET to '/responses/greeting' with parameters:
21
+ |name|Joe |
22
+ Then 'Hello Joe' should be returned
@@ -0,0 +1,4 @@
1
+ Templates are the descriptors pushed to Mirage to tell it what to return to a client.
2
+
3
+ They can be configured to place restrictions on the requests that should be met before they are allowed to be used to generate a response.
4
+
@@ -0,0 +1,113 @@
1
+ Feature: Placing requirements on requests
2
+ If you want Mirage to be choosy when using a Template to generate a response the following can have requirements placed on them when looking for a suitable to Template to generate responses:
3
+
4
+ * request parameters
5
+ * body content
6
+ * HTTP Headers
7
+ * HTTP Method
8
+
9
+ When specifying requirements on Headers, request parameters or the body of a request either a litteral string
10
+ or a regular expression can be used for matching.
11
+
12
+ Background: There is already a default response for 'greeting'
13
+ Given the following template template:
14
+ """
15
+ {
16
+ "request":{
17
+ "parameters":{},
18
+ "http_method":"get",
19
+ "body_content":[]
20
+ },
21
+ "response":{
22
+ "default":false,
23
+ "body":"Hello Stranger",
24
+ "delay":0,
25
+ "content_type":"text/plain",
26
+ "status":200
27
+ }
28
+ }
29
+ """
30
+ And 'response.body' is base64 encoded
31
+ And the template is sent using PUT to '/templates/greeting'
32
+
33
+ Scenario: Configuring a template with requirements on HTTP headers
34
+ Given the following template template:
35
+ """
36
+ {
37
+ "request":{
38
+ "parameters":{},
39
+ "http_method":"get",
40
+ "body_content":[]
41
+ },
42
+ "response":{
43
+ "default":false,
44
+ "body":"Hello Stranger",
45
+ "delay":0,
46
+ "content_type":"text/plain",
47
+ "status":200
48
+ }
49
+ }
50
+ """
51
+ And 'response.body' is base64 encoded
52
+ And the template is sent using PUT to '/templates/greeting'
53
+
54
+
55
+ Scenario: Configuring a template with requirements on request parameters
56
+ Given the following template template:
57
+ """
58
+ {
59
+ "request":{
60
+ "parameters":{
61
+ "firstname" : "%r\{.*e}",
62
+ "surname" : "Blogs"
63
+ },
64
+ "http_method":"get",
65
+ "body_content":[]
66
+ },
67
+ "response":{
68
+ "default":false,
69
+ "body":"Hello Joe",
70
+ "delay":0,
71
+ "content_type":"text/plain",
72
+ "status":200
73
+ }
74
+ }
75
+ """
76
+ And 'response.body' is base64 encoded
77
+ And the template is sent using PUT to '/templates/greeting'
78
+
79
+ When I send GET to '/responses/greeting' with parameters:
80
+ |firstname|Joe |
81
+ |surname |Blogs|
82
+ Then 'Hello Joe' should be returned
83
+
84
+ Scenario: Configuring a template with requirements on the body
85
+ Given the following template template:
86
+ """
87
+ {
88
+ "request":{
89
+ "parameters":{},
90
+ "http_method":"POST",
91
+ "body_content":["Joe", "%r{B..gs}"]
92
+ },
93
+ "response":{
94
+ "default":false,
95
+ "body":"Hello Joe",
96
+ "delay":0,
97
+ "content_type":"text/plain",
98
+ "status":200
99
+ }
100
+ }
101
+ """
102
+ And 'response.body' is base64 encoded
103
+ And the template is sent using PUT to '/templates/greeting'
104
+
105
+ When I send POST to '/responses/greeting' with request entity
106
+ """
107
+ {"username":"Joe Blogs"}
108
+ """
109
+ Then 'Hello Joe' should be returned
110
+
111
+
112
+
113
+
@@ -0,0 +1,44 @@
1
+ Feature: Web interface
2
+ Note: This feature is being rewritten but the screens pretty basic so take a look:
3
+
4
+ The home page is served from '/' so by default is found at http://localhost:7001/
5
+
6
+ Mirage's home page allows you to see what response are currently being hosted.
7
+ From this page you can:
8
+ - See all currently hosted templates
9
+ - Preview at a Templates content
10
+ - View the last request to trigger a particular Template
11
+
12
+
13
+ # Background: There are already a couple of responses hosted on he Mirage server
14
+ # Given the following template template:
15
+ # """
16
+ # {
17
+ # "response":{
18
+ # "body":"SGVsbG8="
19
+ # },
20
+ # "request":{
21
+ # }
22
+ # }
23
+ # """
24
+ # And the template is sent using PUT to '/templates/greeting'
25
+ #
26
+ #
27
+ # Scenario: Using the home page to see what response are being hosted
28
+ # Given I goto to the Mirage home page
29
+ # Then I should see 'greeting/*'
30
+ # Then I should see 'leaving'
31
+ #
32
+ # Scenario: Using the home page to peek at a response
33
+ # Given I goto ''
34
+ # When I click 'peek_response_1'
35
+ # Then I should see 'hello'
36
+ #
37
+ # Scenario: Using the home page to track if a request has been made
38
+ # Given I send POST to '/responses/greeting' with request entity
39
+ # """
40
+ # Yo!
41
+ # """
42
+ # Given I goto ''
43
+ # When I click 'track_response_1'
44
+ # Then I should see 'Yo!'
data/full_build.sh ADDED
@@ -0,0 +1,100 @@
1
+ #!/bin/bash
2
+ blue='\033[34m'
3
+ red='\033[31m'
4
+ green='\033[32m'
5
+ yellow='\033[33m'
6
+ white='\033[37m'
7
+ bold='\033[1m'
8
+ reset='\033[0m'
9
+
10
+ println(){
11
+ echo -e "$1${reset}"
12
+ }
13
+
14
+ print(){
15
+ echo -ne "$1${reset}"
16
+ }
17
+
18
+
19
+
20
+ usage(){
21
+ println "${bold}Usage:\n"
22
+ println "./full_build.sh [ruby_version]\n"
23
+ println "When running with out a ruby version, the full build is run for ruby versions:"
24
+ println "1.8.6\n1.8.7\n1.9.1\n1.9.2\njruby\n"
25
+ println "Else specify a particular ruby version to run the build against\n"
26
+ }
27
+
28
+
29
+ if [ -f "$HOME/.rvm/scripts/rvm" ]
30
+ then
31
+ source "$HOME/.rvm/scripts/rvm"
32
+ elif [ -f "/usr/local/rvm/scripts/rvm" ]
33
+ then
34
+ source "/usr/local/rvm/scripts/rvm"
35
+ else
36
+ println "${bold}RVM Not found"
37
+ println "I looked in $HOME/.rvm/scripts/rvm and /usr/local/rvm/scripts/rvm"
38
+ println "RVM must be installed to run this script. It's great! find out more: here ${bold}http://rvm.beginrescueend.com/"
39
+ println "Until it is installed simply run the default rake target to test Mirage against your active version of Ruby and installed gems"
40
+ exit 1
41
+ fi
42
+
43
+ while getopts ":h" opt; do
44
+ case $opt in
45
+ h)
46
+ usage
47
+ exit 0
48
+ ;;
49
+ \?)
50
+ println "Invalid option: -$OPTARG"
51
+ usage
52
+ exit 1
53
+ ;;
54
+ esac
55
+ done
56
+
57
+ message=""
58
+ result=true
59
+
60
+ run_build_for_ruby( ){
61
+ println "${green}Running build for: $1"
62
+
63
+ ruby_list=`rvm list`
64
+ if [[ ${ruby_list} == *$1* ]]
65
+ then
66
+ rvm --create $1@mirage
67
+ rvm --force gemset empty
68
+ [ -f Gemfile.lock ] && rm Gemfile.lock
69
+ gem install bundler
70
+ bundle install
71
+ rake
72
+
73
+ if [ $? == 0 ]
74
+ then
75
+ message="${message}${blue}$1: ${green}pass\n"
76
+ else
77
+ message="${message}${blue}$1: ${red}fail\n"
78
+ result=false
79
+ fi
80
+ else
81
+ message="${message}${blue}$1: ${yellow}Not installed\n"
82
+ result=false
83
+ fi
84
+ }
85
+
86
+ if [ $1 ]
87
+ then
88
+ run_build_for_ruby $1
89
+ else
90
+ run_build_for_ruby 'ruby-1.8.6'
91
+ run_build_for_ruby 'ruby-1.8.7'
92
+ run_build_for_ruby 'ruby-1.9.1-p378'
93
+ run_build_for_ruby 'ruby-1.9.2'
94
+ run_build_for_ruby 'jruby'
95
+ fi
96
+
97
+ println "\n\n${message}"
98
+ print "${white}Result: "
99
+ [ ${result} == true ] && println "${green}Pass\n" || println "${red}Fail\n"
100
+
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}"
2
+ require 'client/template'
3
+ require 'client/error'
4
+ require 'client/cli_bridge'
5
+ require 'client/runner'
6
+ require 'client/template'
7
+ require 'client/templates'
8
+ require 'client/requests'
9
+ require 'client/request'
10
+ require 'client/client'
@@ -0,0 +1,30 @@
1
+ module Mirage
2
+ module CLIBridge
3
+ def mirage_process_ids ports
4
+ mirage_instances = {}
5
+ ["Mirage Server", "mirage_server", "mirage server"].each do |process_name|
6
+ processes_with_name(process_name).each_line.collect { |line| line.chomp }.each do |process_line|
7
+ pid = process_line.split(' ')[1]
8
+ port = process_line[/port (\d+)/, 1]
9
+ mirage_instances[port] = pid
10
+ end
11
+ end
12
+
13
+ return mirage_instances if ports.first.to_s == "all" || ports.empty?
14
+ Hash[mirage_instances.find_all { |port, pid| ports.include?(port.to_i) }]
15
+ end
16
+
17
+ def kill pid
18
+ ChildProcess.windows? ? `taskkill /F /T /PID #{pid}` : `kill -9 #{pid}`
19
+ end
20
+
21
+ def processes_with_name name
22
+ if ChildProcess.windows?
23
+ `tasklist /V | findstr "#{name.gsub(" ", '\\ ')}"`
24
+ else
25
+ IO.popen("ps aux | grep '#{name}' | grep -v grep | grep -v #{$$}")
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,73 @@
1
+ require 'uri'
2
+ require 'httparty'
3
+ require 'base64'
4
+ require 'json'
5
+
6
+ module Mirage
7
+ class Client
8
+ include HTTParty
9
+
10
+ attr_reader :url
11
+
12
+ def initialize options={:url => "http://localhost:7001"}, &block
13
+ if options.is_a?(String) && options =~ URI.regexp
14
+ @url = options
15
+ elsif options.kind_of?(Hash) && options[:port]
16
+ @url = "http://localhost:#{options[:port]}"
17
+ elsif options.kind_of?(Hash) && options[:url]
18
+ @url = options[:url]
19
+ else
20
+ raise "specify a valid URL or port"
21
+ end
22
+
23
+ @templates = Templates.new(@url)
24
+ @templates.default_config &block if block
25
+ end
26
+
27
+ def configure &block
28
+ templates.default_config &block if block
29
+ end
30
+
31
+ def reset
32
+ templates.default_config.reset
33
+ end
34
+
35
+ def templates id=nil
36
+ return Template.get("#{@url}/templates/#{id}") if id
37
+ @templates
38
+ end
39
+
40
+ def requests id=nil
41
+ return Request.get "#{@url}/requests/#{id}" if id
42
+ Requests.new(@url)
43
+ end
44
+
45
+ def prime
46
+ self.class.send(:put, "#{@url}/defaults", :body => "")
47
+ end
48
+
49
+ def save
50
+ self.class.send(:put, "#{@url}/backup", :body => "")
51
+ end
52
+
53
+ def revert
54
+ self.class.send(:put, @url, :body => "")
55
+ end
56
+
57
+ def put *args, &block
58
+ templates.put *args, &block
59
+ end
60
+
61
+ def clear
62
+ templates.delete_all
63
+ end
64
+
65
+ def == client
66
+ client.instance_of?(Client) && self.url == client.url
67
+ end
68
+
69
+ def running?
70
+ Mirage.running? @url
71
+ end
72
+ end
73
+ end