mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-21 23:55:13 -05:00
FileRecord improvement: unit test for the rescue program
This commit is contained in:
parent
38aa1a8e77
commit
bfb7583544
@ -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.
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
26
rescuesdriq/rescuesdriq_test.go
Normal file
26
rescuesdriq/rescuesdriq_test.go
Normal file
@ -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)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user