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

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