sodium 0.6.2 → 0.7.0
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.
- data.tar.gz.sig +0 -0
- data/.travis.yml +13 -6
- data/CHANGELOG.md +15 -1
- data/VERSION +1 -1
- data/lib/sodium/auth.rb +8 -8
- data/lib/sodium/box.rb +27 -27
- data/lib/sodium/buffer.rb +141 -85
- data/lib/sodium/ffi/lib_c.rb +3 -0
- data/lib/sodium/hash.rb +3 -3
- data/lib/sodium/one_time_auth.rb +8 -8
- data/lib/sodium/random.rb +1 -1
- data/lib/sodium/secret_box.rb +10 -10
- data/lib/sodium/sign.rb +11 -11
- data/tasks/extensions.rake +12 -3
- data/test/sodium/auth/hmacsha256_test.rb +2 -2
- data/test/sodium/auth/hmacsha512256_test.rb +2 -2
- data/test/sodium/auth_test.rb +2 -2
- data/test/sodium/box/curve25519xsalsa20poly1305_test.rb +5 -5
- data/test/sodium/box_test.rb +6 -6
- data/test/sodium/buffer_test.rb +79 -72
- data/test/sodium/hash/sha256_test.rb +1 -1
- data/test/sodium/hash/sha512_test.rb +1 -1
- data/test/sodium/hash_test.rb +3 -2
- data/test/sodium/one_time_auth/poly1305_test.rb +1 -1
- data/test/sodium/one_time_auth_test.rb +2 -2
- data/test/sodium/secret_box/xsalsa20poly1305_test.rb +2 -2
- data/test/sodium/secret_box_test.rb +3 -3
- data/test/sodium/sign/ed25519_test.rb +1 -1
- data/test/sodium/sign_test.rb +4 -4
- metadata +154 -159
- metadata.gz.sig +2 -4
- checksums.yaml +0 -7
- checksums.yaml.gz.sig +0 -0
data/lib/sodium/ffi/lib_c.rb
CHANGED
data/lib/sodium/hash.rb
CHANGED
@@ -8,9 +8,9 @@ class Sodium::Hash
|
|
8
8
|
|
9
9
|
Sodium::Buffer.empty self.implementation[:BYTES] do |digest|
|
10
10
|
self.implementation.nacl(
|
11
|
-
digest.
|
12
|
-
message.
|
13
|
-
message.
|
11
|
+
digest .to_ptr,
|
12
|
+
message.to_ptr,
|
13
|
+
message.bytesize
|
14
14
|
) or raise Sodium::CryptoError, 'failed to generate a hash for the message'
|
15
15
|
end
|
16
16
|
end
|
data/lib/sodium/one_time_auth.rb
CHANGED
@@ -16,10 +16,10 @@ class Sodium::OneTimeAuth
|
|
16
16
|
|
17
17
|
Sodium::Buffer.empty self.implementation[:BYTES] do |authenticator|
|
18
18
|
self.implementation.nacl(
|
19
|
-
authenticator.
|
20
|
-
message.
|
21
|
-
message.
|
22
|
-
@key.
|
19
|
+
authenticator.to_ptr,
|
20
|
+
message .to_ptr,
|
21
|
+
message .bytesize,
|
22
|
+
@key .to_ptr
|
23
23
|
) or raise Sodium::CryptoError, 'failed to generate an authenticator'
|
24
24
|
end
|
25
25
|
end
|
@@ -29,10 +29,10 @@ class Sodium::OneTimeAuth
|
|
29
29
|
authenticator = self.class._authenticator(authenticator)
|
30
30
|
|
31
31
|
self.implementation.nacl_verify(
|
32
|
-
authenticator.
|
33
|
-
message.
|
34
|
-
message.
|
35
|
-
@key.
|
32
|
+
authenticator.to_ptr,
|
33
|
+
message .to_ptr,
|
34
|
+
message .bytesize,
|
35
|
+
@key .to_ptr
|
36
36
|
)
|
37
37
|
end
|
38
38
|
|
data/lib/sodium/random.rb
CHANGED
data/lib/sodium/secret_box.rb
CHANGED
@@ -21,11 +21,11 @@ class Sodium::SecretBox
|
|
21
21
|
|
22
22
|
Sodium::Buffer.empty(message.bytesize) do |ciphertext|
|
23
23
|
self.implementation.nacl(
|
24
|
-
ciphertext.
|
25
|
-
message.
|
26
|
-
message.
|
27
|
-
nonce.
|
28
|
-
@key.
|
24
|
+
ciphertext .to_ptr,
|
25
|
+
message .to_ptr,
|
26
|
+
message .bytesize,
|
27
|
+
nonce .to_ptr,
|
28
|
+
@key .to_ptr
|
29
29
|
) or raise Sodium::CryptoError, 'failed to close the secret box'
|
30
30
|
end.ldrop self.implementation[:BOXZEROBYTES]
|
31
31
|
end
|
@@ -36,11 +36,11 @@ class Sodium::SecretBox
|
|
36
36
|
|
37
37
|
Sodium::Buffer.empty(ciphertext.bytesize) do |message|
|
38
38
|
self.implementation.nacl_open(
|
39
|
-
message.
|
40
|
-
ciphertext.
|
41
|
-
ciphertext.
|
42
|
-
nonce.
|
43
|
-
@key.
|
39
|
+
message .to_ptr,
|
40
|
+
ciphertext .to_ptr,
|
41
|
+
ciphertext .bytesize,
|
42
|
+
nonce .to_ptr,
|
43
|
+
@key .to_ptr
|
44
44
|
) or raise Sodium::CryptoError, 'failed to open the secret box'
|
45
45
|
end.ldrop self.implementation[:ZEROBYTES]
|
46
46
|
end
|
data/lib/sodium/sign.rb
CHANGED
@@ -8,8 +8,8 @@ class Sodium::Sign
|
|
8
8
|
secret_key = Sodium::Buffer.empty self.implementation[:SECRETKEYBYTES]
|
9
9
|
|
10
10
|
self.implementation.nacl_keypair(
|
11
|
-
public_key.
|
12
|
-
secret_key.
|
11
|
+
public_key.to_ptr,
|
12
|
+
secret_key.to_ptr
|
13
13
|
) or raise Sodium::CryptoError, 'failed to generate a keypair'
|
14
14
|
|
15
15
|
return secret_key, public_key
|
@@ -22,11 +22,11 @@ class Sodium::Sign
|
|
22
22
|
mlen = FFI::MemoryPointer.new(:ulong_long, 1, true)
|
23
23
|
|
24
24
|
self.implementation.nacl_open(
|
25
|
-
message.
|
25
|
+
message .to_ptr,
|
26
26
|
mlen,
|
27
|
-
signature.
|
28
|
-
signature.
|
29
|
-
key.
|
27
|
+
signature .to_ptr,
|
28
|
+
signature .bytesize,
|
29
|
+
key .to_ptr
|
30
30
|
)
|
31
31
|
end
|
32
32
|
|
@@ -40,18 +40,18 @@ class Sodium::Sign
|
|
40
40
|
slen = FFI::MemoryPointer.new(:ulong_long, 1, true)
|
41
41
|
|
42
42
|
self.implementation.nacl(
|
43
|
-
signature.
|
43
|
+
signature .to_ptr,
|
44
44
|
slen,
|
45
|
-
message.
|
46
|
-
message.
|
47
|
-
@key.
|
45
|
+
message .to_ptr,
|
46
|
+
message .bytesize,
|
47
|
+
@key .to_ptr
|
48
48
|
) or raise Sodium::CryptoError, 'failed to generate signature'
|
49
49
|
|
50
50
|
# signatures actually encode the message itself at the end, so we
|
51
51
|
# slice off only the signature bytes
|
52
52
|
signature.byteslice(
|
53
53
|
0,
|
54
|
-
slen.read_ulong_long - message.
|
54
|
+
slen.read_ulong_long - message.bytesize
|
55
55
|
)
|
56
56
|
end
|
57
57
|
|
data/tasks/extensions.rake
CHANGED
@@ -9,12 +9,18 @@ namespace :compile do
|
|
9
9
|
desc 'Compile the memory extension'
|
10
10
|
task :memory => %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}}
|
11
11
|
|
12
|
-
file %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}} =>
|
12
|
+
file %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}} => FileList[MEMORY_SRC] do
|
13
|
+
Dir.chdir(MEMORY_PATH) { ruby %{extconf.rb} }
|
13
14
|
sh %{make -C #{MEMORY_PATH} install sitearchdir="#{LIB_PATH}"}
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
task :clean do
|
18
|
+
sh %{make -C #{MEMORY_PATH} realclean} if
|
19
|
+
File.exist? %{#{MEMORY_PATH}/Makefile}
|
20
|
+
end
|
21
|
+
|
22
|
+
task :clobber do
|
23
|
+
CLOBBER.add %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}}
|
18
24
|
end
|
19
25
|
end
|
20
26
|
|
@@ -22,3 +28,6 @@ desc 'Compile all native extensions'
|
|
22
28
|
task :compile => %w{ compile:memory }
|
23
29
|
|
24
30
|
task :test => %w{ compile }
|
31
|
+
|
32
|
+
task :clean => :'compile:clean'
|
33
|
+
task :clobber => :'compile:clobber'
|
@@ -36,11 +36,11 @@ describe Sodium::Auth::HMACSHA256 do
|
|
36
36
|
self.klass.auth(
|
37
37
|
self.key,
|
38
38
|
self.plaintext
|
39
|
-
).
|
39
|
+
).to_s.must_equal self.authenticator
|
40
40
|
|
41
41
|
self.subject.auth(
|
42
42
|
self.plaintext
|
43
|
-
).
|
43
|
+
).to_s.must_equal self.authenticator
|
44
44
|
end
|
45
45
|
|
46
46
|
it 'must verify authenticators' do
|
@@ -35,11 +35,11 @@ describe Sodium::Auth::HMACSHA512256 do
|
|
35
35
|
self.klass.auth(
|
36
36
|
self.key,
|
37
37
|
self.plaintext
|
38
|
-
).
|
38
|
+
).to_s.must_equal self.authenticator
|
39
39
|
|
40
40
|
self.subject.auth(
|
41
41
|
self.plaintext
|
42
|
-
).
|
42
|
+
).to_s.must_equal self.authenticator
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'must verify authenticators' do
|
data/test/sodium/auth_test.rb
CHANGED
@@ -26,12 +26,12 @@ describe Sodium::Auth do
|
|
26
26
|
sodium_mock_default(self.klass) do |klass, mock|
|
27
27
|
mock.expect :[], 0, [:KEYBYTES]
|
28
28
|
|
29
|
-
klass.key.
|
29
|
+
klass.key.to_s.must_equal ''
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'must raise when instantiating with an invalid key' do
|
34
|
-
lambda { self.klass.new(self.key.
|
34
|
+
lambda { self.klass.new(self.key.to_s[0..-2]) }.
|
35
35
|
must_raise Sodium::LengthError
|
36
36
|
end
|
37
37
|
|
@@ -47,18 +47,18 @@ describe Sodium::Box::Curve25519XSalsa20Poly1305 do
|
|
47
47
|
self.subject.box(
|
48
48
|
self.plaintext,
|
49
49
|
self.nonce
|
50
|
-
).
|
50
|
+
).to_s.must_equal self.ciphertext
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'must open boxes' do
|
54
54
|
self.subject.open(
|
55
55
|
self.ciphertext,
|
56
56
|
self.nonce
|
57
|
-
).
|
57
|
+
).to_s.must_equal self.plaintext
|
58
58
|
end
|
59
59
|
|
60
60
|
it 'must generate shared keys' do
|
61
|
-
self.subject.beforenm.
|
61
|
+
self.subject.beforenm.to_s.must_equal self.shared_key
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'must generate closed boxes with shared keys' do
|
@@ -66,7 +66,7 @@ describe Sodium::Box::Curve25519XSalsa20Poly1305 do
|
|
66
66
|
self.shared_key,
|
67
67
|
self.plaintext,
|
68
68
|
self.nonce
|
69
|
-
).
|
69
|
+
).to_s.must_equal self.ciphertext
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'must open boxes with shared keys' do
|
@@ -74,6 +74,6 @@ describe Sodium::Box::Curve25519XSalsa20Poly1305 do
|
|
74
74
|
self.shared_key,
|
75
75
|
self.ciphertext,
|
76
76
|
self.nonce
|
77
|
-
).
|
77
|
+
).to_s.must_equal self.plaintext
|
78
78
|
end
|
79
79
|
end
|
data/test/sodium/box_test.rb
CHANGED
@@ -24,29 +24,29 @@ describe Sodium::Box do
|
|
24
24
|
|
25
25
|
it 'must mint keypairs from the default implementation' do
|
26
26
|
sodium_mock_default(self.klass) do |klass, mock|
|
27
|
-
mock.expect :nacl_keypair, true, [
|
27
|
+
mock.expect :nacl_keypair, true, [ FFI::Pointer, FFI::Pointer ]
|
28
28
|
mock.expect :[], 0, [:PUBLICKEYBYTES]
|
29
29
|
mock.expect :[], 0, [:SECRETKEYBYTES]
|
30
30
|
|
31
31
|
sk, pk = klass.keypair
|
32
32
|
|
33
|
-
sk.
|
34
|
-
pk.
|
33
|
+
sk.to_s.must_equal ''
|
34
|
+
pk.to_s.must_equal ''
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'must raise when instantiating with an invalid keypair' do
|
39
39
|
secret_key, public_key = self.keypair
|
40
40
|
|
41
|
-
lambda { self.klass.new(secret_key.
|
41
|
+
lambda { self.klass.new(secret_key.to_s[0..-2], public_key) }.
|
42
42
|
must_raise Sodium::LengthError
|
43
43
|
|
44
|
-
lambda { self.klass.new(secret_key, public_key.
|
44
|
+
lambda { self.klass.new(secret_key, public_key.to_s[0..-2]) }.
|
45
45
|
must_raise Sodium::LengthError
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'must raise when receiving an invalid nonce' do
|
49
|
-
lambda { self.subject.box('message', self.subject.nonce.
|
49
|
+
lambda { self.subject.box('message', self.subject.nonce.to_s[0..-2]) }.
|
50
50
|
must_raise Sodium::LengthError
|
51
51
|
end
|
52
52
|
|
data/test/sodium/buffer_test.rb
CHANGED
@@ -3,29 +3,35 @@ require 'test_helper'
|
|
3
3
|
describe Sodium::Buffer do
|
4
4
|
subject { Sodium::Buffer }
|
5
5
|
|
6
|
+
def trigger_gc!
|
7
|
+
GC.start
|
8
|
+
1_000_000.times { Object.new }
|
9
|
+
GC.start
|
10
|
+
end
|
11
|
+
|
6
12
|
it '::key must securely generate random keys of specified length' do
|
7
13
|
Sodium::Random.stub(:bytes, lambda {|l| ' ' * l }) do
|
8
|
-
subject.key( 7).
|
9
|
-
subject.key( 8).
|
10
|
-
subject.key(16).
|
11
|
-
subject.key(32).
|
12
|
-
subject.key(64).
|
14
|
+
subject.key( 7).to_s.must_equal(' ' * 7)
|
15
|
+
subject.key( 8).to_s.must_equal(' ' * 8)
|
16
|
+
subject.key(16).to_s.must_equal(' ' * 16)
|
17
|
+
subject.key(32).to_s.must_equal(' ' * 32)
|
18
|
+
subject.key(64).to_s.must_equal(' ' * 64)
|
13
19
|
end
|
14
20
|
end
|
15
21
|
|
16
22
|
it '::nonce must securely generate random nonces of specified length' do
|
17
23
|
Sodium::Random.stub(:bytes, lambda {|l| ' ' * l }) do
|
18
|
-
subject.nonce( 7).
|
19
|
-
subject.nonce( 8).
|
20
|
-
subject.nonce(16).
|
21
|
-
subject.nonce(32).
|
22
|
-
subject.nonce(64).
|
24
|
+
subject.nonce( 7).to_s.must_equal(' ' * 7)
|
25
|
+
subject.nonce( 8).to_s.must_equal(' ' * 8)
|
26
|
+
subject.nonce(16).to_s.must_equal(' ' * 16)
|
27
|
+
subject.nonce(32).to_s.must_equal(' ' * 32)
|
28
|
+
subject.nonce(64).to_s.must_equal(' ' * 64)
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
26
32
|
it '::empty must generate an empty buffer of specified length' do
|
27
|
-
subject.empty(32).
|
28
|
-
subject.empty(40).
|
33
|
+
subject.empty(32).to_s.must_equal("\0" * 32)
|
34
|
+
subject.empty(40).to_s.must_equal("\0" * 40)
|
29
35
|
end
|
30
36
|
|
31
37
|
it '::empty must yield to a block when given' do
|
@@ -38,43 +44,44 @@ describe Sodium::Buffer do
|
|
38
44
|
end
|
39
45
|
|
40
46
|
it '::ljust must pad zero bytes on the end' do
|
41
|
-
subject.ljust('xyz', 5).
|
47
|
+
subject.ljust('xyz', 5).to_s.must_equal "xyz\0\0"
|
42
48
|
end
|
43
49
|
|
44
50
|
it '::ljust must not pad bytes when not needed' do
|
45
|
-
subject.ljust('xyz', 2).
|
51
|
+
subject.ljust('xyz', 2).to_s.must_equal 'xyz'
|
46
52
|
end
|
47
53
|
|
48
54
|
it '::rjust must pad zero bytes onto the front' do
|
49
|
-
subject.rjust('xyz', 5).
|
55
|
+
subject.rjust('xyz', 5).to_s.must_equal "\0\0xyz"
|
50
56
|
end
|
51
57
|
|
52
58
|
it '::rjust must not pad bytes when not needed' do
|
53
|
-
subject.rjust('xyz', 2).
|
59
|
+
subject.rjust('xyz', 2).to_s.must_equal 'xyz'
|
54
60
|
end
|
55
61
|
|
56
62
|
it '::lpad must prepend the required number of bytes' do
|
57
|
-
subject.lpad('xyz', 0).
|
58
|
-
subject.lpad('xyz', 2).
|
63
|
+
subject.lpad('xyz', 0).to_s.must_equal 'xyz'
|
64
|
+
subject.lpad('xyz', 2).to_s.must_equal "\0\0xyz"
|
59
65
|
end
|
60
66
|
|
61
67
|
it '::rpad must append the required number of bytes' do
|
62
|
-
subject.rpad('xyz', 0).
|
63
|
-
subject.rpad('xyz', 2).
|
68
|
+
subject.rpad('xyz', 0).to_s.must_equal 'xyz'
|
69
|
+
subject.rpad('xyz', 2).to_s.must_equal "xyz\0\0"
|
64
70
|
end
|
65
71
|
|
66
72
|
it '::new must create a buffer containing the specified string' do
|
67
|
-
subject.new('xyz' ).
|
68
|
-
subject.new('xyz' * 50).
|
73
|
+
subject.new('xyz' ).to_s.must_equal('xyz')
|
74
|
+
subject.new('xyz' * 50).to_s.must_equal('xyz' * 50)
|
69
75
|
end
|
70
76
|
|
71
77
|
it '::new must do optional length checking' do
|
72
|
-
lambda { subject.new('xyz', 4).
|
78
|
+
lambda { subject.new('xyz', 4).to_s }.
|
73
79
|
must_raise Sodium::LengthError
|
74
80
|
end
|
75
81
|
|
76
82
|
it '#initialize must freeze its bytes' do
|
77
|
-
subject.new('s').
|
83
|
+
subject.new('s').to_ptr.must_be :frozen?
|
84
|
+
subject.new('s').to_s .must_be :frozen?
|
78
85
|
end
|
79
86
|
|
80
87
|
it '#initialize must wipe the memory from the original string' do
|
@@ -87,27 +94,27 @@ describe Sodium::Buffer do
|
|
87
94
|
it '#initialize must prevent the string from being paged to disk'
|
88
95
|
|
89
96
|
it '#== must compare equality of two buffers' do
|
90
|
-
subject.new('xyz')
|
91
|
-
subject.new('xyz')
|
92
|
-
subject.new('xyz')
|
93
|
-
subject.new('xyz')
|
97
|
+
subject.new('xyz').must_be :==, 'xyz'
|
98
|
+
subject.new('xyz').wont_be :==, 'xy'
|
99
|
+
subject.new('xyz').wont_be :==, 'xyzz'
|
100
|
+
subject.new('xyz').wont_be :==, 'abc'
|
94
101
|
end
|
95
102
|
|
96
103
|
it '#== must compare equality of two buffers in constant time'
|
97
104
|
|
98
105
|
it '#+ must append two buffers' do
|
99
|
-
subject.new('xyz').+('abc').
|
106
|
+
subject.new('xyz').+('abc').to_s.must_equal 'xyzabc'
|
100
107
|
end
|
101
108
|
|
102
109
|
it '#^ must XOR two buffers' do
|
103
|
-
subject.new('xyz').^('xyz').
|
104
|
-
subject.new('xyz').^('xyz').
|
110
|
+
subject.new('xyz').^('xyz').to_s.must_equal "\0\0\0"
|
111
|
+
subject.new('xyz').^('xyz').to_s.must_equal "\0\0\0"
|
105
112
|
end
|
106
113
|
|
107
114
|
it '#[]= must allow replacement of byte ranges' do
|
108
|
-
subject.new('xyz').tap {|b| b[0, 3] = 'abc' }.
|
109
|
-
subject.new('xyz').tap {|b| b[0, 2] = 'ab' }.
|
110
|
-
subject.new('xyz').tap {|b| b[2, 1] = 'c' }.
|
115
|
+
subject.new('xyz').tap {|b| b[0, 3] = 'abc' }.to_s.must_equal 'abc'
|
116
|
+
subject.new('xyz').tap {|b| b[0, 2] = 'ab' }.to_s.must_equal 'abz'
|
117
|
+
subject.new('xyz').tap {|b| b[2, 1] = 'c' }.to_s.must_equal 'xyc'
|
111
118
|
end
|
112
119
|
|
113
120
|
it '#[]= must not allow resizing the buffer' do
|
@@ -117,61 +124,61 @@ describe Sodium::Buffer do
|
|
117
124
|
lambda { subject.new('xyz')[2, 2] = 'ab' }.must_raise ArgumentError
|
118
125
|
end
|
119
126
|
|
120
|
-
it '#[] must accept an indivdual byte offset to return' do
|
121
|
-
subject.new('xyz').tap do |buffer|
|
122
|
-
buffer[-4].to_str.must_equal ''
|
123
|
-
buffer[-3].to_str.must_equal 'x'
|
124
|
-
buffer[-2].to_str.must_equal 'y'
|
125
|
-
buffer[-1].to_str.must_equal 'z'
|
126
|
-
buffer[ 0].to_str.must_equal 'x'
|
127
|
-
buffer[ 1].to_str.must_equal 'y'
|
128
|
-
buffer[ 2].to_str.must_equal 'z'
|
129
|
-
buffer[ 3].to_str.must_equal ''
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
it '#[] must accept ranges of bytes to return' do
|
134
|
-
subject.new('xyz').tap do |buffer|
|
135
|
-
buffer[ 0.. 0].to_str.must_equal 'x'
|
136
|
-
buffer[ 0.. 1].to_str.must_equal 'xy'
|
137
|
-
buffer[ 0.. 2].to_str.must_equal 'xyz'
|
138
|
-
buffer[ 0.. 3].to_str.must_equal 'xyz'
|
139
|
-
buffer[ 1..-1].to_str.must_equal 'yz'
|
140
|
-
buffer[ 2..-2].to_str.must_equal ''
|
141
|
-
buffer[-3..-1].to_str.must_equal 'xyz'
|
142
|
-
buffer[-4.. 1].to_str.must_equal ''
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
127
|
it '#[] must accept an offset and number of bytes to return' do
|
147
128
|
subject.new('xyz').tap do |buffer|
|
148
|
-
buffer[ 0, 0].
|
149
|
-
buffer[ 0, 1].
|
150
|
-
buffer[ 0, 3].
|
151
|
-
buffer[ 2,
|
152
|
-
buffer[ 2, 1].to_str.must_equal 'z'
|
153
|
-
buffer[-2, 1].to_str.must_equal 'y'
|
154
|
-
buffer[ 0, -1].to_str.must_equal ''
|
129
|
+
buffer[ 0, 0].to_s.must_equal ''
|
130
|
+
buffer[ 0, 1].to_s.must_equal 'x'
|
131
|
+
buffer[ 0, 3].to_s.must_equal 'xyz'
|
132
|
+
buffer[ 2, 1].to_s.must_equal 'z'
|
155
133
|
end
|
156
134
|
end
|
157
135
|
|
158
|
-
it '#
|
136
|
+
it '#bytesize must return its length' do
|
159
137
|
subject.new('testing').bytesize.must_equal 7
|
160
138
|
end
|
161
139
|
|
162
140
|
it '#ldrop must drop bytes off the left' do
|
163
|
-
subject.new('xyz').ldrop(2).
|
141
|
+
subject.new('xyz').ldrop(2).to_s.must_equal('z')
|
164
142
|
end
|
165
143
|
|
166
144
|
it '#rdrop must drop bytes off the right' do
|
167
|
-
subject.new('xyz').rdrop(2).
|
145
|
+
subject.new('xyz').rdrop(2).to_s.must_equal('x')
|
168
146
|
end
|
169
147
|
|
170
148
|
it '#inspect must not reveal its instance variables' do
|
171
149
|
subject.new('blah').inspect.wont_include 'blah'
|
172
150
|
end
|
173
151
|
|
174
|
-
it '#
|
175
|
-
subject.new('xyz').
|
152
|
+
it '#to_s must return its internal bytes' do
|
153
|
+
subject.new('xyz').to_s.must_equal('xyz')
|
154
|
+
end
|
155
|
+
|
156
|
+
it '#to_ptr must return the live pointer to its data' do
|
157
|
+
subject.new('xyz').to_ptr.read_bytes(3).must_equal('xyz')
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
it 'must wipe its contents when garbage collected' do
|
162
|
+
address = lambda { Sodium::Buffer.new('xyz').to_ptr.address }
|
163
|
+
pointer = FFI::Pointer.new(address.call)
|
164
|
+
|
165
|
+
trigger_gc!
|
166
|
+
|
167
|
+
pointer.read_bytes(3).wont_equal('xyz')
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'must free its contents when garbage collected' do
|
171
|
+
flag = MiniTest::Mock.new
|
172
|
+
free = lambda {|pointer| flag.called(pointer) }
|
173
|
+
flag.expect :called, nil, [ FFI::Pointer ]
|
174
|
+
|
175
|
+
Sodium::FFI::LibC.stub(:free, free) do
|
176
|
+
Sodium::Buffer.new('xyz')
|
177
|
+
|
178
|
+
trigger_gc!
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
flag.verify
|
176
183
|
end
|
177
184
|
end
|