/* DESCRIPTION bitreader_test.go provides testing for functionality defined in bitreader.go. AUTHORS Saxon Nelson-Milton , 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) } } }