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
...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
		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
	}
................................................................................

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







|
|
<
>
|
|
|


|
|
<
<
>
|
>



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





>
>
>
>


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







 







|
|





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
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
		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
	}
................................................................................

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