reorganize validation routines

pull/2/head
Jean-Marc MEESSEN 4 years ago
parent 1c702a3722
commit 8b4e2e5986

@ -0,0 +1,50 @@
package cmd
/*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import (
"strings"
)
func getBraketedData(inputLine, braketType string) (text, cleanedLine string) {
// Get substring between two strings.
a := ""
b := ""
//TODO: refactor that as a switch statement to exclude non supported bracket types
if braketType == "COMMENT" {
a = "<"
b = ">"
}
if braketType == "QSL" {
a = "["
b = "]"
}
posFirst := strings.Index(inputLine, a)
if posFirst == -1 {
return "",inputLine
}
posLast := strings.Index(inputLine, b)
if posLast == -1 {
return "",inputLine
}
posFirstAdjusted := posFirst + 1
if posFirstAdjusted >= posLast {
return "",inputLine
}
return inputLine[posFirstAdjusted:posLast], inputLine
}

@ -0,0 +1,29 @@
package cmd
import "testing"
func Test_getBraketedData(t *testing.T) {
type args struct {
inputLine string
braketType string
}
tests := []struct {
name string
args args
wantText string
wantCleanedLine string
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotText, gotCleanedLine := getBraketedData(tt.args.inputLine, tt.args.braketType)
if gotText != tt.wantText {
t.Errorf("getBraketedData() gotText = %v, want %v", gotText, tt.wantText)
}
if gotCleanedLine != tt.wantCleanedLine {
t.Errorf("getBraketedData() gotCleanedLine = %v, want %v", gotCleanedLine, tt.wantCleanedLine)
}
})
}
}

@ -1,88 +0,0 @@
package cmd
import "testing"
func TestValidateCall(t *testing.T) {
type args struct {
sign string
}
tests := []struct {
name string
args args
wantCall string
wantErrorMsg string
}{
{
"Good call (simple)",
args{ sign: "on4kjm", },
"ON4KJM", "",
},
{
"Good call (suffix)",
args{ sign: "on4kjm/p", },
"ON4KJM/P", "",
},
{
"Good call (prefix only)",
args{ sign: "DL/on4KJm", },
"DL/ON4KJM", "",
},
{
"Good call (prefix and suffix)",
args{ sign: "DL/on4KJm/p", },
"DL/ON4KJM/P", "",
},
{
"Good call (Numerical prefix)",
args{ sign: "4x/on4KJm/p", },
"4X/ON4KJM/P", "",
},
{
"Good call (prefix and long suffix)",
args{ sign: "DL/on4KJm/qrpp ", },
"DL/ON4KJM/QRPP", "",
},
//Error cases
{
"Pure junk passed",
args{ sign: "aaaaaa", },
"*AAAAAA", "Invalid call",
},
{
"empty string",
args{ sign: "", },
"*", "Invalid call",
},
{
"string with spaces",
args{ sign: " ", },
"*", "Invalid call",
},
{
"invalid prefix",
args{ sign: "xyz/on4kjm", },
"*XYZ/ON4KJM", "Invalid prefix",
},
{
"Too many /",
args{ sign: "F/on4kjm/p/x", },
"*F/ON4KJM/P/X", "Too many '/'",
},
{
"signe /",
args{ sign: "/", },
"*/", "Invalid call",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotCall, gotErrorMsg := ValidateCall(tt.args.sign)
if gotCall != tt.wantCall {
t.Errorf("ValidateCall() gotCall = %v, want %v", gotCall, tt.wantCall)
}
if gotErrorMsg != tt.wantErrorMsg {
t.Errorf("ValidateCall() gotErrorMsg = %v, want %v", gotErrorMsg, tt.wantErrorMsg)
}
})
}
}

@ -1,38 +0,0 @@
package cmd
/*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import (
"strings"
"fmt"
"time"
)
// ValidateDate verifies whether the string is a valid date (YYYY-MM-DD).
func ValidateDate(inputStr string) (ref, errorMsg string) {
const RFC3339FullDate = "2006-01-02"
inputStr = strings.ToUpper(strings.TrimSpace(inputStr))
wrongInputStr := "*" + inputStr
_, err := time.Parse(RFC3339FullDate, inputStr)
if err == nil {
return inputStr, ""
}
return wrongInputStr, fmt.Sprint(err)
}

@ -1,38 +0,0 @@
package cmd
import "testing"
func TestValidateDate(t *testing.T) {
type args struct {
inputStr string
}
tests := []struct {
name string
args args
wantRef string
wantErrorMsg string
}{
{
"Good date (simple)",
args{ inputStr: "2020-06-10", },
"2020-06-10", "",
},
{
"Bad date (simple)",
args{ inputStr: "2020-13-10", },
"*2020-13-10", "parsing time \"2020-13-10\": month out of range",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotRef, gotErrorMsg := ValidateDate(tt.args.inputStr)
if gotRef != tt.wantRef {
t.Errorf("ValidateDate() gotRef = %v, want %v", gotRef, tt.wantRef)
}
if gotErrorMsg != tt.wantErrorMsg {
t.Errorf("ValidateDate() gotErrorMsg = %v, want %v", gotErrorMsg, tt.wantErrorMsg)
}
})
}
}

@ -50,14 +50,14 @@ func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg
//TODO: what happens when we have <> or when there are multiple comments //TODO: what happens when we have <> or when there are multiple comments
//TODO: Refactor this! it is ugly //TODO: Refactor this! it is ugly
comment := getBraketedData(inputStr, "COMMENT") comment,inputStr := getBraketedData(inputStr, "COMMENT")
if comment != "" { if comment != "" {
logLine.Comment = comment logLine.Comment = comment
inputStr = strings.Replace(inputStr, "<" + comment + ">", "",1) inputStr = strings.Replace(inputStr, "<" + comment + ">", "",1)
fmt.Println("Cleaned input string: ", inputStr) fmt.Println("Cleaned input string: ", inputStr)
} }
comment = getBraketedData(inputStr, "QSL") comment,inputStr = getBraketedData(inputStr, "QSL")
if comment != "" { if comment != "" {
logLine.QSLmsg = comment logLine.QSLmsg = comment
inputStr = strings.Replace(inputStr, "[" + comment + "]", "",1) inputStr = strings.Replace(inputStr, "[" + comment + "]", "",1)
@ -114,35 +114,7 @@ func SprintLogRecord(logLine LogLine) (output string){
return output return output
} }
func getBraketedData(value, braketType string) (text string) {
// Get substring between two strings.
a := ""
b := ""
//TODO: refactor that as a switch statement to exclude non supported bracket types
if braketType == "COMMENT" {
a = "<"
b = ">"
}
if braketType == "QSL" {
a = "["
b = "]"
}
posFirst := strings.Index(value, a)
if posFirst == -1 {
return ""
}
posLast := strings.Index(value, b)
if posLast == -1 {
return ""
}
posFirstAdjusted := posFirst + 1
if posFirstAdjusted >= posLast {
return ""
}
return value[posFirstAdjusted:posLast]
}
func lookupMode(lookup string) bool { func lookupMode(lookup string) bool {
switch lookup { switch lookup {

@ -1,35 +0,0 @@
package cmd
/*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import (
"regexp"
"strings"
)
var validSotaRegexp = regexp.MustCompile(`^[0-9A-Z]{1,3}/[A-Z]{2}-[\d]{3}$`)
// 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) {
inputStr = strings.ToUpper(strings.TrimSpace(inputStr))
wrongInputStr := "*" + inputStr
if validSotaRegexp.MatchString(inputStr) {
return inputStr, ""
}
return wrongInputStr, "Invalid SOTA reference"
}

@ -1,82 +0,0 @@
package cmd
import "testing"
func TestValidateSota(t *testing.T) {
type args struct {
inputStr string
}
tests := []struct {
name string
args args
wantRef string
wantErrorMsg string
}{
{
"Good ref (simple)",
args{ inputStr: "on/ON-001", },
"ON/ON-001", "",
},
{
"Good ref (single digit prefix)",
args{ inputStr: "g/ON-001", },
"G/ON-001", "",
},
{
"Good ref (numerical prefix)",
args{ inputStr: "4x/ON-001", },
"4X/ON-001", "",
},
{
"Good ref (american style)",
args{ inputStr: "w4z/ON-001", },
"W4Z/ON-001", "",
},
{
"Bad ref (long prefix)",
args{ inputStr: "xxxx/ON-001", },
"*XXXX/ON-001", "Invalid SOTA reference",
},
{
"Bad ref (missing slash)",
args{ inputStr: "on ON-001", },
"*ON ON-001", "Invalid SOTA reference",
},
{
"Bad ref (numerical region)",
args{ inputStr: "on/9N-001", },
"*ON/9N-001", "Invalid SOTA reference",
},
{
"Bad ref (too long region)",
args{ inputStr: "on/ONA-001", },
"*ON/ONA-001", "Invalid SOTA reference",
},
{
"Bad ref (no dash)",
args{ inputStr: "on/ON/001", },
"*ON/ON/001", "Invalid SOTA reference",
},
{
"Bad ref (number too short)",
args{ inputStr: "on/ON-01", },
"*ON/ON-01", "Invalid SOTA reference",
},
{
"Bad ref (Number too long)",
args{ inputStr: "on/ON-9001", },
"*ON/ON-9001", "Invalid SOTA reference",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotRef, gotErrorMsg := ValidateSota(tt.args.inputStr)
if gotRef != tt.wantRef {
t.Errorf("ValidateSota() gotRef = %v, want %v", gotRef, tt.wantRef)
}
if gotErrorMsg != tt.wantErrorMsg {
t.Errorf("ValidateSota() gotErrorMsg = %v, want %v", gotErrorMsg, tt.wantErrorMsg)
}
})
}
}

@ -18,9 +18,39 @@ limitations under the License.
import ( import (
"regexp" "regexp"
"strings" "strings"
"fmt"
"time"
) )
var validSotaRegexp = regexp.MustCompile(`^[0-9A-Z]{1,3}/[A-Z]{2}-[\d]{3}$`)
// 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) {
inputStr = strings.ToUpper(strings.TrimSpace(inputStr))
wrongInputStr := "*" + inputStr
if validSotaRegexp.MatchString(inputStr) {
return inputStr, ""
}
return wrongInputStr, "Invalid SOTA reference"
}
var validWwffRegexp = regexp.MustCompile(`^[\d]{0,1}[A-Z]{1,2}FF-[\d]{4}$`)
// ValidateWwff verifies whether the supplied string is a valid WWFF reference.
// The syntax is: AAFF-CCCC: AA = national prefix, CCCC = 4-digit numeric code (e.g. ONFF-0001).
func ValidateWwff(inputStr string) (ref, errorMsg string) {
inputStr = strings.ToUpper(strings.TrimSpace(inputStr))
wrongInputStr := "*" + inputStr
if validWwffRegexp.MatchString(inputStr) {
return inputStr, ""
}
return wrongInputStr, "Invalid WWFF reference"
}
var validCallRegexp = regexp.MustCompile(`[\d]{0,1}[A-Z]{1,2}\d([A-Z]{1,4}|\d{3,3}|\d{1,3}[A-Z])[A-Z]{0,5}`) var validCallRegexp = regexp.MustCompile(`[\d]{0,1}[A-Z]{1,2}\d([A-Z]{1,4}|\d{3,3}|\d{1,3}[A-Z])[A-Z]{0,5}`)
var validPrefixRegexp = regexp.MustCompile(`\A\d?[a-zA-Z]{1,2}$`) var validPrefixRegexp = regexp.MustCompile(`\A\d?[a-zA-Z]{1,2}$`)
@ -67,3 +97,19 @@ func ValidateCall(sign string) (call, errorMsg string) {
} }
return wrongSign, "Too many '/'" return wrongSign, "Too many '/'"
} }
// ValidateDate verifies whether the string is a valid date (YYYY-MM-DD).
func ValidateDate(inputStr string) (ref, errorMsg string) {
const RFC3339FullDate = "2006-01-02"
inputStr = strings.ToUpper(strings.TrimSpace(inputStr))
wrongInputStr := "*" + inputStr
_, err := time.Parse(RFC3339FullDate, inputStr)
if err == nil {
return inputStr, ""
}
return wrongInputStr, fmt.Sprint(err)
}

@ -0,0 +1,262 @@
package cmd
import "testing"
func TestValidateWwff(t *testing.T) {
type args struct {
inputStr string
}
tests := []struct {
name string
args args
wantRef string
wantErrorMsg string
}{
{
"Good ref (simple)",
args{ inputStr: "onff-0258", },
"ONFF-0258", "",
},
{
"Good ref (single digit country)",
args{ inputStr: "fff-0258", },
"FFF-0258", "",
},
{
"Good ref (Numerical country)",
args{ inputStr: "4xff-0258", },
"4XFF-0258", "",
},
{
"Bad ref (no country prefix)",
args{ inputStr: "ff-0258", },
"*FF-0258", "Invalid WWFF reference",
},
{
"Bad ref (wrong separator)",
args{ inputStr: "gff/0258", },
"*GFF/0258", "Invalid WWFF reference",
},
{
"Bad ref (reference too short)",
args{ inputStr: "onff-258", },
"*ONFF-258", "Invalid WWFF reference",
},
{
"Bad ref (no country prefix)",
args{ inputStr: "onff-02589", },
"*ONFF-02589", "Invalid WWFF reference",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotRef, gotErrorMsg := ValidateWwff(tt.args.inputStr)
if gotRef != tt.wantRef {
t.Errorf("ValidateWwff() gotRef = %v, want %v", gotRef, tt.wantRef)
}
if gotErrorMsg != tt.wantErrorMsg {
t.Errorf("ValidateWwff() gotErrorMsg = %v, want %v", gotErrorMsg, tt.wantErrorMsg)
}
})
}
}
func TestValidateSota(t *testing.T) {
type args struct {
inputStr string
}
tests := []struct {
name string
args args
wantRef string
wantErrorMsg string
}{
{
"Good ref (simple)",
args{ inputStr: "on/ON-001", },
"ON/ON-001", "",
},
{
"Good ref (single digit prefix)",
args{ inputStr: "g/ON-001", },
"G/ON-001", "",
},
{
"Good ref (numerical prefix)",
args{ inputStr: "4x/ON-001", },
"4X/ON-001", "",
},
{
"Good ref (american style)",
args{ inputStr: "w4z/ON-001", },
"W4Z/ON-001", "",
},
{
"Bad ref (long prefix)",
args{ inputStr: "xxxx/ON-001", },
"*XXXX/ON-001", "Invalid SOTA reference",
},
{
"Bad ref (missing slash)",
args{ inputStr: "on ON-001", },
"*ON ON-001", "Invalid SOTA reference",
},
{
"Bad ref (numerical region)",
args{ inputStr: "on/9N-001", },
"*ON/9N-001", "Invalid SOTA reference",
},
{
"Bad ref (too long region)",
args{ inputStr: "on/ONA-001", },
"*ON/ONA-001", "Invalid SOTA reference",
},
{
"Bad ref (no dash)",
args{ inputStr: "on/ON/001", },
"*ON/ON/001", "Invalid SOTA reference",
},
{
"Bad ref (number too short)",
args{ inputStr: "on/ON-01", },
"*ON/ON-01", "Invalid SOTA reference",
},
{
"Bad ref (Number too long)",
args{ inputStr: "on/ON-9001", },
"*ON/ON-9001", "Invalid SOTA reference",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotRef, gotErrorMsg := ValidateSota(tt.args.inputStr)
if gotRef != tt.wantRef {
t.Errorf("ValidateSota() gotRef = %v, want %v", gotRef, tt.wantRef)
}
if gotErrorMsg != tt.wantErrorMsg {
t.Errorf("ValidateSota() gotErrorMsg = %v, want %v", gotErrorMsg, tt.wantErrorMsg)
}
})
}
}
func TestValidateCall(t *testing.T) {
type args struct {
sign string
}
tests := []struct {
name string
args args
wantCall string
wantErrorMsg string
}{
{
"Good call (simple)",
args{ sign: "on4kjm", },
"ON4KJM", "",
},
{
"Good call (suffix)",
args{ sign: "on4kjm/p", },
"ON4KJM/P", "",
},
{
"Good call (prefix only)",
args{ sign: "DL/on4KJm", },
"DL/ON4KJM", "",
},
{
"Good call (prefix and suffix)",
args{ sign: "DL/on4KJm/p", },
"DL/ON4KJM/P", "",
},
{
"Good call (Numerical prefix)",
args{ sign: "4x/on4KJm/p", },
"4X/ON4KJM/P", "",
},
{
"Good call (prefix and long suffix)",
args{ sign: "DL/on4KJm/qrpp ", },
"DL/ON4KJM/QRPP", "",
},
//Error cases
{
"Pure junk passed",
args{ sign: "aaaaaa", },
"*AAAAAA", "Invalid call",
},
{
"empty string",
args{ sign: "", },
"*", "Invalid call",
},
{
"string with spaces",
args{ sign: " ", },
"*", "Invalid call",
},
{
"invalid prefix",
args{ sign: "xyz/on4kjm", },
"*XYZ/ON4KJM", "Invalid prefix",
},
{
"Too many /",
args{ sign: "F/on4kjm/p/x", },
"*F/ON4KJM/P/X", "Too many '/'",
},
{
"signe /",
args{ sign: "/", },
"*/", "Invalid call",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotCall, gotErrorMsg := ValidateCall(tt.args.sign)
if gotCall != tt.wantCall {
t.Errorf("ValidateCall() gotCall = %v, want %v", gotCall, tt.wantCall)
}
if gotErrorMsg != tt.wantErrorMsg {
t.Errorf("ValidateCall() gotErrorMsg = %v, want %v", gotErrorMsg, tt.wantErrorMsg)
}
})
}
}
func TestValidateDate(t *testing.T) {
type args struct {
inputStr string
}
tests := []struct {
name string
args args
wantRef string
wantErrorMsg string
}{
{
"Good date (simple)",
args{ inputStr: "2020-06-10", },
"2020-06-10", "",
},
{
"Bad date (simple)",
args{ inputStr: "2020-13-10", },
"*2020-13-10", "parsing time \"2020-13-10\": month out of range",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotRef, gotErrorMsg := ValidateDate(tt.args.inputStr)
if gotRef != tt.wantRef {
t.Errorf("ValidateDate() gotRef = %v, want %v", gotRef, tt.wantRef)
}
if gotErrorMsg != tt.wantErrorMsg {
t.Errorf("ValidateDate() gotErrorMsg = %v, want %v", gotErrorMsg, tt.wantErrorMsg)
}
})
}
}

@ -1,35 +0,0 @@
package cmd
/*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import (
"regexp"
"strings"
)
var validWwffRegexp = regexp.MustCompile(`^[\d]{0,1}[A-Z]{1,2}FF-[\d]{4}$`)
// ValidateWwff verifies whether the supplied string is a valid WWFF reference.
// The syntax is: AAFF-CCCC: AA = national prefix, CCCC = 4-digit numeric code (e.g. ONFF-0001).
func ValidateWwff(inputStr string) (ref, errorMsg string) {
inputStr = strings.ToUpper(strings.TrimSpace(inputStr))
wrongInputStr := "*" + inputStr
if validWwffRegexp.MatchString(inputStr) {
return inputStr, ""
}
return wrongInputStr, "Invalid WWFF reference"
}

@ -1,63 +0,0 @@
package cmd
import "testing"
func TestValidateWwff(t *testing.T) {
type args struct {
inputStr string
}
tests := []struct {
name string
args args
wantRef string
wantErrorMsg string
}{
{
"Good ref (simple)",
args{ inputStr: "onff-0258", },
"ONFF-0258", "",
},
{
"Good ref (single digit country)",
args{ inputStr: "fff-0258", },
"FFF-0258", "",
},
{
"Good ref (Numerical country)",
args{ inputStr: "4xff-0258", },
"4XFF-0258", "",
},
{
"Bad ref (no country prefix)",
args{ inputStr: "ff-0258", },
"*FF-0258", "Invalid WWFF reference",
},
{
"Bad ref (wrong separator)",
args{ inputStr: "gff/0258", },
"*GFF/0258", "Invalid WWFF reference",
},
{
"Bad ref (reference too short)",
args{ inputStr: "onff-258", },
"*ONFF-258", "Invalid WWFF reference",
},
{
"Bad ref (no country prefix)",
args{ inputStr: "onff-02589", },
"*ONFF-02589", "Invalid WWFF reference",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotRef, gotErrorMsg := ValidateWwff(tt.args.inputStr)
if gotRef != tt.wantRef {
t.Errorf("ValidateWwff() gotRef = %v, want %v", gotRef, tt.wantRef)
}
if gotErrorMsg != tt.wantErrorMsg {
t.Errorf("ValidateWwff() gotErrorMsg = %v, want %v", gotErrorMsg, tt.wantErrorMsg)
}
})
}
}
Loading…
Cancel
Save