Skip to content

Commit 66e951b

Browse files
committed
go-aah/aah#69 reusable format flag parser
1 parent f1d4e15 commit 66e951b

File tree

3 files changed

+184
-0
lines changed

3 files changed

+184
-0
lines changed

archive_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package ess
66

77
import (
88
"io/ioutil"
9+
"strings"
910
"testing"
1011

1112
"aahframework.org/test.v0/assert"
@@ -39,4 +40,12 @@ func TestArchiveZip(t *testing.T) {
3940
err := Zip(zipName, join(testdataPath, "dirpaths"))
4041
assert.Nil(t, err)
4142
assert.True(t, IsFileExists(zipName))
43+
44+
err = Zip(zipName, join(testdataPath, "dirpaths1"))
45+
assert.NotNil(t, err)
46+
assert.True(t, strings.HasPrefix(err.Error(), "source does not exists:"))
47+
48+
err = Zip(zipName, join(testdataPath, "dirpaths"))
49+
assert.NotNil(t, err)
50+
assert.True(t, strings.HasPrefix(err.Error(), "destination archive already exists:"))
4251
}

fmt_flag.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright (c) Jeevanandam M. (https://github.com/jeevatkm)
2+
// go-aah/essentials source code and usage is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package ess
6+
7+
import (
8+
"fmt"
9+
"strings"
10+
)
11+
12+
var (
13+
// FmtFlagSeparator is used parse flags pattern.
14+
FmtFlagSeparator = "%"
15+
16+
// FmtFlagValueSeparator is used to parse into flag and value.
17+
FmtFlagValueSeparator = ":"
18+
19+
defaultFormat = "%v"
20+
)
21+
22+
type (
23+
// FmtFlagPart is indiviual flag details
24+
// For e.g.:
25+
// part := FmtFlagPart{
26+
// Flag: FmtFlagTime,
27+
// Name: "time",
28+
// Format: "2006-01-02 15:04:05.000",
29+
// }
30+
FmtFlagPart struct {
31+
Flag FmtFlag
32+
Name string
33+
Format string
34+
}
35+
36+
// FmtFlag type definition
37+
FmtFlag uint8
38+
)
39+
40+
// ParseFmtFlag it parses the given pattern, format flags into format flag parts.
41+
// For e.g.:
42+
// %time:2006-01-02 15:04:05.000 %level:-5 %message
43+
// %clientip %reqid %reqtime %restime %resstatus %ressize %reqmethod %requrl %reqhdr:Referer %reshdr:Server
44+
func ParseFmtFlag(pattern string, fmtFlags map[string]FmtFlag) ([]FmtFlagPart, error) {
45+
var flagParts []FmtFlagPart
46+
pattern = strings.TrimSpace(pattern)
47+
formatFlags := strings.Split(pattern, FmtFlagSeparator)[1:]
48+
for _, f := range formatFlags {
49+
f = strings.TrimSpace(f)
50+
parts := strings.SplitN(f, FmtFlagValueSeparator, 2)
51+
flag, found := fmtFlags[parts[0]]
52+
if !found {
53+
return nil, fmt.Errorf("fmtflag: unknown flag '%s'", f)
54+
}
55+
56+
part := FmtFlagPart{Flag: flag, Name: parts[0]}
57+
switch len(parts) {
58+
case 2:
59+
// handle `time` related flag, `custom` flag
60+
// and `hdr` flag particularly
61+
if strings.Contains(parts[0], "time") || parts[0] == "custom" ||
62+
strings.HasSuffix(parts[0], "hdr") {
63+
part.Format = parts[1]
64+
} else {
65+
part.Format = "%" + parts[1] + "v"
66+
}
67+
default:
68+
part.Format = defaultFormat
69+
}
70+
71+
flagParts = append(flagParts, part)
72+
}
73+
74+
return flagParts, nil
75+
}

fmt_flag_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright (c) Jeevanandam M. (https://github.com/jeevatkm)
2+
// go-aah/essentials source code and usage is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package ess
6+
7+
import (
8+
"testing"
9+
10+
"aahframework.org/test.v0/assert"
11+
)
12+
13+
func TestFmtParseFlagLog(t *testing.T) {
14+
const (
15+
FmtFlagLevel FmtFlag = iota
16+
FmtFlagTime
17+
FmtFlagUTCTime
18+
FmtFlagLongfile
19+
FmtFlagShortfile
20+
FmtFlagLine
21+
FmtFlagMessage
22+
FmtFlagCustom
23+
)
24+
25+
logFmtFlags := map[string]FmtFlag{
26+
"level": FmtFlagLevel,
27+
"time": FmtFlagTime,
28+
"utctime": FmtFlagUTCTime,
29+
"longfile": FmtFlagLongfile,
30+
"shortfile": FmtFlagShortfile,
31+
"line": FmtFlagLine,
32+
"message": FmtFlagMessage,
33+
"custom": FmtFlagCustom,
34+
}
35+
36+
flagParts, err := ParseFmtFlag("%time:2006-01-02 15:04:05.000 %level %custom:- %message", logFmtFlags)
37+
assert.Nil(t, err)
38+
39+
assertFlagPart(t, "time", "2006-01-02 15:04:05.000", FmtFlag(1), flagParts[0])
40+
assertFlagPart(t, "level", "%v", FmtFlag(0), flagParts[1])
41+
assertFlagPart(t, "custom", "-", FmtFlag(7), flagParts[2])
42+
assertFlagPart(t, "message", "%v", FmtFlag(6), flagParts[3])
43+
44+
// Unknown flag
45+
flagParts, err = ParseFmtFlag("%myflag", logFmtFlags)
46+
assert.NotNil(t, err)
47+
assert.Equal(t, "fmtflag: unknown flag 'myflag'", err.Error())
48+
assert.True(t, len(flagParts) == 0)
49+
}
50+
51+
func TestFmtParseFlagAccessLog(t *testing.T) {
52+
const (
53+
fmtFlagClientIP FmtFlag = iota
54+
fmtFlagRequestTime
55+
fmtFlagRequestURL
56+
fmtFlagRequestMethod
57+
fmtFlagRequestID
58+
fmtFlagRequestHeader
59+
fmtFlagQueryString
60+
fmtFlagResponseStatus
61+
fmtFlagResponseSize
62+
fmtFlagResponseHeader
63+
fmtFlagResponseTime
64+
)
65+
66+
accessLogFmtFlags := map[string]FmtFlag{
67+
"clientip": fmtFlagClientIP,
68+
"reqtime": fmtFlagRequestTime,
69+
"requrl": fmtFlagRequestURL,
70+
"reqmethod": fmtFlagRequestMethod,
71+
"reqid": fmtFlagRequestID,
72+
"reqhdr": fmtFlagRequestHeader,
73+
"querystr": fmtFlagQueryString,
74+
"resstatus": fmtFlagResponseStatus,
75+
"ressize": fmtFlagResponseSize,
76+
"reshdr": fmtFlagResponseHeader,
77+
"restime": fmtFlagResponseTime,
78+
}
79+
80+
flagParts, err := ParseFmtFlag("%clientip %reqid %reqtime %restime %resstatus %ressize %reqmethod %requrl %reqhdr:Referer %reshdr:Server", accessLogFmtFlags)
81+
assert.Nil(t, err)
82+
83+
assertFlagPart(t, "clientip", "%v", FmtFlag(0), flagParts[0])
84+
assertFlagPart(t, "reqid", "%v", FmtFlag(4), flagParts[1])
85+
assertFlagPart(t, "reqtime", "%v", FmtFlag(1), flagParts[2])
86+
assertFlagPart(t, "restime", "%v", FmtFlag(10), flagParts[3])
87+
assertFlagPart(t, "resstatus", "%v", FmtFlag(7), flagParts[4])
88+
assertFlagPart(t, "ressize", "%v", FmtFlag(8), flagParts[5])
89+
assertFlagPart(t, "reqmethod", "%v", FmtFlag(3), flagParts[6])
90+
assertFlagPart(t, "requrl", "%v", FmtFlag(2), flagParts[7])
91+
assertFlagPart(t, "reqhdr", "Referer", FmtFlag(5), flagParts[8])
92+
assertFlagPart(t, "reshdr", "Server", FmtFlag(9), flagParts[9])
93+
}
94+
95+
func assertFlagPart(t *testing.T, name, format string, fflag FmtFlag, flagPart FmtFlagPart) {
96+
t.Logf("Fmt Flag: %v", format)
97+
assert.Equal(t, name, flagPart.Name)
98+
assert.Equal(t, format, flagPart.Format)
99+
assert.Equal(t, fflag, flagPart.Flag)
100+
}

0 commit comments

Comments
 (0)