gcr 0.0.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc8bcb870839377b9462083dd9bfba0799140c9c
4
- data.tar.gz: e273d0e31fb034dd00d63805c81595352c69f011
3
+ metadata.gz: a287464e10ba8e1c1fe77848e417c197ab79ebfb
4
+ data.tar.gz: d4131657599c3008bc8ac4c8f7b3ebafc382b5c7
5
5
  SHA512:
6
- metadata.gz: 51b729c8b9e0d87e4a85845dc4e7df93afa0264858703ad62bd946b96a307d7a739a10a5bc1f1fdcde7de915c58ce5cf32b745cc0b6d559fe2ed919c9e0c03b1
7
- data.tar.gz: c6085701a5c4ffdb6cc5156429acf6f7b39d6708430c5acc6cd7165c1a845011ec83cdef167b4548837fd2a8299c6bad94b159b79447033b6819010064df1b7c
6
+ metadata.gz: 207d6bb496e0a10a095763fb454ddef54002c1121fb4699b629161971b638f31e7f5128d81964bb6cb5bbee2c356c48fa6f2fdd7da734b70e795c36abd613e8d
7
+ data.tar.gz: '09403d61c03c953b111f0429a5f0a380c4948637cdf0ef06fce73f24c5e6b6c6a403e5af89fca34b284551eadc4345289a12f1381c438f1e76a03099f8525c35'
data/lib/gcr.rb CHANGED
@@ -1,9 +1,27 @@
1
+ require "json"
2
+
1
3
  module GCR
2
4
  Error = Class.new(StandardError)
3
5
  ConfigError = Class.new(Error)
4
6
  RunningError = Class.new(Error)
5
7
  NoRecording = Class.new(Error)
6
8
 
9
+ # Ignore these fields when matching requests.
10
+ #
11
+ # *fields - String field names (eg. "token").
12
+ #
13
+ # Returns nothing.
14
+ def ignore(*fields)
15
+ ignored_fields.concat(fields.map(&:to_s))
16
+ end
17
+
18
+ # Fields that are ignored when matching requests.
19
+ #
20
+ # Returns an Array of Strings.
21
+ def ignored_fields
22
+ @ignored_fields ||= []
23
+ end
24
+
7
25
  # Specify where GCR should store cassettes.
8
26
  #
9
27
  # path - The String path to a directory.
@@ -75,29 +93,9 @@ module GCR
75
93
  @cassette = nil
76
94
  end
77
95
 
78
- def serialize_request(route, req, marshal, unmarshal, metadata)
79
- JSON.dump(
80
- "route" => route,
81
- "req" => Base64.strict_encode64(req.to_proto)
82
- )
83
- end
84
-
85
- def serialize_response(resp)
86
- JSON.dump(
87
- "type" => resp.class.descriptor.name,
88
- "buf" => Base64.strict_encode64(resp.to_proto)
89
- )
90
- end
91
-
92
- def deserialize_response(str)
93
- hsh = JSON.parse(str)
94
- klass = Google::Protobuf::DescriptorPool.generated_pool.lookup(hsh["type"]).msgclass
95
- klass.decode(Base64.strict_decode64(hsh["buf"]))
96
- end
97
-
98
96
  extend self
99
97
  end
100
98
 
101
- require "json"
102
- require "base64"
103
99
  require "gcr/cassette"
100
+ require "gcr/request"
101
+ require "gcr/response"
@@ -1,5 +1,7 @@
1
1
  class GCR::Cassette
2
- attr_reader :data
2
+ VERSION = 2
3
+
4
+ attr_reader :reqs
3
5
 
4
6
  # Delete all recorded cassettes.
5
7
  #
@@ -17,7 +19,7 @@ class GCR::Cassette
17
19
  # Returns nothing.
18
20
  def initialize(name)
19
21
  @path = File.join(GCR.cassette_dir, "#{name}.json")
20
- @data = {}
22
+ @reqs = []
21
23
  end
22
24
 
23
25
  # Does this cassette exist?
@@ -31,7 +33,15 @@ class GCR::Cassette
31
33
  #
32
34
  # Returns nothing.
33
35
  def load
34
- @data = JSON.parse(File.read(@path))
36
+ data = JSON.parse(File.read(@path))
37
+
38
+ if data["version"] != VERSION
39
+ raise "GCR cassette version #{data["version"]} not supported"
40
+ end
41
+
42
+ @reqs = data["reqs"].map do |req, resp|
43
+ [GCR::Request.from_hash(req), GCR::Response.from_hash(resp)]
44
+ end
35
45
  end
36
46
 
37
47
  # Persist this cassette.
@@ -39,7 +49,10 @@ class GCR::Cassette
39
49
  # Returns nothing.
40
50
  def save
41
51
  File.open(@path, "w") do |f|
42
- f.write(JSON.pretty_generate(data))
52
+ f.write(JSON.pretty_generate(
53
+ "version" => VERSION,
54
+ "reqs" => reqs,
55
+ ))
43
56
  end
44
57
  end
45
58
 
@@ -69,8 +82,10 @@ class GCR::Cassette
69
82
 
70
83
  def request_response(*args)
71
84
  orig_request_response(*args).tap do |resp|
72
- key = GCR.serialize_request(*args)
73
- GCR.cassette.data[key] ||= GCR.serialize_response(resp)
85
+ req = GCR::Request.from_proto(*args)
86
+ if GCR.cassette.reqs.none? { |r, _| r == req }
87
+ GCR.cassette.reqs << [req, GCR::Response.from_proto(resp)]
88
+ end
74
89
  end
75
90
  end
76
91
  end
@@ -90,12 +105,11 @@ class GCR::Cassette
90
105
  alias_method :orig_request_response, :request_response
91
106
 
92
107
  def request_response(*args)
93
- key = GCR.serialize_request(*args)
94
- if resp = GCR.cassette.data[key]
95
- GCR.deserialize_response(resp)
96
- else
97
- raise GCR::NoRecording
108
+ req = GCR::Request.from_proto(*args)
109
+ GCR.cassette.reqs.each do |other_req, resp|
110
+ return resp.to_proto if req == other_req
98
111
  end
112
+ raise GCR::NoRecording
99
113
  end
100
114
  end
101
115
  end
@@ -105,4 +119,12 @@ class GCR::Cassette
105
119
  alias_method :request_response, :orig_request_response
106
120
  end
107
121
  end
122
+
123
+ def [](req)
124
+ reqs.find { |r| r == req }
125
+ end
126
+
127
+ def []=(req, resp)
128
+ reqs << [req, resp]
129
+ end
108
130
  end
@@ -0,0 +1,47 @@
1
+ class GCR::Request
2
+ def self.from_proto(route, proto_req, *_)
3
+ new(
4
+ "route" => route,
5
+ "class_name" => proto_req.class.name,
6
+ "body" => proto_req.to_json,
7
+ )
8
+ end
9
+
10
+ def self.from_hash(hash_req)
11
+ new(
12
+ "route" => hash_req["route"],
13
+ "class_name" => hash_req["class_name"],
14
+ "body" => hash_req["body"],
15
+ )
16
+ end
17
+
18
+ attr_reader :route, :class_name, :body
19
+
20
+ def initialize(opts)
21
+ @route = opts["route"]
22
+ @class_name = opts["class_name"]
23
+ @body = opts["body"]
24
+ end
25
+
26
+ def parsed_body
27
+ @parsed_body ||= JSON.parse(body)
28
+ end
29
+
30
+ def to_json(*_)
31
+ JSON.dump("route" => route, "class_name" => class_name, "body" => body)
32
+ end
33
+
34
+ def to_proto
35
+ [route, Object.const_get(class_name).decode_json(body)]
36
+ end
37
+
38
+ def ==(other)
39
+ return false unless route == other.route
40
+ return false unless class_name == other.class_name
41
+
42
+ parsed_body.keys.all? do |k|
43
+ next true if GCR.ignored_fields.include?(k)
44
+ parsed_body[k] == other.parsed_body[k]
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,34 @@
1
+ class GCR::Response
2
+ def self.from_proto(proto_resp)
3
+ new(
4
+ "class_name" => proto_resp.class.name,
5
+ "body" => proto_resp.to_json,
6
+ )
7
+ end
8
+
9
+ def self.from_hash(hash_resp)
10
+ new(
11
+ "class_name" => hash_resp["class_name"],
12
+ "body" => hash_resp["body"],
13
+ )
14
+ end
15
+
16
+ attr_reader :class_name, :body
17
+
18
+ def initialize(opts)
19
+ @class_name = opts["class_name"]
20
+ @body = opts["body"]
21
+ end
22
+
23
+ def parsed_body
24
+ @parsed_body ||= JSON.decode(body)
25
+ end
26
+
27
+ def to_json(*_)
28
+ JSON.dump("class_name" => class_name, "body" => body)
29
+ end
30
+
31
+ def to_proto
32
+ Object.const_get(class_name).decode_json(body)
33
+ end
34
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gcr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mastahyeti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-06 00:00:00.000000000 Z
11
+ date: 2018-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -84,6 +84,20 @@ dependencies:
84
84
  - - ">="
85
85
  - !ruby/object:Gem::Version
86
86
  version: '0'
87
+ - !ruby/object:Gem::Dependency
88
+ name: pry
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ type: :development
95
+ prerelease: false
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
87
101
  description:
88
102
  email:
89
103
  executables: []
@@ -92,6 +106,8 @@ extra_rdoc_files: []
92
106
  files:
93
107
  - "./lib/gcr.rb"
94
108
  - "./lib/gcr/cassette.rb"
109
+ - "./lib/gcr/request.rb"
110
+ - "./lib/gcr/response.rb"
95
111
  homepage: https://github.com/mastahyeti/gcr
96
112
  licenses:
97
113
  - MIT
@@ -112,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
128
  version: '0'
113
129
  requirements: []
114
130
  rubyforge_project:
115
- rubygems_version: 2.4.5.1
131
+ rubygems_version: 2.6.14
116
132
  signing_key:
117
133
  specification_version: 4
118
134
  summary: GRPC test helpers