gcr 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/lib/gcr.rb +85 -0
  3. data/lib/gcr/cassette.rb +105 -0
  4. metadata +105 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 654092852f61d95659958cc4b7bdc57863d92474
4
+ data.tar.gz: 1475ecc16fb24ca8c8b69e63ff5ff63fcfc3cbea
5
+ SHA512:
6
+ metadata.gz: 14a2b562b9238808de93eea48fbb2ced1cf8a5ba0d52b1c8bdb009f1bcf38179c5387d29a57be9c1ab4efca4efd99e99ed4f60b7c86e3909d681703fce8f5f95
7
+ data.tar.gz: 8b8a4c32de38ba8dffa4801db17076617e8763080825e4b7e4942531490adbcde99f9a69f4fe99389836ed502969f32d3992ce4883f7d9dd09d02ac2fbc6bdb8
@@ -0,0 +1,85 @@
1
+ module GCR
2
+ Error = Class.new(StandardError)
3
+ ConfigError = Class.new(Error)
4
+ RunningError = Class.new(Error)
5
+ NoRecording = Class.new(Error)
6
+
7
+ # Specify where GCR should store cassettes.
8
+ #
9
+ # path - The String path to a directory.
10
+ #
11
+ # Returns nothing.
12
+ def cassette_dir=(path)
13
+ raise RunningError, "cannot configure GCR within #with_cassette block" if @running
14
+ @cassette_dir = path
15
+ end
16
+
17
+ # Where GCR stores cassettes.
18
+ #
19
+ # Returns a String path to a directory. Raises ConfigError if not configured.
20
+ def cassette_dir
21
+ @cassette_dir || (raise ConfigError, "no cassette dir configured")
22
+ end
23
+
24
+ # Specify the stub to intercept calls to.
25
+ #
26
+ # stub - A GRPC::ClientStub instance.
27
+ #
28
+ # Returns nothing.
29
+ def stub=(stub)
30
+ raise RunningError, "cannot configure GCR within #with_cassette block" if @running
31
+ @stub = stub
32
+ end
33
+
34
+ # The stub that is being mocked.
35
+ #
36
+ # Returns a A GRPC::ClientStub instance. Raises ConfigError if not configured.
37
+ def stub
38
+ @stub || (raise ConfigError, "no cassette dir configured")
39
+ end
40
+
41
+ def cassette
42
+ @cassette
43
+ end
44
+
45
+ # If a cassette with the given name exists, play that cassette for the
46
+ # provided block. Otherwise, record a cassette with the provided block.
47
+ #
48
+ # Returns nothing.
49
+ def with_cassette(name, &blk)
50
+ @cassette = Cassette.new(name)
51
+ if @cassette.exist?
52
+ @cassette.play(&blk)
53
+ else
54
+ @cassette.record(&blk)
55
+ end
56
+ ensure
57
+ @cassette = nil
58
+ end
59
+
60
+ def serialize_request(route, req, marshal, unmarshal, metadata)
61
+ JSON.dump(
62
+ "route" => route,
63
+ "req" => Base64.strict_encode64(req.to_proto)
64
+ )
65
+ end
66
+
67
+ def serialize_response(resp)
68
+ JSON.dump(
69
+ "type" => resp.class.name,
70
+ "buf" => Base64.strict_encode64(resp.to_proto)
71
+ )
72
+ end
73
+
74
+ def deserialize_response(str)
75
+ hsh = JSON.parse(str)
76
+ klass = Google::Protobuf::DescriptorPool.generated_pool.lookup(hsh["type"]).msgclass
77
+ klass.decode(Base64.strict_decode64(hsh["buf"]))
78
+ end
79
+
80
+ extend self
81
+ end
82
+
83
+ require "json"
84
+ require "base64"
85
+ require "gcr/cassette"
@@ -0,0 +1,105 @@
1
+ class GCR::Cassette
2
+ attr_reader :data
3
+
4
+ # Delete all recorded cassettes.
5
+ #
6
+ # Returns nothing.
7
+ def self.delete_all
8
+ Dir[File.join(GCR.cassette_dir, "*.json")].each do |path|
9
+ File.unlink(path)
10
+ end
11
+ end
12
+
13
+ # Initialize a new cassette.
14
+ #
15
+ # name - The String name of the recording, from which the path is derived.
16
+ #
17
+ # Returns nothing.
18
+ def initialize(name)
19
+ @path = File.join(GCR.cassette_dir, "#{name}.json")
20
+ @data = {}
21
+ end
22
+
23
+ # Does this cassette exist?
24
+ #
25
+ # Returns boolean.
26
+ def exist?
27
+ File.exist?(@path)
28
+ end
29
+
30
+ # Load this cassette.
31
+ #
32
+ # Returns nothing.
33
+ def load
34
+ @data = JSON.parse(File.read(@path))
35
+ end
36
+
37
+ # Persist this cassette.
38
+ #
39
+ # Returns nothing.
40
+ def save
41
+ File.open(@path, "w") do |f|
42
+ f.write(JSON.pretty_generate(data))
43
+ end
44
+ end
45
+
46
+ # Record all GRPC calls made while calling the provided block.
47
+ #
48
+ # Returns nothing.
49
+ def record(&blk)
50
+ install_record_hook
51
+ blk.call
52
+ save
53
+ ensure
54
+ remove_hook
55
+ end
56
+
57
+ # Play recorded GRPC responses.
58
+ #
59
+ # Returns nothing.
60
+ def play(&blk)
61
+ load
62
+ install_play_hook
63
+ blk.call
64
+ ensure
65
+ remove_hook
66
+ end
67
+
68
+ private
69
+
70
+ def install_record_hook
71
+ GCR.stub.class.class_eval do
72
+ alias_method :orig_request_response, :request_response
73
+
74
+ def request_response(*args)
75
+ orig_request_response(*args).tap do |resp|
76
+ key = GCR.serialize_request(*args)
77
+ GCR.cassette.data[key] ||= []
78
+ GCR.cassette.data[key] << GCR.serialize_response(resp)
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def install_play_hook
85
+ GCR.stub.class.class_eval do
86
+ alias_method :orig_request_response, :request_response
87
+
88
+ def request_response(*args)
89
+ key = GCR.serialize_request(*args)
90
+ GCR.cassette.data[key] ||= []
91
+ if resp = GCR.cassette.data[key].shift
92
+ GCR.deserialize_response(resp)
93
+ else
94
+ raise GCR::NoRecording
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ def remove_hook
101
+ GCR.stub.class.class_eval do
102
+ alias_method :request_response, :orig_request_response
103
+ end
104
+ end
105
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gcr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - mastahyeti
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: google-protobuf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 3.3.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '3.3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 3.3.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: grpc
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.2'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.2.5
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.2'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.2.5
53
+ - !ruby/object:Gem::Dependency
54
+ name: rspec
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.5'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 3.5.0
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.5'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 3.5.0
73
+ description:
74
+ email:
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - "./lib/gcr.rb"
80
+ - "./lib/gcr/cassette.rb"
81
+ homepage: https://github.com/mastahyeti/gcr
82
+ licenses:
83
+ - MIT
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.5.2
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: GRPC test helpers
105
+ test_files: []