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
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1847f77062b9806ede004f21b2e320af73419fc0
User & Date: spaskalev on 2014-12-16 22:56:40.329
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
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
			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 {

			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 err != nil {
					return err
				}



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

				// Handle remaining bytes, if any

				var remaining []byte = data[8-bufferLength:]
				if len(remaining) > 0 {
					// Recurse, calling ourselves with the rest of the bytes
					err = write(data[8-bufferLength:])
					if err != nil {
						return err
					}
				}
			} else {
				// Add the insufficient data to the buffer and return
				ctx.input = append(ctx.input, data...)
				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 {







>









|
|
|
|
|
>
|
<
|

>
>
|
<
<

|
>
|
<
<
|
|
|
|
<
<
|
|
|
<







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 {

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

					return write(nil)
				}
				// ... otherwise just return
				return nil
			}



			// The current buffer + new data overflow the block size
			// Complete the block, flush it ...
			ctx.input = append(ctx.input, data[:blockSize-bufferLength]...)


			err = write(nil)
			if err != nil {
				return err
			}


			// ... 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 {
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
		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{}

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

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

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

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

	if err := cycle(input); 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}




	if err := cycle(input); err != nil {
		t.Error(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 {
	var (
		buf bytes.Buffer
		err error
	)





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









	err = compressor(input)
	if err != nil {
		return err





	}

	// Flush the compressor
	err = compressor(nil)
	if err != nil {
		return err
	}







|
|
|
<
<
<
<
|
<
|
|
<
<
|
|
<
|
<
|
|
|
|
|
|
<
<

>
>
>
|
|
|
|
|
<
<
|
<
<
|
<
<
|





>
>
>
>


>
>
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>







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

var testData = [][]byte{
	[]byte{},
	[]byte{0, 1, 2, 3},




	[]byte{0, 1, 2, 3, 4, 5, 6, 7},

	[]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},


}


func TestCycle(t *testing.T) {

	for i := 0; i < len(testData); i++ {
		if err := cycle(testData[i], len(testData[i])); err != nil {
			t.Error(err)
		}
	}
}



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


}





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

	// 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)
	}

	// All is good :)
	return nil
}







|
|





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\ntrace:  %#x\noutput: %#x\n",
			delta, input, trace, decompressed)
	}

	// All is good :)
	return nil
}