dtracer 0.0.1

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: 35633957f1d2837f8e43d24ad211683ebb434dee
4
+ data.tar.gz: fe3d29ee7ff8ead9e2f3da297bb3649fb8c371ae
5
+ SHA512:
6
+ metadata.gz: 348da84583a7df13c9cc386147b99b241470b273fd6a49aae8b9e06db25b6b02328ffa4d0907cb9537870f462972aedd435113059992d5efc19167eda2f7a662
7
+ data.tar.gz: e1d2210e72e66253d3be0aa5a3bcfd5b98d99355ae37bd4f7eecf5b8e52ae078fe725e625228ee00b7c2e417e5429010ad756f3d3a88b9406af5ce6bbe57578e
@@ -0,0 +1,101 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ # Created by https://www.gitignore.io
16
+
17
+ ### RubyMine ###
18
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
19
+
20
+ *.iml
21
+
22
+ ## Directory-based project format:
23
+ .idea/
24
+ # if you remove the above rule, at least ignore the following:
25
+
26
+ # User-specific stuff:
27
+ # .idea/workspace.xml
28
+ # .idea/tasks.xml
29
+ # .idea/dictionaries
30
+
31
+ # Sensitive or high-churn files:
32
+ # .idea/dataSources.ids
33
+ # .idea/dataSources.xml
34
+ # .idea/sqlDataSources.xml
35
+ # .idea/dynamic.xml
36
+ # .idea/uiDesigner.xml
37
+
38
+ # Gradle:
39
+ # .idea/gradle.xml
40
+ # .idea/libraries
41
+
42
+ # Mongo Explorer plugin:
43
+ # .idea/mongoSettings.xml
44
+
45
+ ## File-based project format:
46
+ *.ipr
47
+ *.iws
48
+
49
+ ## Plugin-specific files:
50
+
51
+ # IntelliJ
52
+ out/
53
+
54
+ # mpeltonen/sbt-idea plugin
55
+ .idea_modules/
56
+
57
+ # JIRA plugin
58
+ atlassian-ide-plugin.xml
59
+
60
+ # Crashlytics plugin (for Android Studio and IntelliJ)
61
+ com_crashlytics_export_strings.xml
62
+ crashlytics.properties
63
+ crashlytics-build.properties
64
+
65
+
66
+ ### Ruby ###
67
+ *.gem
68
+ *.rbc
69
+ /.config
70
+ /coverage/
71
+ /InstalledFiles
72
+ /pkg/
73
+ /spec/reports/
74
+ /test/tmp/
75
+ /test/version_tmp/
76
+ /tmp/
77
+
78
+ ## Specific to RubyMotion:
79
+ .dat*
80
+ .repl_history
81
+ build/
82
+
83
+ ## Documentation cache and generated files:
84
+ /.yardoc/
85
+ /_yardoc/
86
+ /doc/
87
+ /rdoc/
88
+
89
+ ## Environment normalisation:
90
+ /.bundle/
91
+ /lib/bundler/man/
92
+
93
+ # for a library or gem, you might want to ignore these files since the code is
94
+ # intended to run in multiple environments; otherwise, check them in:
95
+ # Gemfile.lock
96
+ # .ruby-version
97
+ # .ruby-gemset
98
+
99
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
100
+ .rvmrc
101
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dtracer.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Omar Abdelhafith
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,67 @@
1
+ # DTracer
2
+
3
+ DTracer is part ruby gem, part iOS pod, that helps the sending and receiving of DTrace commands.
4
+ The `dtracer` gem will listen to the DTrace commands that are sent from the [OADTraceSender]() pod.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'dtracer'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install dtracer
21
+
22
+ ## Usage
23
+
24
+ 1. Incorporate the `OADTraceSender` in your iOS project ([how to?]())
25
+ 2. Use `OADTraceSender` in your iOS app, to send a dtrace command.
26
+ 3. Run the iOS app to register the probes.
27
+ 4. Use `dtracer` gem command line to register a probe.
28
+
29
+ Any dtrace command you send will be received on your terminal.
30
+
31
+ Note: registering a probe using DTrace requires admin privileges, running any dtracer command will ask for that.
32
+
33
+ ### Type of probes
34
+
35
+ One good usage of DTrace is to log the network communicate instead of polluting the Xcode console.
36
+
37
+ Using DTrace to log network communication has the following benefits:
38
+ - Avoids Xcode console pollution with network logs.
39
+ - Extremely cheap; probes that are not being listened do not add any overhead.
40
+
41
+ To check how to implement OADtraceSender in your iOS project, check [OADtraceSender pod]().
42
+
43
+ Using `dtracer` command you can register 3 types of tracers.
44
+
45
+ #### Request probes
46
+ These are probes that listens to dtrace command sent from `[OADTracer traceRequest:]` objc method.
47
+ - `tracer curl`: outputs the the `NSURLRequest` send with the dtrace event as a curl command.
48
+ - `tracer details`: outputs the the `NSURLRequest` send with the dtrace event as a formatted string. You can pass it multiple flags to decide what to print from the request.
49
+
50
+ Using the `-r` flag with both of the above will add a response probe tee.
51
+
52
+ #### Response probes
53
+ `dtracer response` adds a probe that outputs the `NSURLResponse`, `NSData` and `NSError` combination, sent using `[OADTracer traceResponse:data:error:]` objc method.
54
+
55
+ #### String probes
56
+ In case you have the need to send any arbitrary string, then use `dtracer custom`; This command adds a probe that prints any string sent using `[OADTracer traceString:]` objc method.
57
+
58
+ ## Contributing
59
+
60
+ 1. Fork it ( https://github.com/oarrabi/dtracer/fork )
61
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
62
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
63
+ 4. Push to the branch (`git push origin my-new-feature`)
64
+ 5. Create a new Pull Request
65
+
66
+ ## Tests
67
+ [Yes! ](https://github.com/oarrabi/dtracer/tree/master/spec)
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new :test do |task|
5
+ task.verbose = false
6
+ task.rspec_opts = ['--color', '--format', 'doc']
7
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dtracer/cli'
4
+
5
+ DTracer::CLI.start
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dtracer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dtracer"
8
+ spec.version = DTracer::VERSION
9
+ spec.authors = ["Omar Abdelhafith"]
10
+ spec.email = ["o.arrabi@me.com"]
11
+ spec.summary = %q{DTracer is part ruby gem, part iOS pod, that helps the sending and receiving of DTrace commands..}
12
+ spec.description = %q{DTracer is part ruby gem, part iOS pod, that helps the sending and receiving of DTrace commands.
13
+ The `dtracer` gem will listen to the DTrace commands that are sent from the [OADTraceSender]() pod.}
14
+ spec.homepage = "http://nsomar.com/dtracer"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec"
25
+ spec.add_dependency "thor"
26
+ end
@@ -0,0 +1,4 @@
1
+ require "dtracer/version"
2
+ require "dtracer/probe_listener"
3
+ require "dtracer/request_formatters"
4
+ require "dtracer/response_formatters"
@@ -0,0 +1,43 @@
1
+ class DTracer::Builder
2
+
3
+ def initialize
4
+ @content = []
5
+ end
6
+
7
+ def add_options(is_quite, string_size = 102400)
8
+ @content << "#pragma D option quiet" if is_quite
9
+ @content << "#pragma D option strsize=#{string_size}"
10
+ @content << ''
11
+ end
12
+
13
+ def add_begin_probe
14
+ @content << 'BEGIN {'
15
+ @content << ' printf("Tracing started\n");'
16
+ @content << '}'
17
+ @content << ''
18
+ end
19
+
20
+ def add_request_probe
21
+ add_probe("request")
22
+ end
23
+
24
+ def add_response_probe
25
+ add_probe("response")
26
+ end
27
+
28
+ def add_custom_probe
29
+ add_probe("custom")
30
+ end
31
+
32
+ def build
33
+ @content.join("\n")
34
+ end
35
+
36
+ def add_probe(probe_type)
37
+ @content << "oadprobe*:::#{probe_type} {"
38
+ @content << ' printf("%s\n\n", copyinstr(arg0));'
39
+ @content << '}'
40
+ @content << ''
41
+ end
42
+
43
+ end
@@ -0,0 +1,105 @@
1
+ require 'thor'
2
+ require 'dtracer'
3
+ require 'tempfile'
4
+ require 'json'
5
+
6
+ class DTracer::CLI < Thor
7
+ package_name :dtracer
8
+
9
+ option :r, :aliases => ["--response"], :type => :boolean, desc: "include the request response"
10
+ desc "curl", "register a curl probe"
11
+
12
+ def curl
13
+ say "Starting dtrace", :green
14
+
15
+ t1 = Thread.new do
16
+ ProbeListener.new("request", true).listen do |hash|
17
+ puts RequestCurlFormatter.new(hash).to_s
18
+ end
19
+ end
20
+
21
+ t2 = Thread.new do
22
+ sleep(0.3)
23
+ add_response_probe if options[:r]
24
+ end
25
+
26
+ t1.join
27
+ t2.join
28
+
29
+ rescue Exception => ex
30
+ say ex.message, :red
31
+ end
32
+
33
+ option :b, :aliases => ["--body"], :type => :boolean, desc: "show the http body"
34
+ option :m, :aliases => ["--method"], :type => :boolean, desc: "show the http method"
35
+ option :u, :aliases => ["--url"], :type => :boolean, desc: "show the http url"
36
+ option :h, :aliases => ["--headers"], :type => :boolean, desc: "show the http url"
37
+ option :c, :aliases => ["--cookies"], :type => :boolean, desc: "show the http url"
38
+ option :q, :aliases => ["--quiet"], :type => :boolean, desc: "show the http url"
39
+ option :r, :aliases => ["--response"], :type => :boolean, desc: "include the request response"
40
+ desc "details", "register a curl probe"
41
+
42
+ def details
43
+ options_without_response = options.dup
44
+ options_without_response.delete(:r)
45
+
46
+ raise "Select any option from -b, -c, -h, -u (you can combine them for more info)" if options_without_response.empty?
47
+
48
+ say "Starting dtrace", :green
49
+
50
+ t1 = Thread.new do
51
+ ProbeListener.new("request", true).listen do |hash|
52
+ puts RequestDetailsFormatter.new(hash, options || {}).to_s
53
+ end
54
+ end
55
+
56
+ t2 = Thread.new do
57
+ sleep(0.3)
58
+ add_response_probe if options[:r]
59
+ end
60
+
61
+ t1.join
62
+ t2.join
63
+
64
+ rescue Exception => ex
65
+ say ex.message, :red
66
+ end
67
+
68
+ desc "response", "register a custom probe"
69
+
70
+ def response
71
+ say "Starting dtrace", :green
72
+
73
+ add_response_probe
74
+
75
+ rescue Exception => ex
76
+ say ex.message, :red
77
+ end
78
+
79
+ desc "custom", "register a custom probe"
80
+
81
+ def custom
82
+ say "Starting dtrace", :green
83
+
84
+ probe = ProbeListener.new("custom", false)
85
+
86
+ probe.listen do |string|
87
+ puts string
88
+ end
89
+
90
+ rescue Exception => ex
91
+ say ex.message, :red
92
+ end
93
+
94
+
95
+ private
96
+
97
+ def add_response_probe
98
+ probe = ProbeListener.new("response", true)
99
+ probe.listen do |hash|
100
+ formatter = ResponseFormatter.new(hash)
101
+ puts formatter.to_s
102
+ end
103
+ end
104
+
105
+ end
@@ -0,0 +1,66 @@
1
+ require "open3"
2
+
3
+ class ProbeListener
4
+
5
+ def initialize(name, is_hash)
6
+ @name = name
7
+ @probe_string = probe_string(name)
8
+ @is_hash = is_hash
9
+ end
10
+
11
+ def listen
12
+ write_probe
13
+ cmd = "sudo dtrace -s #{trace_file_path}"
14
+
15
+ IO.popen(cmd) do |stdout|
16
+ stdout.each do |line|
17
+
18
+ if @is_hash
19
+ value = try_parse(line)
20
+ next unless value
21
+ else
22
+ value = line.strip
23
+ next if value.empty?
24
+ end
25
+
26
+ puts "\n#{@name.capitalize}----------------------------------------------"
27
+ yield(value)
28
+ end
29
+ end
30
+
31
+ clean_up
32
+ end
33
+
34
+ private
35
+
36
+ def try_parse(string)
37
+ JSON.parse(string)
38
+ rescue
39
+ nil
40
+ end
41
+
42
+ def probe_string(name)
43
+ builder = DTracer::Builder.new
44
+ builder.add_options(true)
45
+
46
+ builder.add_begin_probe
47
+ builder.add_probe(name)
48
+ builder.build
49
+ end
50
+
51
+ def write_probe
52
+ @file = Tempfile.new('temp.d')
53
+ @file.write(@probe_string)
54
+ @file.flush
55
+ end
56
+
57
+ def clean_up
58
+ @file.unlink
59
+ @file.close
60
+ end
61
+
62
+ def trace_file_path
63
+ @file.path
64
+ end
65
+
66
+ end
@@ -0,0 +1,115 @@
1
+ module RequestFormattable
2
+
3
+ def initialize(hash)
4
+ @hash = hash
5
+ generate
6
+ end
7
+
8
+ def to_s
9
+ @content
10
+ end
11
+
12
+ def generate
13
+ arr = []
14
+
15
+ methods = [:begin_section, :method_section, :body_section,
16
+ :cookie_section, :header_section, :url_section]
17
+
18
+ methods.each do |method_name|
19
+ # get content array for a request section
20
+ content_array = self.send(method_name, @hash)
21
+ arr.concat(content_array) if content_array
22
+
23
+ end
24
+
25
+ @content = arr.join(joining_string)
26
+ end
27
+
28
+ end
29
+
30
+ class RequestCurlFormatter
31
+
32
+ include RequestFormattable
33
+
34
+ def joining_string
35
+ " \\ \n"
36
+ end
37
+
38
+ def begin_section(_)
39
+ ["curl"]
40
+ end
41
+
42
+ def method_section(hash)
43
+ ["-X #{hash["method"]}"]
44
+ end
45
+
46
+ def url_section(hash)
47
+ ["\"#{hash["url"]}\""]
48
+ end
49
+
50
+ def header_section(hash)
51
+ return nil unless hash["headers"]
52
+
53
+ hash["headers"].map { |key, value| "-H '#{key}: #{value}'" }
54
+ end
55
+
56
+ def cookie_section(hash)
57
+ return nil unless hash["cookies"]
58
+
59
+ hash["cookies"].map { |name, value| "--cookie \"#{name}=#{value}\"" }
60
+ end
61
+
62
+ def body_section(hash)
63
+ return nil unless hash["body"]
64
+
65
+ ["-d #{hash["body"]}"]
66
+ end
67
+
68
+ end
69
+
70
+ class RequestDetailsFormatter
71
+
72
+ include RequestFormattable
73
+
74
+ def initialize(hash, options)
75
+ @options = options
76
+ super(hash)
77
+ end
78
+
79
+ def joining_string
80
+ "\n"
81
+ end
82
+
83
+ def begin_section(_)
84
+ []
85
+ end
86
+
87
+ def method_section(hash)
88
+ return nil unless @options[:m] && hash["method"]
89
+
90
+ ["Method:\n #{hash["method"]}"]
91
+ end
92
+
93
+ def url_section(hash)
94
+ return nil unless @options[:u] && hash["url"]
95
+ ["URL:\n #{hash["url"]}"]
96
+ end
97
+
98
+ def header_section(hash)
99
+ return nil unless @options[:h] && hash["headers"]
100
+
101
+ hash["headers"].map { |key, value| " #{key}: #{value}" }.insert(0, "Headers:")
102
+ end
103
+
104
+ def cookie_section(hash)
105
+ return nil unless @options[:c] && hash["cookies"]
106
+
107
+ hash["cookies"].map { |name, value| " #{name}: #{value}" }.insert(0, "Cookies:")
108
+ end
109
+
110
+ def body_section(hash)
111
+ return nil unless @options[:b] && hash["body"]
112
+ ["Body:\n #{hash["body"]}"]
113
+ end
114
+
115
+ end
@@ -0,0 +1,70 @@
1
+ class ResponseFormatter
2
+
3
+ def initialize(hash)
4
+ @hash = hash
5
+ generate
6
+ end
7
+
8
+ def generate
9
+ arr = []
10
+
11
+ methods = [:response_section, :header_section, :cookie_section, :body_section, :error_section]
12
+
13
+ methods.each do |method_name|
14
+ # get content array for a request section
15
+ content_array = self.send(method_name, @hash)
16
+ arr.concat(content_array) if content_array
17
+
18
+ end
19
+
20
+ @content = arr.join("\n")
21
+ end
22
+
23
+ def response_section(hash)
24
+ arr = []
25
+
26
+ if hash["statusCode"]
27
+ arr << "Status Code:"
28
+ arr << " #{hash["statusCode"]}"
29
+ end
30
+
31
+ if hash["url"]
32
+ arr << "URL:"
33
+ arr << " #{hash["url"]}"
34
+ end
35
+
36
+ arr
37
+ end
38
+
39
+ def header_section(hash)
40
+ return nil unless hash["headers"]
41
+
42
+ hash["headers"].map { |key, value| " #{key}: #{value}" }.insert(0, "Headers:")
43
+ end
44
+
45
+ def cookie_section(hash)
46
+ return nil unless hash["cookies"]
47
+
48
+ hash["cookies"].map { |name, value| " #{name}: #{value}" }.insert(0, "Cookies:")
49
+ end
50
+
51
+ def body_section(hash)
52
+ return nil unless hash["body"]
53
+
54
+ ["Body:\n #{hash["body"]}"]
55
+ end
56
+
57
+ def error_section(hash)
58
+ return nil unless hash["error"]
59
+ arr = []
60
+ arr << "Error:"
61
+ arr << " Error Code: #{hash["error"]["errorCode"]}"
62
+ arr << " Description: #{hash["error"]["localizedDescription"]}"
63
+ arr
64
+ end
65
+
66
+ def to_s
67
+ @content
68
+ end
69
+
70
+ end
@@ -0,0 +1,3 @@
1
+ module DTracer
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,45 @@
1
+ require 'rspec'
2
+ require 'dtracer/builder'
3
+
4
+
5
+ describe DTracer::Builder do
6
+ before(:each) do
7
+
8
+ end
9
+
10
+ it "should add options" do
11
+ b = DTracer::Builder.new
12
+ b.add_options(true)
13
+
14
+ expect(b.build).to eq "#pragma D option quiet\n#pragma D option strsize=102400\n"
15
+ end
16
+
17
+ it "should add begin probe" do
18
+ b = DTracer::Builder.new
19
+ b.add_begin_probe
20
+
21
+ expect(b.build).to eq "BEGIN {\n printf(\"Tracing started\\n\");\n}\n"
22
+ end
23
+
24
+ it "should add request probe" do
25
+ b = DTracer::Builder.new
26
+ b.add_request_probe
27
+
28
+ expect(b.build).to eq "oadprobe*:::request {\n printf(\"%s\\n\\n\", copyinstr(arg0));\n}\n"
29
+ end
30
+
31
+ it "should add response probe" do
32
+ b = DTracer::Builder.new
33
+ b.add_response_probe
34
+
35
+ expect(b.build).to eq "oadprobe*:::response {\n printf(\"%s\\n\\n\", copyinstr(arg0));\n}\n"
36
+ end
37
+
38
+ it "should add custom probe" do
39
+ b = DTracer::Builder.new
40
+ b.add_custom_probe
41
+
42
+ expect(b.build).to eq "oadprobe*:::custom {\n printf(\"%s\\n\\n\", copyinstr(arg0));\n}\n"
43
+ end
44
+
45
+ end
@@ -0,0 +1,117 @@
1
+ require 'rspec'
2
+ require 'dtracer/request_formatters'
3
+
4
+ describe 'RequestCurlFormatter' do
5
+
6
+ it 'should correctly convert method and url' do
7
+ f = RequestCurlFormatter.new(HASH_WITHOUT_BODY)
8
+ expect(f.to_s).to eq(CURL_WITHOUT_BODY)
9
+ end
10
+
11
+ it 'should correctly convert the http body' do
12
+ f = RequestCurlFormatter.new(HASH_WITH_BODY)
13
+ expect(f.to_s).to eq(CURL_WITH_BODY)
14
+ end
15
+
16
+ it 'should correctly convert the headers' do
17
+ f = RequestCurlFormatter.new(HASH_WITH_HEADERS)
18
+ expect(f.to_s).to eq(CURL_WITH_HEADER)
19
+ end
20
+
21
+ it 'should correctly convert http with body and cookies' do
22
+ f = RequestCurlFormatter.new(HASH_WITH_BODY_AND_COOKIES)
23
+ expect(f.to_s).to eq(CURL_WITH_BODY_AND_COOKIES)
24
+ end
25
+
26
+ it 'should correctly convert http with body header and cookies' do
27
+ f = RequestCurlFormatter.new(HASH_WITH_BODY_HEADER_AND_COOKIES)
28
+ expect(f.to_s).to eq(CURL_WITH_BODY_HEADER_AND_COOKIES)
29
+ end
30
+
31
+ end
32
+
33
+ ALL_OPTIONS = {:m => true, :b => true, :c => true, :h => true, :u => true}
34
+ describe 'RequestDetailsFormatter' do
35
+
36
+ it 'should correctly convert method and url' do
37
+ f = RequestDetailsFormatter.new(HASH_WITHOUT_BODY, ALL_OPTIONS)
38
+ expect(f.to_s).to eq(DETAIL_WITHOUT_BODY)
39
+ end
40
+
41
+ it 'should correctly convert the http body' do
42
+ f = RequestDetailsFormatter.new(HASH_WITH_BODY, ALL_OPTIONS)
43
+ expect(f.to_s).to eq(DETAIL_WITH_BODY)
44
+ end
45
+
46
+ it 'should correctly convert the headers' do
47
+ f = RequestDetailsFormatter.new(HASH_WITH_HEADERS, ALL_OPTIONS)
48
+ expect(f.to_s).to eq(DETAIL_WITH_HEADER)
49
+ end
50
+
51
+ it 'should correctly convert http with body and cookies' do
52
+ f = RequestDetailsFormatter.new(HASH_WITH_BODY_AND_COOKIES, ALL_OPTIONS)
53
+ expect(f.to_s).to eq(DETAIL_WITH_BODY_AND_COOKIES)
54
+ end
55
+
56
+ it 'should correctly convert http with body header and cookies' do
57
+ f = RequestDetailsFormatter.new(HASH_WITH_BODY_HEADER_AND_COOKIES, ALL_OPTIONS)
58
+ expect(f.to_s).to eq(DETAIL_WITH_BODY_HEADER_AND_COOKIES)
59
+ end
60
+
61
+ context 'Parsing options' do
62
+
63
+ it 'should display only method when m is passed' do
64
+ options = {:m => true}
65
+ f = RequestDetailsFormatter.new(HASH_WITH_BODY_HEADER_AND_COOKIES, options)
66
+ expect(f.to_s).to eq("Method:\n POST")
67
+ end
68
+
69
+ it 'should display only body when b is passed' do
70
+ options = {:b => true}
71
+ f = RequestDetailsFormatter.new(HASH_WITH_BODY_HEADER_AND_COOKIES, options)
72
+ expect(f.to_s).to eq("Body:\n Body is test test")
73
+ end
74
+
75
+ it 'should display header and cookies when h and c are passed' do
76
+ options = {:c => true, :h => true}
77
+ f = RequestDetailsFormatter.new(HASH_WITH_BODY_HEADER_AND_COOKIES, options)
78
+ expect(f.to_s).to eq("Cookies:\n cookie1: v1\n cookie2: v2\nHeaders:\n k1: v1\n k2: v2")
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ # Mock data
86
+
87
+ HASH_WITHOUT_BODY =
88
+ {"url" => "https:\/\/www.google.com", "method" => "GET"}
89
+ HASH_WITH_BODY =
90
+ {"url" => "https:\/\/www.google.com", "method" => "POST",
91
+ "body" => "Body is test test"}
92
+ HASH_WITH_HEADERS =
93
+ {"url" => "https:\/\/www.google.com", "method" => "POST",
94
+ "headers" => {"k1" => "v1", "k2" => "v2"}}
95
+ HASH_WITH_BODY_AND_COOKIES =
96
+ {"url" => "https:\/\/www.google.com", "method" => "POST",
97
+ "body" => "Body is test test",
98
+ "cookies" => {"cookie1" => "v1", "cookie2" => "v2"}}
99
+ HASH_WITH_BODY_HEADER_AND_COOKIES =
100
+ {"url" => "https:\/\/www.google.com", "method" => "POST",
101
+ "body" => "Body is test test",
102
+ "cookies" => {"cookie1" => "v1", "cookie2" => "v2"},
103
+ "headers" => {"k1" => "v1", "k2" => "v2"}}
104
+
105
+
106
+ CURL_WITHOUT_BODY = "curl \\ \n-X GET \\ \n\"https://www.google.com\""
107
+ CURL_WITH_BODY = "curl \\ \n-X POST \\ \n-d Body is test test \\ \n\"https://www.google.com\""
108
+ CURL_WITH_HEADER = "curl \\ \n-X POST \\ \n-H 'k1: v1' \\ \n-H 'k2: v2' \\ \n\"https://www.google.com\""
109
+ CURL_WITH_BODY_AND_COOKIES = "curl \\ \n-X POST \\ \n-d Body is test test \\ \n--cookie \"cookie1=v1\" \\ \n--cookie \"cookie2=v2\" \\ \n\"https://www.google.com\""
110
+ CURL_WITH_BODY_HEADER_AND_COOKIES = "curl \\ \n-X POST \\ \n-d Body is test test \\ \n--cookie \"cookie1=v1\" \\ \n--cookie \"cookie2=v2\" \\ \n-H 'k1: v1' \\ \n-H 'k2: v2' \\ \n\"https://www.google.com\""
111
+
112
+
113
+ DETAIL_WITHOUT_BODY = "Method:\n GET\nURL:\n https://www.google.com"
114
+ DETAIL_WITH_BODY = "Method:\n POST\nBody:\n Body is test test\nURL:\n https://www.google.com"
115
+ DETAIL_WITH_HEADER = "Method:\n POST\nHeaders:\n k1: v1\n k2: v2\nURL:\n https://www.google.com"
116
+ DETAIL_WITH_BODY_AND_COOKIES = "Method:\n POST\nBody:\n Body is test test\nCookies:\n cookie1: v1\n cookie2: v2\nURL:\n https://www.google.com"
117
+ DETAIL_WITH_BODY_HEADER_AND_COOKIES = "Method:\n POST\nBody:\n Body is test test\nCookies:\n cookie1: v1\n cookie2: v2\nHeaders:\n k1: v1\n k2: v2\nURL:\n https://www.google.com"
@@ -0,0 +1,68 @@
1
+ require 'rspec'
2
+ require 'dtracer/response_formatters'
3
+
4
+ describe 'ResponseFormatter' do
5
+
6
+ it 'should correctly convert the http response with status' do
7
+ f = ResponseFormatter.new(HASH_WITH_STATUS)
8
+ expect(f.to_s).to eq(RESPONSE_WITH_STATUS)
9
+ end
10
+
11
+ it 'should correctly convert the http response with status and headers' do
12
+ f = ResponseFormatter.new(HASH_WITH_STATUS_HEADERS)
13
+ expect(f.to_s).to eq(RESPONSE_WITH_STATUS_HEADERS)
14
+ end
15
+
16
+ it 'should correctly convert the http response with status headers and body' do
17
+ f = ResponseFormatter.new(HASH_WITH_STATUS_HEADERS_BODY)
18
+ expect(f.to_s).to eq(RESPONSE_WITH_STATUS_HEADERS_BODY)
19
+ end
20
+
21
+ it 'should correctly convert the http response with errors' do
22
+ f = ResponseFormatter.new(HASH_WITH_ERROR)
23
+ expect(f.to_s).to eq(RESPONSE_WITH_ERROR)
24
+ end
25
+
26
+ it 'should correctly convert the http response with errors and body' do
27
+ f = ResponseFormatter.new(HASH_WITH_ERROR_BODY)
28
+ expect(f.to_s).to eq(RESPONSE_WITH_ERROR_BODY)
29
+ end
30
+
31
+ it 'should correctly convert the http response with errors body and headers' do
32
+ f = ResponseFormatter.new(HASH_WITH_ERROR_BODY_HEADER)
33
+ expect(f.to_s).to eq(RESPONSE_WITH_ERROR_BODY_HEADER)
34
+ end
35
+
36
+ end
37
+
38
+ HASH_WITH_STATUS =
39
+ {"statusCode" => "2", "url" => "http://google.com"}
40
+ HASH_WITH_STATUS_HEADERS =
41
+ {"statusCode" => "2", "url" => "http://google.com",
42
+ "cookies" => {"cookie1" => "v1", "cookie2" => "v2"},
43
+ "headers" => {"k1" => "v1", "k2" => "v2"}}
44
+ HASH_WITH_STATUS_HEADERS_BODY =
45
+ {"statusCode" => "2", "url" => "http://google.com",
46
+ "cookies" => {"cookie1" => "v1", "cookie2" => "v2"},
47
+ "headers" => {"k1" => "v1", "k2" => "v2"},
48
+ "body" => "Some body"}
49
+ HASH_WITH_ERROR =
50
+ {"statusCode" => "500", "url" => "http://google.com",
51
+ "error" => {"errorCode" => "123", "localizedDescription" => "bad thing"}}
52
+ HASH_WITH_ERROR_BODY =
53
+ {"statusCode" => "500", "url" => "http://google.com",
54
+ "error" => {"errorCode" => "123", "localizedDescription" => "bad thing"},
55
+ "body" => "Some body"}
56
+ HASH_WITH_ERROR_BODY_HEADER =
57
+ {"statusCode" => "500", "url" => "http://google.com",
58
+ "error" => {"errorCode" => "123", "localizedDescription" => "bad thing"},
59
+ "headers" => {"k1" => "v1", "k2" => "v2"},
60
+ "body" => "Some body"}
61
+
62
+
63
+ RESPONSE_WITH_STATUS = "Status Code:\n 2\nURL:\n http://google.com"
64
+ RESPONSE_WITH_STATUS_HEADERS = "Status Code:\n 2\nURL:\n http://google.com\nHeaders:\n k1: v1\n k2: v2\nCookies:\n cookie1: v1\n cookie2: v2"
65
+ RESPONSE_WITH_STATUS_HEADERS_BODY = "Status Code:\n 2\nURL:\n http://google.com\nHeaders:\n k1: v1\n k2: v2\nCookies:\n cookie1: v1\n cookie2: v2\nBody:\n Some body"
66
+ RESPONSE_WITH_ERROR = "Status Code:\n 500\nURL:\n http://google.com\nError:\n Error Code: 123\n Description: bad thing"
67
+ RESPONSE_WITH_ERROR_BODY = "Status Code:\n 500\nURL:\n http://google.com\nBody:\n Some body\nError:\n Error Code: 123\n Description: bad thing"
68
+ RESPONSE_WITH_ERROR_BODY_HEADER = "Status Code:\n 500\nURL:\n http://google.com\nHeaders:\n k1: v1\n k2: v2\nBody:\n Some body\nError:\n Error Code: 123\n Description: bad thing"
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dtracer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Omar Abdelhafith
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-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.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
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
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: thor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: |-
70
+ DTracer is part ruby gem, part iOS pod, that helps the sending and receiving of DTrace commands.
71
+ The `dtracer` gem will listen to the DTrace commands that are sent from the [OADTraceSender]() pod.
72
+ email:
73
+ - o.arrabi@me.com
74
+ executables:
75
+ - dtracer
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - .gitignore
80
+ - Gemfile
81
+ - LICENSE.txt
82
+ - README.md
83
+ - Rakefile
84
+ - bin/dtracer
85
+ - dtracer.gemspec
86
+ - lib/dtracer.rb
87
+ - lib/dtracer/builder.rb
88
+ - lib/dtracer/cli.rb
89
+ - lib/dtracer/probe_listener.rb
90
+ - lib/dtracer/request_formatters.rb
91
+ - lib/dtracer/response_formatters.rb
92
+ - lib/dtracer/version.rb
93
+ - spec/builder_spec.rb
94
+ - spec/request_formatter_spec.rb
95
+ - spec/response_formatters_spec.rb
96
+ homepage: http://nsomar.com/dtracer
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.0.14
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: DTracer is part ruby gem, part iOS pod, that helps the sending and receiving
120
+ of DTrace commands..
121
+ test_files:
122
+ - spec/builder_spec.rb
123
+ - spec/request_formatter_spec.rb
124
+ - spec/response_formatters_spec.rb