Home | History | Annotate | Download | only in flate
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package flate
      6 
      7 import (
      8 	"bytes"
      9 	"strings"
     10 	"testing"
     11 )
     12 
     13 func TestDictDecoder(t *testing.T) {
     14 	const (
     15 		abc  = "ABC\n"
     16 		fox  = "The quick brown fox jumped over the lazy dog!\n"
     17 		poem = "The Road Not Taken\nRobert Frost\n" +
     18 			"\n" +
     19 			"Two roads diverged in a yellow wood,\n" +
     20 			"And sorry I could not travel both\n" +
     21 			"And be one traveler, long I stood\n" +
     22 			"And looked down one as far as I could\n" +
     23 			"To where it bent in the undergrowth;\n" +
     24 			"\n" +
     25 			"Then took the other, as just as fair,\n" +
     26 			"And having perhaps the better claim,\n" +
     27 			"Because it was grassy and wanted wear;\n" +
     28 			"Though as for that the passing there\n" +
     29 			"Had worn them really about the same,\n" +
     30 			"\n" +
     31 			"And both that morning equally lay\n" +
     32 			"In leaves no step had trodden black.\n" +
     33 			"Oh, I kept the first for another day!\n" +
     34 			"Yet knowing how way leads on to way,\n" +
     35 			"I doubted if I should ever come back.\n" +
     36 			"\n" +
     37 			"I shall be telling this with a sigh\n" +
     38 			"Somewhere ages and ages hence:\n" +
     39 			"Two roads diverged in a wood, and I-\n" +
     40 			"I took the one less traveled by,\n" +
     41 			"And that has made all the difference.\n"
     42 	)
     43 
     44 	var poemRefs = []struct {
     45 		dist   int // Backward distance (0 if this is an insertion)
     46 		length int // Length of copy or insertion
     47 	}{
     48 		{0, 38}, {33, 3}, {0, 48}, {79, 3}, {0, 11}, {34, 5}, {0, 6}, {23, 7},
     49 		{0, 8}, {50, 3}, {0, 2}, {69, 3}, {34, 5}, {0, 4}, {97, 3}, {0, 4},
     50 		{43, 5}, {0, 6}, {7, 4}, {88, 7}, {0, 12}, {80, 3}, {0, 2}, {141, 4},
     51 		{0, 1}, {196, 3}, {0, 3}, {157, 3}, {0, 6}, {181, 3}, {0, 2}, {23, 3},
     52 		{77, 3}, {28, 5}, {128, 3}, {110, 4}, {70, 3}, {0, 4}, {85, 6}, {0, 2},
     53 		{182, 6}, {0, 4}, {133, 3}, {0, 7}, {47, 5}, {0, 20}, {112, 5}, {0, 1},
     54 		{58, 3}, {0, 8}, {59, 3}, {0, 4}, {173, 3}, {0, 5}, {114, 3}, {0, 4},
     55 		{92, 5}, {0, 2}, {71, 3}, {0, 2}, {76, 5}, {0, 1}, {46, 3}, {96, 4},
     56 		{130, 4}, {0, 3}, {360, 3}, {0, 3}, {178, 5}, {0, 7}, {75, 3}, {0, 3},
     57 		{45, 6}, {0, 6}, {299, 6}, {180, 3}, {70, 6}, {0, 1}, {48, 3}, {66, 4},
     58 		{0, 3}, {47, 5}, {0, 9}, {325, 3}, {0, 1}, {359, 3}, {318, 3}, {0, 2},
     59 		{199, 3}, {0, 1}, {344, 3}, {0, 3}, {248, 3}, {0, 10}, {310, 3}, {0, 3},
     60 		{93, 6}, {0, 3}, {252, 3}, {157, 4}, {0, 2}, {273, 5}, {0, 14}, {99, 4},
     61 		{0, 1}, {464, 4}, {0, 2}, {92, 4}, {495, 3}, {0, 1}, {322, 4}, {16, 4},
     62 		{0, 3}, {402, 3}, {0, 2}, {237, 4}, {0, 2}, {432, 4}, {0, 1}, {483, 5},
     63 		{0, 2}, {294, 4}, {0, 2}, {306, 3}, {113, 5}, {0, 1}, {26, 4}, {164, 3},
     64 		{488, 4}, {0, 1}, {542, 3}, {248, 6}, {0, 5}, {205, 3}, {0, 8}, {48, 3},
     65 		{449, 6}, {0, 2}, {192, 3}, {328, 4}, {9, 5}, {433, 3}, {0, 3}, {622, 25},
     66 		{615, 5}, {46, 5}, {0, 2}, {104, 3}, {475, 10}, {549, 3}, {0, 4}, {597, 8},
     67 		{314, 3}, {0, 1}, {473, 6}, {317, 5}, {0, 1}, {400, 3}, {0, 3}, {109, 3},
     68 		{151, 3}, {48, 4}, {0, 4}, {125, 3}, {108, 3}, {0, 2},
     69 	}
     70 
     71 	var got, want bytes.Buffer
     72 	var dd dictDecoder
     73 	dd.init(1<<11, nil)
     74 
     75 	var writeCopy = func(dist, length int) {
     76 		for length > 0 {
     77 			cnt := dd.tryWriteCopy(dist, length)
     78 			if cnt == 0 {
     79 				cnt = dd.writeCopy(dist, length)
     80 			}
     81 
     82 			length -= cnt
     83 			if dd.availWrite() == 0 {
     84 				got.Write(dd.readFlush())
     85 			}
     86 		}
     87 	}
     88 	var writeString = func(str string) {
     89 		for len(str) > 0 {
     90 			cnt := copy(dd.writeSlice(), str)
     91 			str = str[cnt:]
     92 			dd.writeMark(cnt)
     93 			if dd.availWrite() == 0 {
     94 				got.Write(dd.readFlush())
     95 			}
     96 		}
     97 	}
     98 
     99 	writeString(".")
    100 	want.WriteByte('.')
    101 
    102 	str := poem
    103 	for _, ref := range poemRefs {
    104 		if ref.dist == 0 {
    105 			writeString(str[:ref.length])
    106 		} else {
    107 			writeCopy(ref.dist, ref.length)
    108 		}
    109 		str = str[ref.length:]
    110 	}
    111 	want.WriteString(poem)
    112 
    113 	writeCopy(dd.histSize(), 33)
    114 	want.Write(want.Bytes()[:33])
    115 
    116 	writeString(abc)
    117 	writeCopy(len(abc), 59*len(abc))
    118 	want.WriteString(strings.Repeat(abc, 60))
    119 
    120 	writeString(fox)
    121 	writeCopy(len(fox), 9*len(fox))
    122 	want.WriteString(strings.Repeat(fox, 10))
    123 
    124 	writeString(".")
    125 	writeCopy(1, 9)
    126 	want.WriteString(strings.Repeat(".", 10))
    127 
    128 	writeString(strings.ToUpper(poem))
    129 	writeCopy(len(poem), 7*len(poem))
    130 	want.WriteString(strings.Repeat(strings.ToUpper(poem), 8))
    131 
    132 	writeCopy(dd.histSize(), 10)
    133 	want.Write(want.Bytes()[want.Len()-dd.histSize():][:10])
    134 
    135 	got.Write(dd.readFlush())
    136 	if got.String() != want.String() {
    137 		t.Errorf("final string mismatch:\ngot  %q\nwant %q", got.String(), want.String())
    138 	}
    139 }
    140