FileRecord improvement: unit test for the rescue program

pull/228/head
f4exb 2018-10-09 18:28:59 +02:00
rodzic 38aa1a8e77
commit bfb7583544
3 zmienionych plików z 90 dodań i 60 usunięć

Wyświetl plik

@ -12,9 +12,9 @@ The header is composed as follows:
- Sample size as 16 or 24 bits (4 bytes, 32 bits) - Sample size as 16 or 24 bits (4 bytes, 32 bits)
- filler with all zeroes (4 bytes, 32 bits) - filler with all zeroes (4 bytes, 32 bits)
- CRC32 (IEEE) of the 28 bytes above (4 bytes, 32 bits) - CRC32 (IEEE) of the 28 bytes above (4 bytes, 32 bits)
The header size is 32 bytes in total which is a multiple of 8 bytes thus occupies an integer number of samples whether in 16 or 24 bits mode. When migrating from a pre version 4.2.1 header you may crunch a very small amount of samples. The header size is 32 bytes in total which is a multiple of 8 bytes thus occupies an integer number of samples whether in 16 or 24 bits mode. When migrating from a pre version 4.2.1 header you may crunch a very small amount of samples.
You can replace values in the header with the following options: You can replace values in the header with the following options:
- -sr uint - -sr uint
@ -28,21 +28,21 @@ You can replace values in the header with the following options:
- -sz uint - -sz uint
Sample size (16 or 24) (default 16) Sample size (16 or 24) (default 16)
You need to specify an input file. If no output file is specified the current header values are printed to the console and the program exits: You need to specify an input file. If no output file is specified the current header values are printed to the console and the program exits:
- -in string - -in string
input file (default "foo") input file (default "foo")
To convert to a new file you need to specify the output file: To convert to a new file you need to specify the output file:
- -out string - -out string
output file (default "foo") output file (default "foo")
You can specify a block size in multiples of 4k for the copy. Large blocks will yield a faster copy but a larger output file. With the default of 1 (4k) the copy does not take much time anyway: You can specify a block size in multiples of 4k for the copy. Large blocks will yield a faster copy but a larger output file. With the default of 1 (4k) the copy does not take much time anyway:
- -bz uint - -bz uint
Copy block size in multiple of 4k (default 1) Copy block size in multiple of 4k (default 1)
<h2>Build</h2> <h2>Build</h2>
The program is written in go and is provided only in source code form. Compiling it is very easy: The program is written in go and is provided only in source code form. Compiling it is very easy:
@ -55,5 +55,11 @@ You will usually find a `golang` package in your distribution. For example in Ub
In this directory just do `go build` In this directory just do `go build`
<h3>Unit testing</h3>
Unit test (very simple) is located in `rescuesdriq_test.go`. It uses the [Go Convey](https://github.com/smartystreets/goconvey) framework. You should first install it with:
`go get github.com/smartystreets/goconvey`
You can run unit test from command line with: `go test`
Or with the Go Convey server that you start from this directory with: `$GOPATH/bin/goconvey` where `$GOPATH` is the path to your go installation.

Wyświetl plik

@ -1,41 +1,39 @@
package main package main
import ( import (
"bufio"
"bytes"
"encoding/binary"
"flag" "flag"
"fmt" "fmt"
"bufio" "hash/crc32"
"io" "io"
"os" "os"
"bytes" "time"
"encoding/binary"
"time"
"hash/crc32"
) )
type HeaderStd struct { type HeaderStd struct {
SampleRate uint32 SampleRate uint32
CenterFrequency uint64 CenterFrequency uint64
StartTimestamp int64 StartTimestamp int64
SampleSize uint32 SampleSize uint32
Filler uint32 Filler uint32
CRC32 uint32 CRC32 uint32
} }
func check(e error) { func check(e error) {
if e != nil { if e != nil {
panic(e) panic(e)
} }
} }
func analyze(r *bufio.Reader) HeaderStd { func analyze(r *bufio.Reader) HeaderStd {
headerbuf := make([]byte, 32) // This is a full header with CRC headerbuf := make([]byte, 32) // This is a full header with CRC
n, err := r.Read(headerbuf) n, err := r.Read(headerbuf)
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
panic(err) panic(err)
} }
if (n != 32) { if n != 32 {
panic("Header too small") panic("Header too small")
} }
@ -44,7 +42,7 @@ func analyze(r *bufio.Reader) HeaderStd {
err = binary.Read(headerr, binary.LittleEndian, &header) err = binary.Read(headerr, binary.LittleEndian, &header)
check(err) check(err)
return header return header
} }
func writeHeader(writer *bufio.Writer, header *HeaderStd) { func writeHeader(writer *bufio.Writer, header *HeaderStd) {
@ -62,7 +60,7 @@ func setCRC(header *HeaderStd) {
header.CRC32 = crc32.ChecksumIEEE(bin_buf.Bytes()[0:28]) header.CRC32 = crc32.ChecksumIEEE(bin_buf.Bytes()[0:28])
} }
func getCRC(header *HeaderStd) uint32 { func GetCRC(header *HeaderStd) uint32 {
var bin_buf bytes.Buffer var bin_buf bytes.Buffer
header.Filler = 0 header.Filler = 0
binary.Write(&bin_buf, binary.LittleEndian, header) binary.Write(&bin_buf, binary.LittleEndian, header)
@ -70,13 +68,13 @@ func getCRC(header *HeaderStd) uint32 {
} }
func printHeader(header *HeaderStd) { func printHeader(header *HeaderStd) {
fmt.Println("Sample rate:", header.SampleRate) fmt.Println("Sample rate:", header.SampleRate)
fmt.Println("Frequency :", header.CenterFrequency) fmt.Println("Frequency :", header.CenterFrequency)
fmt.Println("Sample Size:", header.SampleSize) fmt.Println("Sample Size:", header.SampleSize)
tm := time.Unix(header.StartTimestamp, 0) tm := time.Unix(header.StartTimestamp, 0)
fmt.Println("Start :", tm) fmt.Println("Start :", tm)
fmt.Println("CRC32 :", header.CRC32) fmt.Println("CRC32 :", header.CRC32)
fmt.Println("CRC32 OK :", getCRC(header)) fmt.Println("CRC32 OK :", GetCRC(header))
} }
func copyContent(reader *bufio.Reader, writer *bufio.Writer, blockSize uint) { func copyContent(reader *bufio.Reader, writer *bufio.Writer, blockSize uint) {
@ -97,7 +95,7 @@ func copyContent(reader *bufio.Reader, writer *bufio.Writer, blockSize uint) {
} }
} else { } else {
writer.Write(p) writer.Write(p)
sz += int64(blockSize)*4096 sz += int64(blockSize) * 4096
} }
fmt.Printf("Wrote %d bytes\r", sz) fmt.Printf("Wrote %d bytes\r", sz)
@ -107,14 +105,14 @@ func copyContent(reader *bufio.Reader, writer *bufio.Writer, blockSize uint) {
} }
func main() { func main() {
inFileStr := flag.String("in", "foo", "input file") inFileStr := flag.String("in", "foo", "input file")
outFileStr := flag.String("out", "foo", "output file") outFileStr := flag.String("out", "foo", "output file")
sampleRate := flag.Uint("sr", 0, "Sample rate (S/s)") sampleRate := flag.Uint("sr", 0, "Sample rate (S/s)")
centerFreq := flag.Uint64("cf", 0, "Center frequency (Hz)") centerFreq := flag.Uint64("cf", 0, "Center frequency (Hz)")
sampleSize := flag.Uint("sz", 16, "Sample size (16 or 24)") sampleSize := flag.Uint("sz", 16, "Sample size (16 or 24)")
timeStr := flag.String("ts", "", "start time RFC3339 (ex: 2006-01-02T15:04:05Z)") timeStr := flag.String("ts", "", "start time RFC3339 (ex: 2006-01-02T15:04:05Z)")
timeNow := flag.Bool("now", false , "use now for start time") timeNow := flag.Bool("now", false, "use now for start time")
blockSize := flag.Uint("bz", 1, "Copy block size in multiple of 4k") blockSize := flag.Uint("bz", 1, "Copy block size in multiple of 4k")
flag.Parse() flag.Parse()
flagSeen := make(map[string]bool) flagSeen := make(map[string]bool)
@ -123,16 +121,16 @@ func main() {
if flagSeen["in"] { if flagSeen["in"] {
fmt.Println("input file :", *inFileStr) fmt.Println("input file :", *inFileStr)
// open input file // open input file
fi, err := os.Open(*inFileStr) fi, err := os.Open(*inFileStr)
check(err) check(err)
// close fi on exit and check for its returned error // close fi on exit and check for its returned error
defer func() { defer func() {
err := fi.Close(); err := fi.Close()
check(err) check(err)
}() }()
// make a read buffer // make a read buffer
reader := bufio.NewReader(fi) reader := bufio.NewReader(fi)
var headerOrigin HeaderStd = analyze(reader) var headerOrigin HeaderStd = analyze(reader)
printHeader(&headerOrigin) printHeader(&headerOrigin)
@ -150,7 +148,7 @@ func main() {
} }
} else if flagSeen["ts"] { } else if flagSeen["ts"] {
t, err := time.Parse(time.RFC3339, *timeStr) t, err := time.Parse(time.RFC3339, *timeStr)
if (err == nil) { if err == nil {
headerOrigin.StartTimestamp = t.Unix() headerOrigin.StartTimestamp = t.Unix()
} else { } else {
fmt.Println("Incorrect time specified. Defaulting to now") fmt.Println("Incorrect time specified. Defaulting to now")
@ -169,10 +167,10 @@ func main() {
fo, err := os.Create(*outFileStr) fo, err := os.Create(*outFileStr)
check(err) check(err)
defer func() { defer func() {
err := fo.Close(); err := fo.Close()
check(err) check(err)
}() }()
writer := bufio.NewWriter(fo) writer := bufio.NewWriter(fo)

Wyświetl plik

@ -0,0 +1,26 @@
package main
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestSpec(t *testing.T) {
// Only pass t into top-level Convey calls
Convey("Given a header structure", t, func() {
var header HeaderStd
header.SampleRate = 75000
header.CenterFrequency = 435000000
header.StartTimestamp = 1539083921
header.SampleSize = 16
header.Filler = 0
crc32 := GetCRC(&header)
Convey("The CRC32 value should be 2294957931", func() {
So(crc32, ShouldEqual, 2294957931)
})
})
}