mirror of
https://github.com/on4kjm/FLEcli.git
synced 2025-01-18 13:01:09 +01:00
Merge branch 'master' into 101-support-multiple-sota-in-same-input-file
This commit is contained in:
commit
a826d8400d
15 changed files with 505 additions and 1 deletions
|
@ -52,6 +52,14 @@ var adifCmd = &cobra.Command{
|
|||
return fmt.Errorf("Too many arguments.%s", "")
|
||||
}
|
||||
|
||||
// Verify given output directory exists. This check should be performed
|
||||
// Before running any long process so as to not make the user wait and
|
||||
// then be notified the file cannot be written.
|
||||
dirErr := CheckDir(outputFilename)
|
||||
if dirErr != nil {
|
||||
return dirErr
|
||||
}
|
||||
|
||||
var adifParam = new(fleprocess.AdifParams)
|
||||
adifParam.InputFilename = inputFilename
|
||||
adifParam.OutputFilename = outputFilename
|
||||
|
|
75
flecmd/adif_test.go
Normal file
75
flecmd/adif_test.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
Copyright © 2024 Jean-Marc Meessen jean-marc@meessen-web.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
package flecmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_AdifWithoutParmMustFail(t *testing.T) {
|
||||
actual := new(bytes.Buffer)
|
||||
rootCmd.SetOut(actual)
|
||||
rootCmd.SetErr(actual)
|
||||
rootCmd.SetArgs([]string{"adif"})
|
||||
error := rootCmd.Execute()
|
||||
|
||||
assert.Error(t, error, "Function call should have failed")
|
||||
|
||||
// Error is expected
|
||||
expectedMsg := "Error: missing input file "
|
||||
lines := strings.Split(actual.String(), "\n")
|
||||
assert.Equal(t, expectedMsg, lines[0], "Function did not fail for the expected cause")
|
||||
}
|
||||
|
||||
func Test_AdifWithToManyParmMustFail(t *testing.T) {
|
||||
actual := new(bytes.Buffer)
|
||||
rootCmd.SetOut(actual)
|
||||
rootCmd.SetErr(actual)
|
||||
rootCmd.SetArgs([]string{"adif", "param1", "param2", "param3"})
|
||||
error := rootCmd.Execute()
|
||||
|
||||
assert.Error(t, error, "Function call should have failed")
|
||||
|
||||
// Error is expected
|
||||
expectedMsg := "Error: Too many arguments."
|
||||
lines := strings.Split(actual.String(), "\n")
|
||||
assert.Equal(t, expectedMsg, lines[0], "Function did not fail for the expected cause")
|
||||
}
|
||||
|
||||
func Test_AdifBadOutpoutDirMustFail(t *testing.T) {
|
||||
actual := new(bytes.Buffer)
|
||||
rootCmd.SetOut(actual)
|
||||
rootCmd.SetErr(actual)
|
||||
rootCmd.SetArgs([]string{"adif", "../test/data/fle-1.txt", "badDirectory/outputfile.adi"})
|
||||
error := rootCmd.Execute()
|
||||
|
||||
assert.Error(t, error, "Function call should have failed")
|
||||
|
||||
// Error is expected
|
||||
expectedMsg := "Error: The directory of specified output file (badDirectory) does not exist."
|
||||
lines := strings.Split(actual.String(), "\n")
|
||||
assert.Equal(t, expectedMsg, lines[0], "Function did not fail for the expected cause")
|
||||
}
|
|
@ -51,6 +51,14 @@ func csvCmdConstructor() *cobra.Command {
|
|||
return fmt.Errorf("Too many arguments.%s", "")
|
||||
}
|
||||
|
||||
// Verify given output directory exists. This check should be performed
|
||||
// Before running any long process so as to not make the user wait and
|
||||
// then be notified the file cannot be written.
|
||||
dirErr := CheckDir(outputCsvFilename)
|
||||
if dirErr != nil {
|
||||
return dirErr
|
||||
}
|
||||
|
||||
if err := fleprocess.ProcessCsvCommand(inputFilename, outputCsvFilename, isInterpolateTime, isOverwriteCsv); err != nil {
|
||||
fmt.Println("\nUnable to generate CSV file:")
|
||||
fmt.Println(err)
|
||||
|
|
75
flecmd/csv_test.go
Normal file
75
flecmd/csv_test.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
Copyright © 2024 Jean-Marc Meessen jean-marc@meessen-web.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
package flecmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_CsvWithoutParmMustFail(t *testing.T) {
|
||||
actual := new(bytes.Buffer)
|
||||
rootCmd.SetOut(actual)
|
||||
rootCmd.SetErr(actual)
|
||||
rootCmd.SetArgs([]string{"csv"})
|
||||
error := rootCmd.Execute()
|
||||
|
||||
assert.Error(t, error, "Function call should have failed")
|
||||
|
||||
// Error is expected
|
||||
expectedMsg := "Error: Missing input file "
|
||||
lines := strings.Split(actual.String(), "\n")
|
||||
assert.Equal(t, expectedMsg, lines[0], "Function did not fail for the expected cause")
|
||||
}
|
||||
|
||||
func Test_CsvWithToManyParmMustFail(t *testing.T) {
|
||||
actual := new(bytes.Buffer)
|
||||
rootCmd.SetOut(actual)
|
||||
rootCmd.SetErr(actual)
|
||||
rootCmd.SetArgs([]string{"csv", "param1", "param2", "param3"})
|
||||
error := rootCmd.Execute()
|
||||
|
||||
assert.Error(t, error, "Function call should have failed")
|
||||
|
||||
// Error is expected
|
||||
expectedMsg := "Error: Too many arguments."
|
||||
lines := strings.Split(actual.String(), "\n")
|
||||
assert.Equal(t, expectedMsg, lines[0], "Function did not fail for the expected cause")
|
||||
}
|
||||
|
||||
func Test_CsvBadOutpoutDirMustFail(t *testing.T) {
|
||||
actual := new(bytes.Buffer)
|
||||
rootCmd.SetOut(actual)
|
||||
rootCmd.SetErr(actual)
|
||||
rootCmd.SetArgs([]string{"csv", "../test/data/fle-1.txt", "badDirectory/outputfile.adi"})
|
||||
error := rootCmd.Execute()
|
||||
|
||||
assert.Error(t, error, "Function call should have failed")
|
||||
|
||||
// Error is expected
|
||||
expectedMsg := "Error: The directory of specified output file (badDirectory) does not exist."
|
||||
lines := strings.Split(actual.String(), "\n")
|
||||
assert.Equal(t, expectedMsg, lines[0], "Function did not fail for the expected cause")
|
||||
}
|
|
@ -25,6 +25,7 @@ THE SOFTWARE.
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -83,3 +84,15 @@ func initConfig() {
|
|||
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
||||
}
|
||||
}
|
||||
|
||||
// CheckDir verifies a given path/file string actually exists. If it does not
|
||||
// then exit with an error.
|
||||
func CheckDir(file string) error {
|
||||
path := filepath.Dir(file)
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("The directory of specified output file (%s) does not exist.", path)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
53
flecmd/root_test.go
Normal file
53
flecmd/root_test.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright © 2024 Jean-Marc Meessen jean-marc@meessen-web.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
package flecmd
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCheckDir(t *testing.T) {
|
||||
type args struct {
|
||||
file string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"Valid directory",
|
||||
args{file: "../test/data/fle-1.txt"},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Invalid directory",
|
||||
args{file: "../junkDir/fle-1.txt"},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := CheckDir(tt.args.file); (err != nil) != tt.wantErr {
|
||||
t.Errorf("CheckDir() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -93,6 +93,13 @@ func buildAdif(fullLog []LogLine, adifParams AdifParams) (adifList []string) {
|
|||
if logLine.MyGrid != "" {
|
||||
adifLine.WriteString(adifElement("MY_GRIDSQUARE", logLine.MyGrid))
|
||||
}
|
||||
|
||||
if logLine.MyLat != "" {
|
||||
adifLine.WriteString(adifElement("MY_LAT", logLine.MyLat))
|
||||
}
|
||||
if logLine.MyLon != "" {
|
||||
adifLine.WriteString(adifElement("MY_LON", logLine.MyLon))
|
||||
}
|
||||
if logLine.MyCounty != "" {
|
||||
adifLine.WriteString(adifElement("MY_CNTY", logLine.MyCounty))
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ func Test_buildAdif(t *testing.T) {
|
|||
sampleFilledLogPOTA2 := []LogLine{
|
||||
{MyCall: "ON4KJM/P", Call: "S57LC", Date: "2020-05-24", MyGrid: "JO40eu", Time: "1310", Band: "20m", Frequency: "14.045", Mode: "CW", RSTsent: "599", RSTrcvd: "599", GridLoc: "JO50", MyPOTA: "ON-00259", Operator: "ON4KJM", Nickname: "ON-00259-1"},
|
||||
{MyCall: "ON4KJM/P", Call: "ON4LY", Date: "2020-05-24", MyGrid: "JO40eu", Time: "1312", Band: "20m", Mode: "CW", RSTsent: "559", RSTrcvd: "599", MyPOTA: "ON-00259", Operator: "ON4KJM", POTA: "DL-00001"},
|
||||
{MyCall: "ON4KJM/P", Call: "ON4LY", Date: "2020-05-24", MyGrid: "JO40eu", Time: "1312", Band: "20m", Mode: "CW", RSTsent: "559", RSTrcvd: "599", MyPOTA: "ON-00259", Operator: "ON4KJM", POTA: "DL-00001", MyLat: "15.1234567", MyLon: "-123.1234567"},
|
||||
}
|
||||
|
||||
expectedOutputPOTA2 := []string{
|
||||
|
@ -120,6 +121,7 @@ func Test_buildAdif(t *testing.T) {
|
|||
"<EOH>",
|
||||
"<STATION_CALLSIGN:8>ON4KJM/P <CALL:5>S57LC <QSO_DATE:8>20200524 <TIME_ON:4>1310 <BAND:3>20m <MODE:2>CW <FREQ:6>14.045 <RST_SENT:3>599 <RST_RCVD:3>599 <GRIDSQUARE:4>JO50 <MY_SIG:4>POTA <MY_SIG_INFO:8>ON-00259 <OPERATOR:6>ON4KJM <MY_GRIDSQUARE:6>JO40eu <APP_EQSL_QTH_NICKNAME:10>ON-00259-1 <EOR>",
|
||||
"<STATION_CALLSIGN:8>ON4KJM/P <CALL:5>ON4LY <QSO_DATE:8>20200524 <TIME_ON:4>1312 <BAND:3>20m <MODE:2>CW <RST_SENT:3>559 <RST_RCVD:3>599 <MY_SIG:4>POTA <MY_SIG_INFO:8>ON-00259 <SIG:4>POTA <SIG_INFO:8>DL-00001 <OPERATOR:6>ON4KJM <MY_GRIDSQUARE:6>JO40eu <EOR>",
|
||||
"<STATION_CALLSIGN:8>ON4KJM/P <CALL:5>ON4LY <QSO_DATE:8>20200524 <TIME_ON:4>1312 <BAND:3>20m <MODE:2>CW <RST_SENT:3>559 <RST_RCVD:3>599 <MY_SIG:4>POTA <MY_SIG_INFO:8>ON-00259 <SIG:4>POTA <SIG_INFO:8>DL-00001 <OPERATOR:6>ON4KJM <MY_GRIDSQUARE:6>JO40eu <MY_LAT:10>15.1234567 <MY_LON:12>-123.1234567 <EOR>",
|
||||
}
|
||||
|
||||
type args struct {
|
||||
|
|
|
@ -79,6 +79,14 @@ func SprintHeaderValues(logLine LogLine) string {
|
|||
output.WriteString("MyGrid " + logLine.MyGrid + "\n")
|
||||
}
|
||||
|
||||
if logLine.MyLat != "" {
|
||||
output.WriteString("MyLat " + logLine.MyLat + "\n")
|
||||
}
|
||||
|
||||
if logLine.MyLon != "" {
|
||||
output.WriteString("MyLon " + logLine.MyLon + "\n")
|
||||
}
|
||||
|
||||
if logLine.MyCounty != "" {
|
||||
output.WriteString("MyCounty " + logLine.MyCounty + "\n")
|
||||
}
|
||||
|
|
|
@ -64,6 +64,8 @@ func LoadFile(inputFilename string, isInterpolateTime bool) (filleFullLog []LogL
|
|||
regexpHeaderMySota := regexp.MustCompile(`(?i)^mysota\s+`)
|
||||
regexpHeaderMyPota := regexp.MustCompile(`(?i)^mypota\s+`)
|
||||
regexpHeaderMyGrid := regexp.MustCompile(`(?i)^mygrid\s+`)
|
||||
regexpHeaderMyLat := regexp.MustCompile(`(?i)^mylat\s+`)
|
||||
regexpHeaderMyLon := regexp.MustCompile(`(?i)^mylon\s+`)
|
||||
regexpHeaderMyCounty := regexp.MustCompile(`(?i)^mycounty\s+`)
|
||||
regexpHeaderQslMsg := regexp.MustCompile(`(?i)^qslmsg\s+`)
|
||||
regexpHeaderNickname := regexp.MustCompile(`(?i)^nickname\s+`)
|
||||
|
@ -74,6 +76,8 @@ func LoadFile(inputFilename string, isInterpolateTime bool) (filleFullLog []LogL
|
|||
headerMySOTA := ""
|
||||
headerMyPOTA := ""
|
||||
headerMyGrid := ""
|
||||
headerMyLat := ""
|
||||
headerMyLon := ""
|
||||
headerMyCounty := ""
|
||||
headerQslMsg := ""
|
||||
headerNickname := ""
|
||||
|
@ -249,6 +253,44 @@ func LoadFile(inputFilename string, isInterpolateTime bool) (filleFullLog []LogL
|
|||
continue
|
||||
}
|
||||
|
||||
//My Lat
|
||||
if regexpHeaderMyLat.MatchString(eachline) {
|
||||
//Attempt to redefine value
|
||||
if headerMyLat != "" {
|
||||
errorLog = append(errorLog, fmt.Sprintf("Attempt to redefine MyLat at line %d", lineCount))
|
||||
continue
|
||||
}
|
||||
errorMsg := ""
|
||||
myLatList := regexpHeaderMyLat.Split(eachline, -1)
|
||||
if len(strings.TrimSpace(myLatList[1])) > 0 {
|
||||
headerMyLat, errorMsg = ValidateLat(strings.TrimSpace(myLatList[1]))
|
||||
if len(errorMsg) != 0 {
|
||||
errorLog = append(errorLog, fmt.Sprintf("Invalid \"My Lat\" at line %d: %s (%s)", lineCount, myLatList[1], errorMsg))
|
||||
}
|
||||
}
|
||||
//If there is no data after the marker, we just skip the data.
|
||||
continue
|
||||
}
|
||||
|
||||
//My Lon
|
||||
if regexpHeaderMyLon.MatchString(eachline) {
|
||||
//Attempt to redefine value
|
||||
if headerMyLon != "" {
|
||||
errorLog = append(errorLog, fmt.Sprintf("Attempt to redefine MyLon at line %d", lineCount))
|
||||
continue
|
||||
}
|
||||
errorMsg := ""
|
||||
myLonList := regexpHeaderMyLon.Split(eachline, -1)
|
||||
if len(strings.TrimSpace(myLonList[1])) > 0 {
|
||||
headerMyLon, errorMsg = ValidateLon(strings.TrimSpace(myLonList[1]))
|
||||
if len(errorMsg) != 0 {
|
||||
errorLog = append(errorLog, fmt.Sprintf("Invalid \"My Lon\" at line %d: %s (%s)", lineCount, myLonList[1], errorMsg))
|
||||
}
|
||||
}
|
||||
//If there is no data after the marker, we just skip the data.
|
||||
continue
|
||||
}
|
||||
|
||||
//My County
|
||||
if regexpHeaderMyCounty.MatchString(eachline) {
|
||||
myMyCountyList := regexpHeaderMyCounty.Split(eachline, -1)
|
||||
|
@ -298,6 +340,8 @@ func LoadFile(inputFilename string, isInterpolateTime bool) (filleFullLog []LogL
|
|||
previousLogLine.MyPOTA = headerMyPOTA
|
||||
previousLogLine.MySOTA = headerMySOTA
|
||||
previousLogLine.MyGrid = headerMyGrid
|
||||
previousLogLine.MyLat = headerMyLat
|
||||
previousLogLine.MyLon = headerMyLon
|
||||
previousLogLine.MyCounty = headerMyCounty
|
||||
previousLogLine.QSLmsg = headerQslMsg //previousLogLine.QslMsg is redundant
|
||||
previousLogLine.Nickname = headerNickname
|
||||
|
|
|
@ -44,6 +44,8 @@ func TestLoadFile_happyCase(t *testing.T) {
|
|||
dataArray = append(dataArray, "mySota on/on-001")
|
||||
dataArray = append(dataArray, "myPota k-0802")
|
||||
dataArray = append(dataArray, "myGrid jo50")
|
||||
dataArray = append(dataArray, "myLat 55.5555555")
|
||||
dataArray = append(dataArray, "myLon -120.01234567")
|
||||
dataArray = append(dataArray, "myCounty Ham County")
|
||||
dataArray = append(dataArray, "QslMsg This is a QSL message")
|
||||
dataArray = append(dataArray, " ")
|
||||
|
@ -86,6 +88,14 @@ func TestLoadFile_happyCase(t *testing.T) {
|
|||
if loadedLogFile[0].MySOTA != expectedValue {
|
||||
t.Errorf("Not the expected MySOTA value: %s (expecting %s)", loadedLogFile[0].MySOTA, expectedValue)
|
||||
}
|
||||
expectedValue = "55.5555555"
|
||||
if loadedLogFile[0].MyLat != expectedValue {
|
||||
t.Errorf("Not the expected MyLat value: %s (expecting %s)", loadedLogFile[0].MyLat, expectedValue)
|
||||
}
|
||||
expectedValue = "-120.01234567"
|
||||
if loadedLogFile[0].MyLon != expectedValue {
|
||||
t.Errorf("Not the expected MyLon value: %s (expecting %s)", loadedLogFile[0].MyLon, expectedValue)
|
||||
}
|
||||
expectedValue = "This is a QSL message"
|
||||
if loadedLogFile[0].QSLmsg != expectedValue {
|
||||
t.Errorf("Not the expected QSL Message from Header value: %s (expecting %s)", loadedLogFile[0].QSLmsg, expectedValue)
|
||||
|
@ -388,6 +398,166 @@ func TestLoadFile_happyCase_day(t *testing.T) {
|
|||
os.Remove(temporaryDataFileName)
|
||||
}
|
||||
|
||||
func TestLoadFile_redefining_myLat_must_fail(t *testing.T) {
|
||||
|
||||
//Given
|
||||
dataArray := make([]string, 0)
|
||||
dataArray = append(dataArray, "# Header")
|
||||
dataArray = append(dataArray, "myCall on4kjm/p")
|
||||
dataArray = append(dataArray, "operator on4kjm")
|
||||
dataArray = append(dataArray, "nickname Portable")
|
||||
dataArray = append(dataArray, "myLat -55.55")
|
||||
dataArray = append(dataArray, " ")
|
||||
dataArray = append(dataArray, " #Log")
|
||||
dataArray = append(dataArray, "20/5/23")
|
||||
dataArray = append(dataArray, "40m cw 0950 ik5zve/5 9 5")
|
||||
dataArray = append(dataArray, "myLat 55.55")
|
||||
|
||||
temporaryDataFileName := createTestFile(dataArray)
|
||||
|
||||
//When
|
||||
loadedLogFile, isLoadedOK := LoadFile(temporaryDataFileName, true)
|
||||
|
||||
//Then
|
||||
if isLoadedOK {
|
||||
t.Error("Test file processing should return with an error")
|
||||
}
|
||||
if len(loadedLogFile) == 0 {
|
||||
t.Error("No data loaded")
|
||||
}
|
||||
|
||||
expectedValue := "-55.55"
|
||||
if loadedLogFile[0].MyLat != expectedValue {
|
||||
t.Errorf("Not the expected MyLat value: %s (expecting %s)", loadedLogFile[0].MyLat, expectedValue)
|
||||
}
|
||||
|
||||
//Clean Up
|
||||
os.Remove(temporaryDataFileName)
|
||||
}
|
||||
|
||||
func TestLoadFile_redefining_myLon_must_fail(t *testing.T) {
|
||||
|
||||
//Given
|
||||
dataArray := make([]string, 0)
|
||||
dataArray = append(dataArray, "# Header")
|
||||
dataArray = append(dataArray, "myCall on4kjm/p")
|
||||
dataArray = append(dataArray, "operator on4kjm")
|
||||
dataArray = append(dataArray, "nickname Portable")
|
||||
dataArray = append(dataArray, "myLon -55.55")
|
||||
dataArray = append(dataArray, " ")
|
||||
dataArray = append(dataArray, " #Log")
|
||||
dataArray = append(dataArray, "20/5/23")
|
||||
dataArray = append(dataArray, "40m cw 0950 ik5zve/5 9 5")
|
||||
dataArray = append(dataArray, "myLon 55.55")
|
||||
|
||||
temporaryDataFileName := createTestFile(dataArray)
|
||||
|
||||
//When
|
||||
loadedLogFile, isLoadedOK := LoadFile(temporaryDataFileName, true)
|
||||
|
||||
//Then
|
||||
if isLoadedOK {
|
||||
t.Error("Test file processing should return with an error")
|
||||
}
|
||||
if len(loadedLogFile) == 0 {
|
||||
t.Error("No data loaded")
|
||||
}
|
||||
|
||||
expectedValue := "-55.55"
|
||||
if loadedLogFile[0].MyLon != expectedValue {
|
||||
t.Errorf("Not the expected MyLon value: %s (expecting %s)", loadedLogFile[0].MyLon, expectedValue)
|
||||
}
|
||||
|
||||
//Clean Up
|
||||
os.Remove(temporaryDataFileName)
|
||||
}
|
||||
|
||||
func Outofrange_myLonHelper(t *testing.T, val string) {
|
||||
//Given
|
||||
dataArray := make([]string, 0)
|
||||
dataArray = append(dataArray, "# Header")
|
||||
dataArray = append(dataArray, "myCall on4kjm/p")
|
||||
dataArray = append(dataArray, "operator on4kjm")
|
||||
dataArray = append(dataArray, "nickname Portable")
|
||||
dataArray = append(dataArray, "myLon "+val)
|
||||
dataArray = append(dataArray, " ")
|
||||
dataArray = append(dataArray, " #Log")
|
||||
dataArray = append(dataArray, "20/5/23")
|
||||
dataArray = append(dataArray, "40m cw 0950 ik5zve/5 9 5")
|
||||
|
||||
temporaryDataFileName := createTestFile(dataArray)
|
||||
|
||||
//When
|
||||
loadedLogFile, isLoadedOK := LoadFile(temporaryDataFileName, true)
|
||||
|
||||
//Then
|
||||
if isLoadedOK {
|
||||
t.Error("Test file processing should return with an error")
|
||||
}
|
||||
if len(loadedLogFile) == 0 {
|
||||
t.Error("No data loaded")
|
||||
}
|
||||
|
||||
expectedValue := "*" + val
|
||||
if loadedLogFile[0].MyLon != expectedValue {
|
||||
t.Errorf("Not the expected MyLon value: %s (expecting %s)", loadedLogFile[0].MyLon, expectedValue)
|
||||
}
|
||||
|
||||
//Clean Up
|
||||
os.Remove(temporaryDataFileName)
|
||||
}
|
||||
|
||||
func TestLoadFile_outofrange_high_myLon_must_fail(t *testing.T) {
|
||||
Outofrange_myLonHelper(t, "180.0001")
|
||||
}
|
||||
|
||||
func TestLoadFile_outofrange_low_myLon_must_fail(t *testing.T) {
|
||||
Outofrange_myLonHelper(t, "-180.0001")
|
||||
}
|
||||
|
||||
func Outofrange_myLatHelper(t *testing.T, val string) {
|
||||
//Given
|
||||
dataArray := make([]string, 0)
|
||||
dataArray = append(dataArray, "# Header")
|
||||
dataArray = append(dataArray, "myCall on4kjm/p")
|
||||
dataArray = append(dataArray, "operator on4kjm")
|
||||
dataArray = append(dataArray, "nickname Portable")
|
||||
dataArray = append(dataArray, "myLat "+val)
|
||||
dataArray = append(dataArray, " ")
|
||||
dataArray = append(dataArray, " #Log")
|
||||
dataArray = append(dataArray, "20/5/23")
|
||||
dataArray = append(dataArray, "40m cw 0950 ik5zve/5 9 5")
|
||||
|
||||
temporaryDataFileName := createTestFile(dataArray)
|
||||
|
||||
//When
|
||||
loadedLogFile, isLoadedOK := LoadFile(temporaryDataFileName, true)
|
||||
|
||||
//Then
|
||||
if isLoadedOK {
|
||||
t.Error("Test file processing should return with an error")
|
||||
}
|
||||
if len(loadedLogFile) == 0 {
|
||||
t.Error("No data loaded")
|
||||
}
|
||||
|
||||
expectedValue := "*" + val
|
||||
if loadedLogFile[0].MyLat != expectedValue {
|
||||
t.Errorf("Not the expected MyLat value: %s (expecting %s)", loadedLogFile[0].MyLat, expectedValue)
|
||||
}
|
||||
|
||||
//Clean Up
|
||||
os.Remove(temporaryDataFileName)
|
||||
}
|
||||
|
||||
func TestLoadFile_outofrange_high_myLat_must_fail(t *testing.T) {
|
||||
Outofrange_myLatHelper(t, "90.0001")
|
||||
}
|
||||
|
||||
func TestLoadFile_outofrange_low_myLat_must_fail(t *testing.T) {
|
||||
Outofrange_myLatHelper(t, "-90.0001")
|
||||
}
|
||||
|
||||
func TestLoadFile_redefining_myCall_must_fail(t *testing.T) {
|
||||
|
||||
//Given
|
||||
|
@ -1074,6 +1244,8 @@ func TestLoadFile_wrongData(t *testing.T) {
|
|||
dataArray = append(dataArray, "myWwff foobar")
|
||||
dataArray = append(dataArray, "mySota foobar")
|
||||
dataArray = append(dataArray, "myGrid foobar")
|
||||
dataArray = append(dataArray, "myLat foobar")
|
||||
dataArray = append(dataArray, "myLon foobar")
|
||||
dataArray = append(dataArray, " ")
|
||||
dataArray = append(dataArray, " #Log")
|
||||
dataArray = append(dataArray, "date 2020-05-23")
|
||||
|
@ -1114,6 +1286,12 @@ func TestLoadFile_wrongData(t *testing.T) {
|
|||
if loadedLogFile[0].MyGrid != expectedValue {
|
||||
t.Errorf("Not the expected MyGrid value: %s (expecting %s)", loadedLogFile[0].MyGrid, expectedValue)
|
||||
}
|
||||
if loadedLogFile[0].MyLat != expectedValue {
|
||||
t.Errorf("Not the expected MyLat value: %s (expecting %s)", loadedLogFile[0].MyLat, expectedValue)
|
||||
}
|
||||
if loadedLogFile[0].MyLon != expectedValue {
|
||||
t.Errorf("Not the expected MyLon value: %s (expecting %s)", loadedLogFile[0].MyLon, expectedValue)
|
||||
}
|
||||
|
||||
expectedValue = "IK5ZVE"
|
||||
if loadedLogFile[0].Call != expectedValue {
|
||||
|
|
|
@ -35,6 +35,8 @@ type LogLine struct {
|
|||
MyPota string
|
||||
MySota string
|
||||
MyGrid string
|
||||
MyLat string
|
||||
MyLon string
|
||||
MyCounty string
|
||||
QslMsgFromHeader string
|
||||
Nickname string
|
||||
|
|
|
@ -19,10 +19,35 @@ limitations under the License.
|
|||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ValidateLat checks if value is within range of +-90 degrees inclusive.
|
||||
func ValidateLat(lat string) (ref, errorMsg string) {
|
||||
if val, err := strconv.ParseFloat(lat, 64); err == nil {
|
||||
if val <= float64(90.0) && val >= float64(-90.0) {
|
||||
return lat, ""
|
||||
}
|
||||
}
|
||||
|
||||
errorMsg = "[" + lat + "] is an invalid lat"
|
||||
return "*" + lat, errorMsg
|
||||
}
|
||||
|
||||
// ValidateLon checks if value is within range of +-180 degrees inclusive.
|
||||
func ValidateLon(lon string) (ref, errorMsg string) {
|
||||
if val, err := strconv.ParseFloat(lon, 64); err == nil {
|
||||
if val <= float64(180.0) && val >= float64(-180.0) {
|
||||
return lon, ""
|
||||
}
|
||||
}
|
||||
|
||||
errorMsg = "[" + lon + "] is an invalid lon"
|
||||
return "*" + lon, errorMsg
|
||||
}
|
||||
|
||||
// ValidateSota verifies whether the supplied string is a valid SOTA reference.
|
||||
// The syntax is: AA/NN-CCC: Association/Name-3-digit numeric Code (e.g. G/CE-001).
|
||||
func ValidateSota(inputStr string) (ref, errorMsg string) {
|
||||
|
|
3
go.mod
3
go.mod
|
@ -6,15 +6,18 @@ require (
|
|||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/viper v1.18.2
|
||||
github.com/stretchr/testify v1.9.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
|
|
5
go.sum
5
go.sum
|
@ -2,6 +2,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
|
@ -22,6 +23,7 @@ github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6
|
|||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
|
@ -46,8 +48,9 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
|
|||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
|
|
Loading…
Reference in a new issue