Add a snappytool command that uses the C++ library.

The pi.txt.rawsnappy file was generated by this tool, on an amd64
(little-endian) system.
This commit is contained in:
Nigel Tao 2016-02-25 13:31:42 +11:00
Родитель f1ae40350d
Коммит 343d0f4579
5 изменённых файлов: 111 добавлений и 14 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -1,3 +1,4 @@
cmd/snappytool/snappytool
testdata/bench
# These explicitly listed benchmark data files are for an obsolete version of

74
cmd/snappytool/main.cpp Normal file
Просмотреть файл

@ -0,0 +1,74 @@
/*
To build the snappytool binary:
g++ main.cpp /usr/lib/libsnappy.a -o snappytool
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "snappy.h"
#define N 1000000
char dst[N];
char src[N];
int main(int argc, char** argv) {
// Parse args.
if (argc != 2) {
fprintf(stderr, "exactly one of -d or -e must be given\n");
return 1;
}
bool decode = strcmp(argv[1], "-d") == 0;
bool encode = strcmp(argv[1], "-e") == 0;
if (decode == encode) {
fprintf(stderr, "exactly one of -d or -e must be given\n");
return 1;
}
// Read all of stdin into src[:s].
size_t s = 0;
while (1) {
if (s == N) {
fprintf(stderr, "input too large\n");
return 1;
}
ssize_t n = read(0, src+s, N-s);
if (n == 0) {
break;
}
if (n < 0) {
fprintf(stderr, "read error: %s\n", strerror(errno));
// TODO: handle EAGAIN, EINTR?
return 1;
}
s += n;
}
// Encode or decode src[:s] to dst[:d], and write to stdout.
size_t d = 0;
if (encode) {
if (N < snappy::MaxCompressedLength(s)) {
fprintf(stderr, "input too large after encoding\n");
return 1;
}
snappy::RawCompress(src, s, dst, &d);
} else {
if (!snappy::GetUncompressedLength(src, s, &d)) {
fprintf(stderr, "could not get uncompressed length\n");
return 1;
}
if (N < d) {
fprintf(stderr, "input too large after decoding\n");
return 1;
}
if (!snappy::RawUncompress(src, s, dst)) {
fprintf(stderr, "input was not valid Snappy-compressed data\n");
return 1;
}
}
write(1, dst, d);
return 0;
}

Просмотреть файл

@ -29,13 +29,28 @@ func TestMaxEncodedLenOfMaxBlockSize(t *testing.T) {
}
}
func cmp(a, b []byte) error {
if bytes.Equal(a, b) {
return nil
}
if len(a) != len(b) {
return fmt.Errorf("got %d bytes, want %d", len(a), len(b))
}
for i := range a {
if a[i] != b[i] {
return fmt.Errorf("byte #%d: got 0x%02x, want 0x%02x", i, a[i], b[i])
}
}
return nil
}
func roundtrip(b, ebuf, dbuf []byte) error {
d, err := Decode(dbuf, Encode(ebuf, b))
if err != nil {
return fmt.Errorf("decoding error: %v", err)
}
if !bytes.Equal(b, d) {
return fmt.Errorf("roundtrip mismatch:\n\twant %v\n\tgot %v", b, d)
if err := cmp(d, b); err != nil {
return fmt.Errorf("roundtrip mismatch: %v", err)
}
return nil
}
@ -327,6 +342,24 @@ func TestDecodeLengthOffset(t *testing.T) {
}
}
func TestDecodeGoldenInput(t *testing.T) {
src, err := ioutil.ReadFile("testdata/pi.txt.rawsnappy")
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
got, err := Decode(nil, src)
if err != nil {
t.Fatalf("Decode: %v", err)
}
want, err := ioutil.ReadFile("testdata/pi.txt")
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
if err := cmp(got, want); err != nil {
t.Fatal(err)
}
}
// TestEncodeNoiseThenRepeats encodes input for which the first half is very
// incompressible and the second half is very compressible. The encoded form's
// length should be closer to 50% of the original length than 100%.
@ -348,18 +381,6 @@ func TestEncodeNoiseThenRepeats(t *testing.T) {
}
}
func cmp(a, b []byte) error {
if len(a) != len(b) {
return fmt.Errorf("got %d bytes, want %d", len(a), len(b))
}
for i := range a {
if a[i] != b[i] {
return fmt.Errorf("byte #%d: got 0x%02x, want 0x%02x", i, a[i], b[i])
}
}
return nil
}
func TestFramingFormat(t *testing.T) {
// src is comprised of alternating 1e5-sized sequences of random
// (incompressible) bytes and repeated (compressible) bytes. 1e5 was chosen

1
testdata/pi.txt поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Двоичные данные
testdata/pi.txt.rawsnappy поставляемый Normal file

Двоичный файл не отображается.