av/codec/h264/decode/bits/bitreader_test.go

312 lines
6.8 KiB
Go

/*
DESCRIPTION
bitreader_test.go provides testing for functionality defined in bitreader.go.
AUTHORS
Saxon Nelson-Milton <saxon@ausocean.org>, The Australian Ocean Laboratory (AusOcean)
LICENSE
Copyright (C) 2017-2018 the Australian Ocean Lab (AusOcean)
It is free software: you can redistribute it and/or modify them
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
It is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
in gpl.txt. If not, see http://www.gnu.org/licenses.
*/
package bits
import (
"bytes"
"fmt"
"io"
"reflect"
"testing"
)
func TestReadBits(t *testing.T) {
tests := []struct {
in []byte // The bytes the source io.Reader will be initialised with.
n []int // The values of n for the reads we wish to do.
want []uint64 // The results we expect for each ReadBits call.
err []error // The error expected from each ReadBits call.
}{
{
in: []byte{0xff},
n: []int{8},
want: []uint64{0xff},
err: []error{nil},
},
{
in: []byte{0xff},
n: []int{4, 4},
want: []uint64{0x0f, 0x0f},
err: []error{nil, nil},
},
{
in: []byte{0xff},
n: []int{1, 7},
want: []uint64{0x01, 0x7f},
err: []error{nil, nil},
},
{
in: []byte{0xff, 0xff},
n: []int{8, 8},
want: []uint64{0xff, 0xff},
err: []error{nil, nil},
},
{
in: []byte{0xff, 0xff},
n: []int{8, 10},
want: []uint64{0xff, 0},
err: []error{nil, io.ErrUnexpectedEOF},
},
{
in: []byte{0xff, 0xff},
n: []int{4, 8, 4},
want: []uint64{0x0f, 0xff, 0x0f},
err: []error{nil, nil, nil},
},
{
in: []byte{0xff, 0xff},
n: []int{16},
want: []uint64{0xffff},
err: []error{nil},
},
{
in: []byte{0x8f, 0xe3},
n: []int{4, 2, 4, 6},
want: []uint64{0x8, 0x3, 0xf, 0x23},
err: []error{nil, nil, nil, nil},
},
}
for i, test := range tests {
br := NewBitReader(bytes.NewReader(test.in))
// For each value of n defined in test.reads, we call br.ReadBits, collect
// the result and check the error.
var got []uint64
for j, n := range test.n {
bits, err := br.ReadBits(n)
if err != test.err[j] {
t.Fatalf("did not expect error: %v for read: %d test: %d", err, j, i)
}
got = append(got, bits)
}
// Now we can check the read results.
if !reflect.DeepEqual(got, test.want) {
t.Errorf("did not get expected results from ReadBits for test: %d\nGot: %v\nWant: %v\n", i, got, test.want)
}
}
}
func TestPeekBits(t *testing.T) {
tests := []struct {
in []byte
n []int
want []uint64
err []error
}{
{
in: []byte{0xff},
n: []int{8},
want: []uint64{0xff},
err: []error{nil},
},
{
in: []byte{0x8f, 0xe3},
n: []int{4, 8, 16},
want: []uint64{0x8, 0x8f, 0x8fe3},
err: []error{nil, nil, nil},
},
{
in: []byte{0x8f, 0xe3, 0x8f, 0xe3},
n: []int{32},
want: []uint64{0x8fe38fe3},
err: []error{nil},
},
{
in: []byte{0x8f, 0xe3},
n: []int{3, 5, 10},
want: []uint64{0x4, 0x11, 0x23f},
err: []error{nil, nil, nil},
},
{
in: []byte{0x8f, 0xe3},
n: []int{3, 20, 10},
want: []uint64{0x4, 0, 0x23f},
err: []error{nil, io.ErrUnexpectedEOF, nil},
},
}
for i, test := range tests {
br := NewBitReader(bytes.NewReader(test.in))
// Call PeekBits for each value of n defined in test.
var got []uint64
for j, n := range test.n {
bits, err := br.PeekBits(n)
if err != test.err[j] {
t.Fatalf("did not expect error: %v for peek: %d test: %d", err, j, i)
}
got = append(got, bits)
}
// Now we can check the peek results.
if !reflect.DeepEqual(got, test.want) {
t.Errorf("did not get expected results from PeekBits for test: %d\nGot: %v\nWant: %v\n", i, got, test.want)
}
}
}
func TestReadOrPeek(t *testing.T) {
// The possible operations we might make.
const (
read = iota
peek
)
tests := []struct {
in []byte // The bytes the source io.Reader will be initialised with.
op []int // The series of operations we want to perform (read or peek).
n []int // The values of n for the reads/peeks we wish to do.
want []uint64 // The results we expect for each ReadBits call.
}{
{
in: []byte{0x8f, 0xe3, 0x8f, 0xe3},
op: []int{read, peek, peek, read, peek},
n: []int{13, 3, 3, 7, 12},
want: []uint64{0x11fc, 0x3, 0x3, 0x38, 0xfe3},
},
}
for i, test := range tests {
br := NewBitReader(bytes.NewReader(test.in))
var (
bits uint64
got []uint64
err error
)
// Go through the operations we wish to perform for this test and collect
// results/errors.
for j, op := range test.op {
switch op {
case read:
bits, err = br.ReadBits(test.n[j])
case peek:
bits, err = br.PeekBits(test.n[j])
default:
panic(fmt.Sprintf("bad test: invalid operation: %d", op))
}
got = append(got, bits)
if err != nil {
t.Fatalf("did not expect error: %v for operation: %d test: %d", err, j, i)
}
}
// Now we can check the results from the reads/peeks.
if !reflect.DeepEqual(got, test.want) {
t.Errorf("did not get expected results for test: %d\nGot: %v\nWant: %v\n", i, got, test.want)
}
}
}
func TestByteAligned(t *testing.T) {
tests := []struct {
in []byte
n []int
want bool
}{
{
in: []byte{0xff},
n: []int{1},
want: false,
},
{
in: []byte{0xff},
n: []int{2},
want: false,
},
{
in: []byte{0xff},
n: []int{3},
want: false,
},
{
in: []byte{0xff},
n: []int{4},
want: false,
},
{
in: []byte{0xff},
n: []int{5},
want: false,
},
{
in: []byte{0xff},
n: []int{6},
want: false,
},
{
in: []byte{0xff},
n: []int{7},
want: false,
},
{
in: []byte{0xff},
n: []int{8},
want: true,
},
{
in: []byte{0xff, 0xff},
n: []int{9},
want: false,
},
{
in: []byte{0xff, 0xff},
n: []int{16},
want: true,
},
{
in: []byte{0xff, 0xff},
n: []int{5, 2},
want: false,
},
{
in: []byte{0xff, 0xff},
n: []int{5, 3},
want: true,
},
}
for i, test := range tests {
br := NewBitReader(bytes.NewReader(test.in))
// Call ReadBits for each value of n defined in test.
for j, n := range test.n {
_, err := br.ReadBits(n)
if err != nil {
t.Fatalf("did not expect error: %v for ReadBits: %d test: %d", err, j, i)
}
}
// Now check br.ByteAligned.
got := br.ByteAligned()
if got != test.want {
t.Errorf("did not get expected results from ByteAligned for test: %d\nGot: %v\nWant: %v\n", i, got, test.want)
}
}
}