Check-in [1847f77062]
Overview
Comment:Reworked the compressor's buffering code, switched to table testing, add step testing for the compressor. Code coverage at 88.3%
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1847f77062b9806ede004f21b2e320af73419fc0
User & Date: spaskalev on 2014-12-16 22:56:40
Other Links: manifest | tags
Context
2014-12-16
23:29
Removed err variable from compressor check-in: 0f4bc650d1 user: spaskalev tags: trunk
22:56
Reworked the compressor's buffering code, switched to table testing, add step testing for the compressor. Code coverage at 88.3% check-in: 1847f77062 user: spaskalev tags: trunk
16:04
Removed goto from predictor's compressor, added more tests that invoke both compress/decompress check-in: 10013ae789 user: spaskalev tags: trunk
Changes

Modified src/0dev.org/predictor/predictor.go from [0cc123a3c6] to [2d1c692ccb].

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
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







+









-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+

+
+
-
+
-
-

-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
-







			err          error
			blockSize    int = 8
			bufferLength int = len(ctx.input)
		)

		// Force a flush if we are called with no data to write
		if len(data) == 0 {
			// Nothing to flush if the buffer is empty though
			if len(ctx.input) == 0 {
				return nil
			}
			// We can't have more than 7 bytes in the buffer so this is safe
			data, blockSize, bufferLength = ctx.input, len(ctx.input), 0
		}

		// Check if there are pending bytes in the buffer
		if len(data) < blockSize || bufferLength > 0 {
			// Check whether we have enough bytes for a complete block
			if len(data) > 8-bufferLength {
				// Fill the buffer ...
				ctx.input = append(ctx.input, data[:8-bufferLength]...)
				// ... and recurse, calling ourselves with the full buffer
				err = write(ctx.input)

			// If the current buffer + new data can fit into a block
			if (len(data) + bufferLength) <= blockSize {
				ctx.input = append(ctx.input, data...)

				// Flush the block if the buffer fills it
				if len(ctx.input) == blockSize {
				if err != nil {
					return err
					return write(nil)
				}
				// ... otherwise just return
				return nil

			}
				// Clear the buffer
				ctx.input = ctx.input[:0]

				// Handle remaining bytes, if any
				var remaining []byte = data[8-bufferLength:]
			// The current buffer + new data overflow the block size
			// Complete the block, flush it ...
			ctx.input = append(ctx.input, data[:blockSize-bufferLength]...)
				if len(remaining) > 0 {
					// Recurse, calling ourselves with the rest of the bytes
					err = write(data[8-bufferLength:])
					if err != nil {
						return err
					}
			err = write(nil)
			if err != nil {
				return err
			}
				}
			} else {
				// Add the insufficient data to the buffer and return
				ctx.input = append(ctx.input, data...)
				return nil
			// ... and stage the rest of the data in the buffer
			ctx.input = append(ctx.input, data[blockSize-bufferLength:]...)
			return nil
			}
		}

		var buf []byte = make([]byte, 1, blockSize+1)
		for block := 0; block < len(data)/blockSize; block++ {
			for i := 0; i < blockSize; i++ {
				var current byte = data[(block*blockSize)+i]
				if ctx.table[ctx.hash] == current {

Modified src/0dev.org/predictor/predictor_test.go from [717a9810a3] to [73a8f932ed].

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
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







-
-
-
+
+
+
-
-
-
-
-
+
-
-
-
+
+
-
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-

+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
-
-
-
+
-
-
-
+





+
+
+
+


+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+







		func(i, j int) bool { return result[i] == input[j] }})

	if len(delta.Added) > 0 || len(delta.Removed) > 0 {
		t.Error("Unexpected decompressed output", delta)
	}
}

func TestEmptyCycle(t *testing.T) {
	var input []byte = []byte{}

var testData = [][]byte{
	[]byte{},
	[]byte{0, 1, 2, 3},
	if err := cycle(input); err != nil {
		t.Error(err)
	}
}

	[]byte{0, 1, 2, 3, 4, 5, 6, 7},
func TestPartialCycle(t *testing.T) {
	var input []byte = []byte{0, 1, 2, 3}

	[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
	[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
	if err := cycle(input); err != nil {
		t.Error(err)
	}
}
}


func TestBlockCycle(t *testing.T) {
func TestCycle(t *testing.T) {
	var input []byte = []byte{0, 1, 2, 3, 4, 5, 6, 7}

	if err := cycle(input); err != nil {
		t.Error(err)
	}
}

	for i := 0; i < len(testData); i++ {
		if err := cycle(testData[i], len(testData[i])); err != nil {
			t.Error(err)
		}
	}
}
func TestBlockPartialCycle(t *testing.T) {
	var input []byte = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}

func TestStepCycle(t *testing.T) {
	for i := 0; i < len(testData); i++ {
		for j := 1; j < len(testData); j++ {
	if err := cycle(input); err != nil {
		t.Error(err)
	}
}

			if err := cycle(testData[i], j); err != nil {
				t.Error("Error for testData[", i, "], step[", j, "] ", err)
			}
		}
	}
func TestDualBlockCycle(t *testing.T) {
	var input []byte = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}

}
	if err := cycle(input); err != nil {
		t.Error(err)
	}

}

func cycle(input []byte) error {
func cycle(input []byte, step int) error {
	var (
		buf bytes.Buffer
		err error
	)

	if step > len(input) {
		return nil
	}

	// Create a compressor and write the given data
	compressor := Compressor(&buf)

	var data []byte = input
	var trace []byte = make([]byte, 0)

	for len(data) > 0 {
		if step <= len(data) {

			trace = append(trace, data[:step]...)

	err = compressor(input)
	if err != nil {
		return err
			err = compressor(data[:step])
			if err != nil {
				return err
			}
			data = data[step:]
		} else {
			step = len(data)
		}
	}

	// Flush the compressor
	err = compressor(nil)
	if err != nil {
		return err
	}
132
133
134
135
136
137
138
139
140


141
142
143
144
145
136
137
138
139
140
141
142


143
144
145
146
147
148
149







-
-
+
+






	// Diff the result against the initial input
	delta := diff.Diff(diff.D{len(input), len(decompressed),
		func(i, j int) bool { return input[i] == decompressed[j] }})

	// Return a well-formated error if any differences are found
	if len(delta.Added) > 0 || len(delta.Removed) > 0 {
		return fmt.Errorf("Unexpected decompressed output %v\ninput:  %#x\noutput: %#x\n",
			delta, input, decompressed)
		return fmt.Errorf("Unexpected decompressed output %v\ninput:  %#x\ntrace:  %#x\noutput: %#x\n",
			delta, input, trace, decompressed)
	}

	// All is good :)
	return nil
}