mock_redis 0.21.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/CHANGELOG.md +8 -0
- data/LICENSE.md +21 -0
- data/README.md +37 -13
- data/lib/mock_redis/hash_methods.rb +9 -2
- data/lib/mock_redis/utility_methods.rb +5 -2
- data/lib/mock_redis/version.rb +1 -1
- data/lib/mock_redis/zset_methods.rb +18 -0
- data/mock_redis.gemspec +1 -2
- data/spec/commands/hmset_spec.rb +26 -0
- data/spec/commands/scan_spec.rb +9 -0
- data/spec/commands/zpopmax_spec.rb +60 -0
- data/spec/commands/zpopmin_spec.rb +60 -0
- data/spec/spec_helper.rb +1 -1
- metadata +7 -23
- data/LICENSE +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9dd8cc0a4f19edccfb6c7b3f1a82724f0da757ad7139f4a576eed1d0b815b8d
|
4
|
+
data.tar.gz: 980f4326447c75afb034b6292baab71bb723ca05689b04aa7ed4933bd8bbf356
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53a8419ef9f62a4d276993714241f22f9da4087df9ce69158821ea42c735e4fc022f4ab9431bbef268eb562130cc139308fd46ad9eeef8941ef95d9b56afc083
|
7
|
+
data.tar.gz: 266de40ac11c22fa449d709380cec9461a93cd18c6950d31aee538b295c613ab2a0ee2fb828420ff02ea2e2351e92e2d565a9bad630abfd21abf8b8eab7c144d
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# MockRedis Changelog
|
2
2
|
|
3
|
+
### 0.22.0
|
4
|
+
|
5
|
+
* Gracefully handle cursors larger than the collection size in scan commands ([#171](https://github.com/sds/mock_redis/pull/171))
|
6
|
+
* Add `zpopmin` and `zpopmax` commands ([#172](https://github.com/sds/mock_redis/pull/172))
|
7
|
+
* Fix `hmset` to support array arguments ([#173](https://github.com/sds/mock_redis/pull/173))
|
8
|
+
* Fix `hmset` to always treat keys as strings ([#173](https://github.com/sds/mock_redis/pull/173))
|
9
|
+
* Remove unnecessary dependency on `rake` gem
|
10
|
+
|
3
11
|
### 0.21.0
|
4
12
|
|
5
13
|
* Fix behavior of `time` to return array of two integers ([#161](https://github.com/sds/mock_redis/pull/161))
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MockRedis released under the MIT license.
|
2
|
+
|
3
|
+
> Copyright (c) Shane da Silva. http://shane.io
|
4
|
+
>
|
5
|
+
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
> of this software and associated documentation files (the "Software"), to deal
|
7
|
+
> in the Software without restriction, including without limitation the rights
|
8
|
+
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
> copies of the Software, and to permit persons to whom the Software is
|
10
|
+
> furnished to do so, subject to the following conditions:
|
11
|
+
>
|
12
|
+
> The above copyright notice and this permission notice shall be included in
|
13
|
+
> all copies or substantial portions of the Software.
|
14
|
+
>
|
15
|
+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
> SOFTWARE.
|
data/README.md
CHANGED
@@ -8,11 +8,20 @@ MockRedis provides the same interface as `redis-rb`, but it stores its
|
|
8
8
|
data in memory instead of talking to a Redis server. It is intended
|
9
9
|
for use in tests.
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
## Requirements
|
12
|
+
|
13
|
+
* Ruby 2.4+
|
14
|
+
|
15
|
+
The current implementation is tested against **Redis 5**. Older versions may work, but can also return different results or not support some commands.
|
13
16
|
|
14
17
|
## Getting Started
|
15
18
|
|
19
|
+
Install the gem:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
gem install mock_redis
|
23
|
+
```
|
24
|
+
|
16
25
|
It's as easy as `require 'mock_redis'; mr = MockRedis.new`. Then you can
|
17
26
|
call the same methods on it as you can call on a real `Redis` object.
|
18
27
|
|
@@ -90,17 +99,32 @@ please submit a pull request with your (tested!) implementation.
|
|
90
99
|
* `#config(:get|:set|:resetstat)` isn't done. They can just return
|
91
100
|
canned values.
|
92
101
|
|
93
|
-
##
|
102
|
+
## Running tests
|
103
|
+
|
104
|
+
We recommend running Redis within a Docker container to make development as simple as possible, but as long as you have a Redis instance listening on `localhost:6379` you should be good to go.
|
105
|
+
|
106
|
+
1. Start Redis.
|
107
|
+
```bash
|
108
|
+
docker run --rm -p 6379:6379 redis
|
109
|
+
```
|
110
|
+
2. Install dependencies.
|
111
|
+
```bash
|
112
|
+
bundle install
|
113
|
+
```
|
114
|
+
3. Run tests.
|
115
|
+
```bash
|
116
|
+
bundle exec rspec
|
117
|
+
```
|
118
|
+
|
119
|
+
These tests were written with Redis running on `localhost` without any
|
120
|
+
passwords required. If you're using a different version of Redis, you
|
121
|
+
may see failures due to error message text being different and other
|
122
|
+
breaking changes over time.
|
123
|
+
|
124
|
+
## Changelog
|
94
125
|
|
95
|
-
|
96
|
-
older versions of Ruby, use `0.18.0` or older.
|
126
|
+
If you're interested in seeing the changes and bug fixes between each version of `mock_redis`, read the [MockRedis Changelog](CHANGELOG.md).
|
97
127
|
|
98
|
-
##
|
128
|
+
## License
|
99
129
|
|
100
|
-
|
101
|
-
tests. (Just kidding! There's no probably about it.) These tests were
|
102
|
-
written with Redis running on `localhost` without any passwords
|
103
|
-
required. If you're using a different version of Redis, you may see
|
104
|
-
failures due to error message text being different. If you're running
|
105
|
-
a really old version of Redis, you'll definitely see failures due to
|
106
|
-
stuff that doesn't work!
|
130
|
+
This project is released under the [MIT license](LICENSE.md).
|
@@ -84,10 +84,17 @@ class MockRedis
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def hmset(key, *kvpairs)
|
87
|
+
if key.is_a? Array
|
88
|
+
err_msg = 'ERR wrong number of arguments for \'hmset\' command'
|
89
|
+
kvpairs = key[1..-1]
|
90
|
+
key = key[0]
|
91
|
+
end
|
92
|
+
|
87
93
|
kvpairs.flatten!
|
88
94
|
assert_has_args(kvpairs, 'hmset')
|
95
|
+
|
89
96
|
if kvpairs.length.odd?
|
90
|
-
raise Redis::CommandError, 'ERR wrong number of arguments for HMSET'
|
97
|
+
raise Redis::CommandError, err_msg || 'ERR wrong number of arguments for HMSET'
|
91
98
|
end
|
92
99
|
|
93
100
|
kvpairs.each_slice(2) do |(k, v)|
|
@@ -143,7 +150,7 @@ class MockRedis
|
|
143
150
|
private
|
144
151
|
|
145
152
|
def with_hash_at(key, &blk)
|
146
|
-
with_thing_at(key, :assert_hashy, proc { {} }, &blk)
|
153
|
+
with_thing_at(key.to_s, :assert_hashy, proc { {} }, &blk)
|
147
154
|
end
|
148
155
|
|
149
156
|
def hashy?(key)
|
@@ -28,12 +28,15 @@ class MockRedis
|
|
28
28
|
cursor = cursor.to_i
|
29
29
|
match = opts[:match] || '*'
|
30
30
|
key = opts[:key] || lambda { |x| x }
|
31
|
+
filtered_values = []
|
31
32
|
|
32
33
|
limit = cursor + count
|
33
34
|
next_cursor = limit >= values.length ? '0' : limit.to_s
|
34
35
|
|
35
|
-
|
36
|
-
|
36
|
+
unless values[cursor...limit].nil?
|
37
|
+
filtered_values = values[cursor...limit].select do |val|
|
38
|
+
redis_pattern_to_ruby_regex(match).match(key.call(val))
|
39
|
+
end
|
37
40
|
end
|
38
41
|
|
39
42
|
[next_cursor, filtered_values]
|
data/lib/mock_redis/version.rb
CHANGED
@@ -155,6 +155,24 @@ class MockRedis
|
|
155
155
|
retval
|
156
156
|
end
|
157
157
|
|
158
|
+
def zpopmin(key, count = 1)
|
159
|
+
with_zset_at(key) do |z|
|
160
|
+
pairs = z.sorted.first(count)
|
161
|
+
pairs.each { |pair| z.delete?(pair.last) }
|
162
|
+
retval = to_response(pairs, with_scores: true)
|
163
|
+
count == 1 ? retval.first : retval
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def zpopmax(key, count = 1)
|
168
|
+
with_zset_at(key) do |z|
|
169
|
+
pairs = z.sorted.reverse.first(count)
|
170
|
+
pairs.each { |pair| z.delete?(pair.last) }
|
171
|
+
retval = to_response(pairs, with_scores: true)
|
172
|
+
count == 1 ? retval.first : retval
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
158
176
|
def zrevrange(key, start, stop, options = {})
|
159
177
|
with_zset_at(key) do |z|
|
160
178
|
to_response(z.sorted.reverse[start..stop] || [], options)
|
data/mock_redis.gemspec
CHANGED
@@ -23,8 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
|
24
24
|
s.required_ruby_version = '>= 2.4'
|
25
25
|
|
26
|
-
s.add_development_dependency '
|
27
|
-
s.add_development_dependency 'redis', '~>4.1.0'
|
26
|
+
s.add_development_dependency 'redis', '~> 4.1.0'
|
28
27
|
s.add_development_dependency 'rspec', '~> 3.0'
|
29
28
|
s.add_development_dependency 'rspec-its', '~> 1.0'
|
30
29
|
s.add_development_dependency 'timecop', '~> 0.9.1'
|
data/spec/commands/hmset_spec.rb
CHANGED
@@ -39,5 +39,31 @@ describe '#hmset(key, field, value [, field, value ...])' do
|
|
39
39
|
end.should raise_error(Redis::CommandError)
|
40
40
|
end
|
41
41
|
|
42
|
+
# The following tests address https://github.com/sds/mock_redis/issues/170
|
43
|
+
context 'keys are stored as strings' do
|
44
|
+
before do
|
45
|
+
@redises.hmset(1, :foo, :bar)
|
46
|
+
@redises.hmset(:a_sym, :boo, :bas)
|
47
|
+
end
|
48
|
+
|
49
|
+
it { expect(@redises.hgetall('1')).to eq @redises.hgetall(1) }
|
50
|
+
it { expect(@redises.hgetall('a_sym')).to eq @redises.hgetall(:a_sym) }
|
51
|
+
it { expect(@redises.del('1')).to eq 1 }
|
52
|
+
it { expect(@redises.del(1)).to eq 1 }
|
53
|
+
it { expect(@redises.del('a_sym')).to eq 1 }
|
54
|
+
it { expect(@redises.del(:a_sym)).to eq 1 }
|
55
|
+
|
56
|
+
after do
|
57
|
+
@redises.del(1)
|
58
|
+
@redises.del(:a_sym)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# The following tests address https://github.com/sds/mock_redis/issues/134
|
63
|
+
context 'hmset accepts an array as its only argument' do
|
64
|
+
it { expect(@redises.hmset([@key, :bar, :bas])).to eq 'OK' }
|
65
|
+
it { lambda { @redises.hmset([:foo, :bar]) }.should raise_error(Redis::CommandError) }
|
66
|
+
end
|
67
|
+
|
42
68
|
it_should_behave_like 'a hash-only command'
|
43
69
|
end
|
data/spec/commands/scan_spec.rb
CHANGED
@@ -42,6 +42,15 @@ describe '#scan' do
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
context 'when cursor is greater than collection size' do
|
46
|
+
let(:collection) { Array.new(count) { |i| "mock:key#{i}" } }
|
47
|
+
let(:expected) { ['0', []] }
|
48
|
+
|
49
|
+
it 'returns a 0 cursor and empty collection' do
|
50
|
+
expect(subject.scan(20, count: count, match: match)).to eq(expected)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
45
54
|
context 'when giving a custom match filter' do
|
46
55
|
let(:match) { 'mock:key*' }
|
47
56
|
let(:collection) { %w[mock:key mock:key2 mock:otherkey] }
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#zpopmax(key, count)' do
|
4
|
+
before(:each) do
|
5
|
+
@key = 'mock-redis-test:zpopmax'
|
6
|
+
@redises.del(@key)
|
7
|
+
@redises.zadd(@key, 1, 'one')
|
8
|
+
@redises.zadd(@key, 2, 'two')
|
9
|
+
@redises.zadd(@key, 3, 'three')
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when count is unspecified' do
|
13
|
+
it 'returns nil if the set does not exist' do
|
14
|
+
@redises.zpopmax('does-not-exist').should nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns the highest ranked element' do
|
18
|
+
@redises.zpopmax(@key).should == ['three', 3]
|
19
|
+
@redises.zcard(@key).should == 2
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when count is 1' do
|
24
|
+
let(:count) { 1 }
|
25
|
+
|
26
|
+
it 'returns nil if the set does not exist' do
|
27
|
+
@redises.zpopmax('does-not-exist', count).should nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns the highest ranked element' do
|
31
|
+
@redises.zpopmax(@key, count).should == ['three', 3]
|
32
|
+
@redises.zcard(@key).should == 2
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when count is greater than 1' do
|
37
|
+
let(:count) { 2 }
|
38
|
+
|
39
|
+
it 'returns empty array if the set does not exist' do
|
40
|
+
@redises.zpopmax('does-not-exist', count).should == []
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns the highest ranked elements' do
|
44
|
+
@redises.zpopmax(@key, count).should == [['three', 3], ['two', 2]]
|
45
|
+
@redises.zcard(@key).should == 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when count is greater than the size of the set' do
|
50
|
+
let(:count) { 4 }
|
51
|
+
|
52
|
+
it 'returns the entire set' do
|
53
|
+
before = @redises.zrange(@key, 0, count, with_scores: true).reverse
|
54
|
+
@redises.zpopmax(@key, count).should == before
|
55
|
+
@redises.zcard(@key).should == 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it_should_behave_like 'a zset-only command'
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#zpopmin(key, count)' do
|
4
|
+
before(:each) do
|
5
|
+
@key = 'mock-redis-test:zpopmin'
|
6
|
+
@redises.del(@key)
|
7
|
+
@redises.zadd(@key, 1, 'one')
|
8
|
+
@redises.zadd(@key, 2, 'two')
|
9
|
+
@redises.zadd(@key, 3, 'three')
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when count is unspecified' do
|
13
|
+
it 'returns nil if the set does not exist' do
|
14
|
+
@redises.zpopmin('does-not-exist').should nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns the lowest ranked element' do
|
18
|
+
@redises.zpopmin(@key).should == ['one', 1]
|
19
|
+
@redises.zcard(@key).should == 2
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when count is 1' do
|
24
|
+
let(:count) { 1 }
|
25
|
+
|
26
|
+
it 'returns nil if the set does not exist' do
|
27
|
+
@redises.zpopmin('does-not-exist', count).should nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns the lowest ranked element' do
|
31
|
+
@redises.zpopmin(@key, count).should == ['one', 1]
|
32
|
+
@redises.zcard(@key).should == 2
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when count is greater than 1' do
|
37
|
+
let(:count) { 2 }
|
38
|
+
|
39
|
+
it 'returns empty array if the set does not exist' do
|
40
|
+
@redises.zpopmin('does-not-exist', count).should == []
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns the lowest ranked elements' do
|
44
|
+
@redises.zpopmin(@key, count).should == [['one', 1], ['two', 2]]
|
45
|
+
@redises.zcard(@key).should == 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when count is greater than the size of the set' do
|
50
|
+
let(:count) { 4 }
|
51
|
+
|
52
|
+
it 'returns the entire set' do
|
53
|
+
before = @redises.zrange(@key, 0, count, with_scores: true)
|
54
|
+
@redises.zpopmin(@key, count).should == before
|
55
|
+
@redises.zcard(@key).should == 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it_should_behave_like 'a zset-only command'
|
60
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -27,7 +27,7 @@ module TypeCheckingHelper
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def args_for_method(method)
|
30
|
-
return [] if method.to_s
|
30
|
+
return [] if %w[spop zpopmin zpopmax].include?(method.to_s)
|
31
31
|
method_arity = @redises.real.method(method).arity
|
32
32
|
if method_arity < 0 # -1 comes from def foo(*args)
|
33
33
|
[1, 2] # probably good enough
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mock_redis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane da Silva
|
@@ -9,28 +9,8 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-10-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: rake
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
requirements:
|
18
|
-
- - ">="
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: '10'
|
21
|
-
- - "<"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: '12'
|
24
|
-
type: :development
|
25
|
-
prerelease: false
|
26
|
-
version_requirements: !ruby/object:Gem::Requirement
|
27
|
-
requirements:
|
28
|
-
- - ">="
|
29
|
-
- !ruby/object:Gem::Version
|
30
|
-
version: '10'
|
31
|
-
- - "<"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '12'
|
34
14
|
- !ruby/object:Gem::Dependency
|
35
15
|
name: redis
|
36
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -105,7 +85,7 @@ files:
|
|
105
85
|
- ".travis.yml"
|
106
86
|
- CHANGELOG.md
|
107
87
|
- Gemfile
|
108
|
-
- LICENSE
|
88
|
+
- LICENSE.md
|
109
89
|
- README.md
|
110
90
|
- Rakefile
|
111
91
|
- lib/mock_redis.rb
|
@@ -266,6 +246,8 @@ files:
|
|
266
246
|
- spec/commands/zcount_spec.rb
|
267
247
|
- spec/commands/zincrby_spec.rb
|
268
248
|
- spec/commands/zinterstore_spec.rb
|
249
|
+
- spec/commands/zpopmax_spec.rb
|
250
|
+
- spec/commands/zpopmin_spec.rb
|
269
251
|
- spec/commands/zrange_spec.rb
|
270
252
|
- spec/commands/zrangebyscore_spec.rb
|
271
253
|
- spec/commands/zrank_spec.rb
|
@@ -446,6 +428,8 @@ test_files:
|
|
446
428
|
- spec/commands/zcount_spec.rb
|
447
429
|
- spec/commands/zincrby_spec.rb
|
448
430
|
- spec/commands/zinterstore_spec.rb
|
431
|
+
- spec/commands/zpopmax_spec.rb
|
432
|
+
- spec/commands/zpopmin_spec.rb
|
449
433
|
- spec/commands/zrange_spec.rb
|
450
434
|
- spec/commands/zrangebyscore_spec.rb
|
451
435
|
- spec/commands/zrank_spec.rb
|
data/LICENSE
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
Copyright (c) 2011 Philotic, Inc.
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
of this software and associated documentation files (the "Software"), to deal
|
5
|
-
in the Software without restriction, including without limitation the rights
|
6
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
copies of the Software, and to permit persons to whom the Software is
|
8
|
-
furnished to do so, subject to the following conditions:
|
9
|
-
|
10
|
-
The above copyright notice and this permission notice shall be included in
|
11
|
-
all copies or substantial portions of the Software.
|
12
|
-
|
13
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
THE SOFTWARE.
|