summaryrefslogtreecommitdiff
path: root/tests/encode-tests.lisp
blob: b4c6892f8dfb56bf2889137c25e5faad3f06fa58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
;; This file is part of eris-cl.
;; Copyright (C) 2022 Piotr Szarmański

;; eris-cl is free software: you can redistribute it and/or modify it under the
;; terms of the GNU Lesser General Public License as published by the Free
;; Software Foundation, either version 3 of the License, or (at your option) any
;; later version.

;; eris-cl is distributed in the hope that it will be useful, but WITHOUT ANY
;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
;; A PARTICULAR PURPOSE. See the GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License along with
;; eris-cl. If not, see <https://www.gnu.org/licenses/>.

(in-package :eris/test)
(def-suite* encoding-tests :in eris-tests)


(defmacro check-urn (data block-size urn &key (secret null-secret))
  `(let ((urn ,urn)
         (vector-encode (read-capability-to-urn
                         (eris-encode ,data
                                      ,block-size
                                      (lambda (block ref) (declare (ignore ref)) block)
                                      :secret ,secret)))
         (stream-encode (read-capability-to-urn
                         (with-octet-input-stream (stream ,data)
                           (eris-encode stream
                                        ,block-size
                                        (lambda (block ref) (declare (ignore ref)) block)
                                        :secret ,secret)))))
     (is (equalp vector-encode urn))
     (is (equalp stream-encode urn))))

(test hello-world
  (check-urn (base32-to-bytes-unpadded "JBSWY3DPEB3W64TMMQQQ") 1024
             "urn:eris:BIAD77QDJMFAKZYH2DXBUZYAP3MXZ3DJZVFYQ5DFWC6T65WSFCU5S2IT4YZGJ7AC4SYQMP2DM2ANS2ZTCP3DJJIRV733CRAAHOSWIYZM3M"))

(test empty-stream
  (check-urn (serapeum:make-octet-vector 0) 1024
             "urn:eris:BIADFUKDPYKJNLGCVSIIDI3FVKND7MO5AGOCXBK2C4ITT5MAL4LSCZF62B4PDOFQCLLNL7AXXSJFGINUYXVGVTDCQ2V7S7W5S234WFXCJ4")
  (check-urn (serapeum:make-octet-vector 0) eris:32kib
             "urn:eris:B4AC3MKL2BYR3E2WPMY2QRA6QZBLY4VNWJEBTSK5KWD66BRIT2EXVQVWY6TWVKJCZLC66RE3T2PKWDU3TBAKZZZIZRBTMP6BSOPE4CRXII"))

;; simple gray stream class for this particular construction.
(defclass null-stream (fundamental-binary-input-stream)
  ((counter :initform 0 :accessor counter)
   (max-counter :initarg :max-counter)))

(defmethod stream-read-sequence ((stream null-stream) seq start end &key)
  (with-slots (counter max-counter) stream
    (if (eql counter max-counter)
        0
        (let ((bytes (if end (- end start) (- (length seq) start))))
          (replace seq (make-array bytes :element-type '(unsigned-byte 8) :initial-element 0) :start1 start :end1 end)
          (setf counter (+ bytes counter))
          bytes))))

(defmacro large-content-test (key block-size urn length)
  `(let* ((stream (make-instance 'null-stream :max-counter ,length))
          (chacha-stream (make-encrypting-stream stream
                                                 :chacha
                                                 :stream
                                                 (ironclad:digest-sequence
                                                  :blake2/256
                                                  ,key)
                                                 :initialization-vector (make-array 8 :element-type '(unsigned-byte 8) :initial-element 0)
                                                 :direction :input)))
     (let ((read-capability (eris-encode chacha-stream ,block-size (lambda (block ref) (declare (ignore ref)) block))))
       (is (equalp (read-capability-to-urn read-capability)
                   ,urn)))))

(test 100MiB
  (large-content-test
   (make-array 24 :element-type '(unsigned-byte 8)
                  :initial-contents
                  #(49 48 48 77 105 66 32 40 98 108 111 99 107 32 115 105 122 101 32 49 75 105 66 41))
   1024
   "urn:eris:BIC6F5EKY2PMXS2VNOKPD3AJGKTQBD3EXSCSLZIENXAXBM7PCTH2TCMF5OKJWAN36N4DFO6JPFZBR3MS7ECOGDYDERIJJ4N5KAQSZS67YY"
   104857600))

(test 1GiB
  (large-content-test
   (make-array 23 :element-type '(unsigned-byte 8)
                  :initial-contents
                  #(49 71 105 66 32 40 98 108 111 99 107 32 115 105 122 101 32 51 50 75 105 66 41))
   32kib
   "urn:eris:B4BL4DKSEOPGMYS2CU2OFNYCH4BGQT774GXKGURLFO5FDXAQQPJGJ35AZR3PEK6CVCV74FVTAXHRSWLUUNYYA46ZPOPDOV2M5NVLBETWVI"
   1073741824))


(defmacro encode-consensus-test (tmpdir data block-size &key (secret (random-data 32)))
  "Test if all the eris-encode methods give the same results."
  `(let ((pathname-encode
           (let ((pathname (merge-pathnames (crypto:byte-array-to-hex-string (crypto:random-data 16))
                                            ,tmpdir)))
             (with-open-file (f pathname
                                :direction :output
                                :element-type 'serapeum:octet
                                :if-does-not-exist :create)
               (write-sequence ,data f))
             (read-capability-to-urn
              (eris-encode pathname
                           ,block-size
                           (lambda (block ref) (declare (ignore ref)) block)
                           :secret ,secret))))
         (file-stream-encode
           (let ((pathname (merge-pathnames (crypto:byte-array-to-hex-string (crypto:random-data 16))
                                            ,tmpdir)))
             (with-open-file (f pathname
                                :direction :output
                                :element-type 'serapeum:octet
                                :if-does-not-exist :create)
               (write-sequence ,data f))
             (read-capability-to-urn
              (with-open-file (f pathname :direction :input
                                          :element-type 'serapeum:octet)
                (eris-encode f
                             ,block-size
                             (lambda (block ref) (declare (ignore ref)) block)
                             :secret ,secret)))))
         (vector-encode
           (read-capability-to-urn
            (eris-encode ,data
                         ,block-size
                         (lambda (block ref) (declare (ignore ref)) block)
                         :secret ,secret)))
         (stream-encode
           (read-capability-to-urn
            (with-octet-input-stream (stream ,data)
              (eris-encode stream
                           ,block-size
                           (lambda (block ref) (declare (ignore ref)) block)
                           :secret ,secret)))))
     (is (serapeum:equalp* vector-encode stream-encode pathname-encode file-stream-encode))))

(test encoding-consensus-tests
  (with-temporary-dir tdir
    (encode-consensus-test tdir (make-octets 1 :element 2) 1024)
    (encode-consensus-test tdir (make-octets 512 :element 2) 1024)
    (encode-consensus-test tdir (make-octets 1023 :element 2) 1024)
    (encode-consensus-test tdir (make-octets 1024 :element 2) 1024)
    (encode-consensus-test tdir (make-octets 16383 :element 2) 1024)
    (encode-consensus-test tdir (make-octets 16384 :element 2) 1024)
    (encode-consensus-test tdir (make-octets 1024 :element 2) 32kib)
    (encode-consensus-test tdir (make-octets 32767 :element 2) 32kib)
    (encode-consensus-test tdir (make-octets 32768 :element 2) 32kib)
    (encode-consensus-test tdir (make-octets 64000 :element 2) 32kib)
    (for-all ((buffer (gen-buffer :length (gen-integer :min 1 :max 70000))))
      (encode-consensus-test tdir buffer 1024)
      (encode-consensus-test tdir buffer 32kib))))


(test encoding-nothing
  (with-temporary-dir tdir
    (encode-consensus-test tdir (make-octets 0) 1024)
    (encode-consensus-test tdir (make-octets 0) 32kib)))


(defmacro encoding-file-pos (tmpdir data pos block-size &key (secret null-secret))
  `(let ((vector-encode (read-capability-to-urn
                         (eris-encode (subseq ,data ,pos)
                                      ,block-size
                                      (lambda (block ref) (declare (ignore ref)) block)
                                      :secret ,secret)))
         (file-stream-encode
           (let ((pathname (merge-pathnames (crypto:byte-array-to-hex-string (crypto:random-data 16))
                                            ,tmpdir)))
             (with-open-file (f pathname
                                :direction :output
                                :element-type 'serapeum:octet
                                :if-does-not-exist :create)
               (write-sequence ,data f))
             (read-capability-to-urn
              (with-open-file (f pathname :direction :input
                                          :element-type 'serapeum:octet)
                (file-position f ,pos)
                (eris-encode f
                             ,block-size
                             (lambda (block ref) (declare (ignore ref)) block)
                             :secret ,secret))))))
     (is (equalp vector-encode file-stream-encode))))

(test encoding-file-position-tests
  (with-temporary-dir tdir
   (encoding-file-pos tdir (make-octets 1024 :element 2) 512 1024)
   (encoding-file-pos tdir (make-octets 1024 :element 2) 1023 1024)
   (encoding-file-pos tdir (make-octets 1024 :element 2) 1 1024)
   (encoding-file-pos tdir (make-octets 32000 :element 2) 1673 32kib)
   (encoding-file-pos tdir (make-octets 32000 :element 2) 31999 32kib)))