forked from TrueCloudLab/rclone
vendor: add qingstor-sdk-go for QingStor
This commit is contained in:
parent
f682002b84
commit
466dd22b44
136 changed files with 15952 additions and 1 deletions
28
vendor/github.com/pengsrc/go-shared/.gitignore
generated
vendored
Normal file
28
vendor/github.com/pengsrc/go-shared/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
vendor
|
||||
|
||||
coverage
|
35
vendor/github.com/pengsrc/go-shared/.travis.yml
generated
vendored
Normal file
35
vendor/github.com/pengsrc/go-shared/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.8
|
||||
- 1.7
|
||||
- 1.6
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- ${HOME}/source
|
||||
|
||||
before_install:
|
||||
- pushd ${HOME}/source
|
||||
- if [[ ! -d "./make-4.0" ]]; then
|
||||
wget http://ftp.gnu.org/gnu/make/make-4.0.tar.gz &&
|
||||
tar -vxzf make-4.0.tar.gz &&
|
||||
pushd make-4.0 && ./configure --prefix=/usr/local && make && popd;
|
||||
fi
|
||||
- pushd make-4.0 && sudo make install && popd
|
||||
- if [[ ! -d "./glide-v0.12.3" ]]; then
|
||||
wget https://github.com/Masterminds/glide/releases/download/v0.12.3/glide-v0.12.3-linux-amd64.tar.gz &&
|
||||
tar -vxzf glide-v0.12.3-linux-amd64.tar.gz &&
|
||||
mv linux-amd64 glide-v0.12.3;
|
||||
fi
|
||||
- pushd glide-v0.12.3 && sudo cp glide /usr/local/bin && popd
|
||||
- popd
|
||||
- /usr/local/bin/make --version
|
||||
- /usr/local/bin/glide --version
|
||||
|
||||
install:
|
||||
- go get -u github.com/golang/lint/golint
|
||||
- glide install
|
||||
|
||||
script:
|
||||
- /usr/local/bin/make check
|
||||
- /usr/local/bin/make test-coverage
|
202
vendor/github.com/pengsrc/go-shared/LICENSE
generated
vendored
Normal file
202
vendor/github.com/pengsrc/go-shared/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2017 Jingwen Peng
|
||||
|
||||
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.
|
61
vendor/github.com/pengsrc/go-shared/Makefile
generated
vendored
Normal file
61
vendor/github.com/pengsrc/go-shared/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
SHELL := /bin/bash
|
||||
|
||||
PACKAGE_NAME="github.com/pengsrc/go-shared"
|
||||
|
||||
DIRS_TO_CHECK=$(shell ls -d */ | grep -v "vendor")
|
||||
PKGS_TO_CHECK=$(shell go list ./... | grep -vE "/vendor")
|
||||
|
||||
ifneq (${PKG},)
|
||||
DIRS_TO_CHECK="./${PKG}"
|
||||
PKGS_TO_CHECK="${PACKAGE_NAME}/${PKG}"
|
||||
endif
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "Please use \`make <target>\` where <target> is one of"
|
||||
@echo " check to vet and lint"
|
||||
@echo " test to run test"
|
||||
@echo " test-coverage to run test with coverage"
|
||||
|
||||
.PHONY: check
|
||||
check: format vet lint
|
||||
|
||||
.PHONY: format
|
||||
format:
|
||||
@gofmt -w .
|
||||
@echo "ok"
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
@echo "go tool vet, skipping vendor packages"
|
||||
@go tool vet -all ${DIRS_TO_CHECK}
|
||||
@echo "ok"
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
@echo "golint, skipping vendor packages"
|
||||
@lint=$$(for pkg in ${PKGS_TO_CHECK}; do golint $${pkg}; done); \
|
||||
lint=$$(echo "$${lint}"); \
|
||||
if [[ -n $${lint} ]]; then echo "$${lint}"; exit 1; fi
|
||||
@echo "ok"
|
||||
|
||||
.PHONY: update
|
||||
.PHONY: test
|
||||
test:
|
||||
@echo "run test"
|
||||
@go test -v ${PKGS_TO_CHECK}
|
||||
@echo "ok"
|
||||
|
||||
.PHONY: test-coverage
|
||||
test-coverage:
|
||||
@echo "run test with coverage"
|
||||
@for pkg in ${PKGS_TO_CHECK}; do \
|
||||
output="coverage$${pkg#${PACKAGE_NAME}}"; \
|
||||
mkdir -p $${output}; \
|
||||
go test -v -cover -coverprofile="$${output}/profile.out" $${pkg}; \
|
||||
if [[ -e "$${output}/profile.out" ]]; then \
|
||||
go tool cover -html="$${output}/profile.out" \
|
||||
-o "$${output}/profile.html"; \
|
||||
fi; \
|
||||
done
|
||||
@echo "ok"
|
19
vendor/github.com/pengsrc/go-shared/README.md
generated
vendored
Normal file
19
vendor/github.com/pengsrc/go-shared/README.md
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
# go-shared
|
||||
|
||||
[](https://travis-ci.org/pengsrc/go-shared)
|
||||
[](https://goreportcard.com/report/github.com/pengsrc/go-shared)
|
||||
[](https://github.com/yunify/qingstor-sdk-go/blob/master/LICENSE)
|
||||
|
||||
Useful packages for the Go programming language.
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork it ( https://github.com/pengsrc/go-shared/fork )
|
||||
2. Create your feature branch (`git checkout -b new-feature`)
|
||||
3. Commit your changes (`git commit -asm 'Add some feature'`)
|
||||
4. Push to the branch (`git push origin new-feature`)
|
||||
5. Create a new Pull Request
|
||||
|
||||
## LICENSE
|
||||
|
||||
The Apache License (Version 2.0, January 2004).
|
21
vendor/github.com/pengsrc/go-shared/check/error.go
generated
vendored
Normal file
21
vendor/github.com/pengsrc/go-shared/check/error.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
package check
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ErrorForExit check the error.
|
||||
// If error is not nil, print the error message and exit the application.
|
||||
// If error is nil, do nothing.
|
||||
func ErrorForExit(name string, err error, code ...int) {
|
||||
if err != nil {
|
||||
exitCode := 1
|
||||
if len(code) > 0 {
|
||||
exitCode = code[0]
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "%s: %s (%d)\n", name, err.Error(), exitCode)
|
||||
fmt.Fprintf(os.Stderr, "See \"%s --help\".\n", name)
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
}
|
12
vendor/github.com/pengsrc/go-shared/check/error_test.go
generated
vendored
Normal file
12
vendor/github.com/pengsrc/go-shared/check/error_test.go
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
package check
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCheckErrorForExit(t *testing.T) {
|
||||
ErrorForExit("name", nil)
|
||||
assert.True(t, true)
|
||||
}
|
11
vendor/github.com/pengsrc/go-shared/check/host.go
generated
vendored
Normal file
11
vendor/github.com/pengsrc/go-shared/check/host.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
package check
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// HostAndPort checks whether a string contains host and port.
|
||||
// It returns true if matched.
|
||||
func HostAndPort(hostAndPort string) bool {
|
||||
return regexp.MustCompile(`^[^:]+:[0-9]+$`).MatchString(hostAndPort)
|
||||
}
|
16
vendor/github.com/pengsrc/go-shared/check/host_test.go
generated
vendored
Normal file
16
vendor/github.com/pengsrc/go-shared/check/host_test.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
package check
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCheckHostAndPort(t *testing.T) {
|
||||
assert.False(t, HostAndPort("127.0.0.1:80:90"))
|
||||
assert.False(t, HostAndPort("127.0.0.1"))
|
||||
assert.False(t, HostAndPort("mysql"))
|
||||
assert.False(t, HostAndPort("mysql:mysql"))
|
||||
assert.True(t, HostAndPort("mysql:3306"))
|
||||
assert.True(t, HostAndPort("172.16.70.50:6379"))
|
||||
}
|
41
vendor/github.com/pengsrc/go-shared/check/slice.go
generated
vendored
Normal file
41
vendor/github.com/pengsrc/go-shared/check/slice.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
package check
|
||||
|
||||
// StringSliceContains iterates over the slice to find the target.
|
||||
func StringSliceContains(slice []string, target string) bool {
|
||||
for _, v := range slice {
|
||||
if v == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IntSliceContains iterates over the slice to find the target.
|
||||
func IntSliceContains(slice []int, target int) bool {
|
||||
for _, v := range slice {
|
||||
if v == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Int32SliceContains iterates over the slice to find the target.
|
||||
func Int32SliceContains(slice []int32, target int32) bool {
|
||||
for _, v := range slice {
|
||||
if v == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Int64SliceContains iterates over the slice to find the target.
|
||||
func Int64SliceContains(slice []int64, target int64) bool {
|
||||
for _, v := range slice {
|
||||
if v == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
27
vendor/github.com/pengsrc/go-shared/check/slice_test.go
generated
vendored
Normal file
27
vendor/github.com/pengsrc/go-shared/check/slice_test.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
package check
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStringSliceContains(t *testing.T) {
|
||||
assert.True(t, StringSliceContains([]string{"1", "2", "3"}, "2"))
|
||||
assert.False(t, StringSliceContains([]string{"1", "2", "3"}, "4"))
|
||||
}
|
||||
|
||||
func TestIntSliceContains(t *testing.T) {
|
||||
assert.True(t, IntSliceContains([]int{1, 2, 3, 4, 5, 6}, 4))
|
||||
assert.False(t, IntSliceContains([]int{1, 2, 3, 4, 5, 6}, 7))
|
||||
}
|
||||
|
||||
func TestInt32SliceContains(t *testing.T) {
|
||||
assert.True(t, Int32SliceContains([]int32{1, 2, 3, 4, 5, 6}, 4))
|
||||
assert.False(t, Int32SliceContains([]int32{1, 2, 3, 4, 5, 6}, 7))
|
||||
}
|
||||
|
||||
func TestInt64SliceContains(t *testing.T) {
|
||||
assert.True(t, Int64SliceContains([]int64{1, 2, 3, 4, 5, 6}, 4))
|
||||
assert.False(t, Int64SliceContains([]int64{1, 2, 3, 4, 5, 6}, 7))
|
||||
}
|
56
vendor/github.com/pengsrc/go-shared/convert/time.go
generated
vendored
Normal file
56
vendor/github.com/pengsrc/go-shared/convert/time.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
package convert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pengsrc/go-shared/check"
|
||||
)
|
||||
|
||||
// Supported time layouts
|
||||
const (
|
||||
RFC822 = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||
ISO8601 = "2006-01-02T15:04:05Z"
|
||||
ISO8601Milli = "2006-01-02T15:04:05.000Z"
|
||||
NGINXTime = "02/Jan/2006:15:04:05 -0700"
|
||||
)
|
||||
|
||||
// TimeToString transforms given time to string.
|
||||
func TimeToString(timeValue time.Time, format string) string {
|
||||
if check.StringSliceContains([]string{RFC822, ISO8601, ISO8601Milli}, format) {
|
||||
timeValue = timeValue.UTC()
|
||||
}
|
||||
return timeValue.Format(format)
|
||||
}
|
||||
|
||||
// StringToTime transforms given string to time.
|
||||
func StringToTime(timeString string, format string) (time.Time, error) {
|
||||
result, err := time.Parse(format, timeString)
|
||||
if timeString != "0001-01-01T00:00:00Z" {
|
||||
zero := time.Time{}
|
||||
if result == zero {
|
||||
err = fmt.Errorf(`failed to parse "%s" like "%s"`, timeString, format)
|
||||
}
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// TimeToTimestamp transforms given time to unix time int.
|
||||
func TimeToTimestamp(t time.Time) int64 {
|
||||
return t.Unix()
|
||||
}
|
||||
|
||||
// TimestampToTime transforms given unix time int64 to time in UTC.
|
||||
func TimestampToTime(unix int64) time.Time {
|
||||
return time.Unix(unix, 0).UTC()
|
||||
}
|
||||
|
||||
// StringToUnixTimestamp transforms given string to unix time int64. It will
|
||||
// return -1 when time string parse error.
|
||||
func StringToUnixTimestamp(timeString string, format string) int64 {
|
||||
t, err := StringToTime(timeString, format)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return t.Unix()
|
||||
}
|
78
vendor/github.com/pengsrc/go-shared/convert/time_test.go
generated
vendored
Normal file
78
vendor/github.com/pengsrc/go-shared/convert/time_test.go
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
package convert
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTimeToString(t *testing.T) {
|
||||
tz, err := time.LoadLocation("Asia/Shanghai")
|
||||
assert.NoError(t, err)
|
||||
|
||||
someTime := time.Date(2016, 9, 1, 15, 30, 0, 500000000, tz)
|
||||
assert.Equal(t, "Thu, 01 Sep 2016 07:30:00 GMT", TimeToString(someTime, RFC822))
|
||||
assert.Equal(t, "2016-09-01T07:30:00Z", TimeToString(someTime, ISO8601))
|
||||
assert.Equal(t, "2016-09-01T07:30:00.500Z", TimeToString(someTime, ISO8601Milli))
|
||||
assert.Equal(t, "01/Sep/2016:15:30:00 +0800", TimeToString(someTime, NGINXTime))
|
||||
assert.Equal(t, "01/Sep/2016:07:30:00 +0000", TimeToString(someTime.UTC(), NGINXTime))
|
||||
}
|
||||
|
||||
func TestStringToTime(t *testing.T) {
|
||||
tz, err := time.LoadLocation("Asia/Shanghai")
|
||||
assert.NoError(t, err)
|
||||
someTime := time.Date(2016, 9, 1, 15, 30, 0, 0, tz)
|
||||
|
||||
parsedTime, err := StringToTime("Thu, 01 Sep 2016 07:30:00 GMT", RFC822)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, someTime.UTC(), parsedTime)
|
||||
|
||||
parsedTime, err = StringToTime("2016-09-01T07:30:00Z", ISO8601)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, someTime.UTC(), parsedTime)
|
||||
|
||||
parsedTime, err = StringToTime("1472715000", ISO8601)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, time.Time{}, parsedTime)
|
||||
|
||||
someTime = time.Date(2016, 9, 1, 15, 30, 0, 500000000, tz)
|
||||
parsedTime, err = StringToTime("2016-09-01T07:30:00.500Z", ISO8601Milli)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, someTime.UTC(), parsedTime)
|
||||
someTime = time.Date(2016, 9, 1, 15, 30, 0, 0, tz)
|
||||
|
||||
parsedTime, err = StringToTime("01/Sep/2016:15:30:00 +0800", NGINXTime)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, someTime.UTC(), parsedTime.UTC())
|
||||
|
||||
parsedTime, err = StringToTime("01/Sep/2016:07:30:00 +0000", NGINXTime)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, someTime.UTC(), parsedTime.UTC())
|
||||
}
|
||||
|
||||
func TestStringToUnixString(t *testing.T) {
|
||||
assert.Equal(t, int64(1472715000), StringToUnixTimestamp("Thu, 01 Sep 2016 07:30:00 GMT", RFC822))
|
||||
assert.Equal(t, int64(-1), StringToUnixTimestamp("2016-09-01T07:30:00.000Z", RFC822))
|
||||
assert.Equal(t, int64(1472715000), StringToUnixTimestamp("2016-09-01T07:30:00Z", ISO8601))
|
||||
assert.Equal(t, int64(1472715000), StringToUnixTimestamp("2016-09-01T07:30:00.000Z", ISO8601Milli))
|
||||
assert.Equal(t, int64(1472715000), StringToUnixTimestamp("2016-09-01T07:30:00.500Z", ISO8601Milli))
|
||||
assert.Equal(t, int64(1472715000), StringToUnixTimestamp("01/Sep/2016:15:30:00 +0800", NGINXTime))
|
||||
assert.Equal(t, int64(1472715000), StringToUnixTimestamp("01/Sep/2016:07:30:00 +0000", NGINXTime))
|
||||
}
|
||||
|
||||
func TestTimeToUnixInt(t *testing.T) {
|
||||
tz, err := time.LoadLocation("Asia/Shanghai")
|
||||
assert.NoError(t, err)
|
||||
someTime := time.Date(2016, 9, 1, 15, 30, 0, 0, tz)
|
||||
|
||||
assert.Equal(t, int64(1472715000), TimeToTimestamp(someTime))
|
||||
}
|
||||
|
||||
func TestUnixIntToTime(t *testing.T) {
|
||||
tz, err := time.LoadLocation("Asia/Shanghai")
|
||||
assert.NoError(t, err)
|
||||
someTime := time.Date(2016, 9, 1, 15, 30, 0, 0, tz)
|
||||
|
||||
assert.Equal(t, someTime.UTC(), TimestampToTime(1472715000))
|
||||
}
|
477
vendor/github.com/pengsrc/go-shared/convert/types.go
generated
vendored
Normal file
477
vendor/github.com/pengsrc/go-shared/convert/types.go
generated
vendored
Normal file
|
@ -0,0 +1,477 @@
|
|||
package convert
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// String returns a pointer to the given string value.
|
||||
func String(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
// StringValue returns the value of the given string pointer or
|
||||
// "" if the pointer is nil.
|
||||
func StringValue(v *string) string {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// StringSlice converts a slice of string values into a slice of
|
||||
// string pointers
|
||||
func StringSlice(src []string) []*string {
|
||||
dst := make([]*string, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringValueSlice converts a slice of string pointers into a slice of
|
||||
// string values
|
||||
func StringValueSlice(src []*string) []string {
|
||||
dst := make([]string, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringMap converts a string map of string values into a string
|
||||
// map of string pointers
|
||||
func StringMap(src map[string]string) map[string]*string {
|
||||
dst := make(map[string]*string)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringValueMap converts a string map of string pointers into a string
|
||||
// map of string values
|
||||
func StringValueMap(src map[string]*string) map[string]string {
|
||||
dst := make(map[string]string)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Bool returns a pointer to the given bool value.
|
||||
func Bool(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
||||
// BoolValue returns the value of the given bool pointer or
|
||||
// false if the pointer is nil.
|
||||
func BoolValue(v *bool) bool {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BoolSlice converts a slice of bool values into a slice of
|
||||
// bool pointers
|
||||
func BoolSlice(src []bool) []*bool {
|
||||
dst := make([]*bool, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolValueSlice converts a slice of bool pointers into a slice of
|
||||
// bool values
|
||||
func BoolValueSlice(src []*bool) []bool {
|
||||
dst := make([]bool, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolMap converts a string map of bool values into a string
|
||||
// map of bool pointers
|
||||
func BoolMap(src map[string]bool) map[string]*bool {
|
||||
dst := make(map[string]*bool)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolValueMap converts a string map of bool pointers into a string
|
||||
// map of bool values
|
||||
func BoolValueMap(src map[string]*bool) map[string]bool {
|
||||
dst := make(map[string]bool)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int returns a pointer to the given int value.
|
||||
func Int(v int) *int {
|
||||
return &v
|
||||
}
|
||||
|
||||
// IntValue returns the value of the given int pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func IntValue(v *int) int {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// IntSlice converts a slice of int values into a slice of
|
||||
// int pointers
|
||||
func IntSlice(src []int) []*int {
|
||||
dst := make([]*int, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntValueSlice converts a slice of int pointers into a slice of
|
||||
// int values
|
||||
func IntValueSlice(src []*int) []int {
|
||||
dst := make([]int, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntMap converts a string map of int values into a string
|
||||
// map of int pointers
|
||||
func IntMap(src map[string]int) map[string]*int {
|
||||
dst := make(map[string]*int)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntValueMap converts a string map of int pointers into a string
|
||||
// map of int values
|
||||
func IntValueMap(src map[string]*int) map[string]int {
|
||||
dst := make(map[string]int)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32 returns a pointer to the given int32 value.
|
||||
func Int32(v int32) *int32 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Int32Value returns the value of the given int32 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Int32Value(v *int32) int32 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int32Slice converts a slice of int32 values into a slice of
|
||||
// int32 pointers
|
||||
func Int32Slice(src []int32) []*int32 {
|
||||
dst := make([]*int32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32ValueSlice converts a slice of int32 pointers into a slice of
|
||||
// int32 values
|
||||
func Int32ValueSlice(src []*int32) []int32 {
|
||||
dst := make([]int32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32Map converts a string map of int32 values into a string
|
||||
// map of int32 pointers
|
||||
func Int32Map(src map[string]int32) map[string]*int32 {
|
||||
dst := make(map[string]*int32)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32ValueMap converts a string map of int32 pointers into a string
|
||||
// map of int32 values
|
||||
func Int32ValueMap(src map[string]*int32) map[string]int32 {
|
||||
dst := make(map[string]int32)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64 returns a pointer to the given int64 value.
|
||||
func Int64(v int64) *int64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Int64Value returns the value of the given int64 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Int64Value(v *int64) int64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int64Slice converts a slice of int64 values into a slice of
|
||||
// int64 pointers
|
||||
func Int64Slice(src []int64) []*int64 {
|
||||
dst := make([]*int64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64ValueSlice converts a slice of int64 pointers into a slice of
|
||||
// int64 values
|
||||
func Int64ValueSlice(src []*int64) []int64 {
|
||||
dst := make([]int64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64Map converts a string map of int64 values into a string
|
||||
// map of int64 pointers
|
||||
func Int64Map(src map[string]int64) map[string]*int64 {
|
||||
dst := make(map[string]*int64)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64ValueMap converts a string map of int64 pointers into a string
|
||||
// map of int64 values
|
||||
func Int64ValueMap(src map[string]*int64) map[string]int64 {
|
||||
dst := make(map[string]int64)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32 returns a pointer to the given float32 value.
|
||||
func Float32(v float32) *float32 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Float32Value returns the value of the given float32 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Float32Value(v *float32) float32 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Float32Slice converts a slice of float32 values into a slice of
|
||||
// float32 pointers
|
||||
func Float32Slice(src []float32) []*float32 {
|
||||
dst := make([]*float32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32ValueSlice converts a slice of float32 pointers into a slice of
|
||||
// float32 values
|
||||
func Float32ValueSlice(src []*float32) []float32 {
|
||||
dst := make([]float32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32Map converts a string map of float32 values into a string
|
||||
// map of float32 pointers
|
||||
func Float32Map(src map[string]float32) map[string]*float32 {
|
||||
dst := make(map[string]*float32)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32ValueMap converts a string map of float32 pointers into a string
|
||||
// map of float32 values
|
||||
func Float32ValueMap(src map[string]*float32) map[string]float32 {
|
||||
dst := make(map[string]float32)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64 returns a pointer to the given float64 value.
|
||||
func Float64(v float64) *float64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Float64Value returns the value of the given float64 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Float64Value(v *float64) float64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Float64Slice converts a slice of float64 values into a slice of
|
||||
// float64 pointers
|
||||
func Float64Slice(src []float64) []*float64 {
|
||||
dst := make([]*float64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64ValueSlice converts a slice of float64 pointers into a slice of
|
||||
// float64 values
|
||||
func Float64ValueSlice(src []*float64) []float64 {
|
||||
dst := make([]float64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64Map converts a string map of float64 values into a string
|
||||
// map of float64 pointers
|
||||
func Float64Map(src map[string]float64) map[string]*float64 {
|
||||
dst := make(map[string]*float64)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64ValueMap converts a string map of float64 pointers into a string
|
||||
// map of float64 values
|
||||
func Float64ValueMap(src map[string]*float64) map[string]float64 {
|
||||
dst := make(map[string]float64)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Time returns a pointer to the given time.Time value.
|
||||
func Time(v time.Time) *time.Time {
|
||||
return &v
|
||||
}
|
||||
|
||||
// TimeValue returns the value of the given time.Time pointer or
|
||||
// time.Time{} if the pointer is nil.
|
||||
func TimeValue(v *time.Time) time.Time {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// TimeSlice converts a slice of time.Time values into a slice of
|
||||
// time.Time pointers
|
||||
func TimeSlice(src []time.Time) []*time.Time {
|
||||
dst := make([]*time.Time, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeValueSlice converts a slice of time.Time pointers into a slice of
|
||||
// time.Time values
|
||||
func TimeValueSlice(src []*time.Time) []time.Time {
|
||||
dst := make([]time.Time, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeMap converts a string map of time.Time values into a string
|
||||
// map of time.Time pointers
|
||||
func TimeMap(src map[string]time.Time) map[string]*time.Time {
|
||||
dst := make(map[string]*time.Time)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeValueMap converts a string map of time.Time pointers into a string
|
||||
// map of time.Time values
|
||||
func TimeValueMap(src map[string]*time.Time) map[string]time.Time {
|
||||
dst := make(map[string]time.Time)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
635
vendor/github.com/pengsrc/go-shared/convert/types_test.go
generated
vendored
Normal file
635
vendor/github.com/pengsrc/go-shared/convert/types_test.go
generated
vendored
Normal file
|
@ -0,0 +1,635 @@
|
|||
package convert
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStringValue(t *testing.T) {
|
||||
s := "string"
|
||||
assert.Equal(t, s, StringValue(String(s)))
|
||||
|
||||
assert.Equal(t, "", StringValue(nil))
|
||||
}
|
||||
|
||||
var testCasesStringSlice = [][]string{
|
||||
{"a", "b", "c", "d", "e"},
|
||||
{"a", "b", "", "", "e"},
|
||||
}
|
||||
|
||||
func TestStringSlice(t *testing.T) {
|
||||
for idx, in := range testCasesStringSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := StringValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesStringValueSlice = [][]*string{
|
||||
{String("a"), String("b"), nil, String("c")},
|
||||
}
|
||||
|
||||
func TestStringValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesStringValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := StringSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesStringMap = []map[string]string{
|
||||
{"a": "1", "b": "2", "c": "3"},
|
||||
}
|
||||
|
||||
func TestStringMap(t *testing.T) {
|
||||
for idx, in := range testCasesStringMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := StringValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoolValue(t *testing.T) {
|
||||
b := true
|
||||
assert.Equal(t, b, BoolValue(Bool(b)))
|
||||
|
||||
assert.Equal(t, false, BoolValue(nil))
|
||||
}
|
||||
|
||||
var testCasesBoolSlice = [][]bool{
|
||||
{true, true, false, false},
|
||||
}
|
||||
|
||||
func TestBoolSlice(t *testing.T) {
|
||||
for idx, in := range testCasesBoolSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := BoolValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolValueSlice = [][]*bool{}
|
||||
|
||||
func TestBoolValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesBoolValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := BoolSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolMap = []map[string]bool{
|
||||
{"a": true, "b": false, "c": true},
|
||||
}
|
||||
|
||||
func TestBoolMap(t *testing.T) {
|
||||
for idx, in := range testCasesBoolMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := BoolValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntValue(t *testing.T) {
|
||||
i := 1024
|
||||
assert.Equal(t, i, IntValue(Int(i)))
|
||||
|
||||
assert.Equal(t, 0, IntValue(nil))
|
||||
}
|
||||
|
||||
var testCasesIntSlice = [][]int{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestIntSlice(t *testing.T) {
|
||||
for idx, in := range testCasesIntSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := IntValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntValueSlice = [][]*int{}
|
||||
|
||||
func TestIntValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesIntValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := IntSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntMap = []map[string]int{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestIntMap(t *testing.T) {
|
||||
for idx, in := range testCasesIntMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := IntValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt64Value(t *testing.T) {
|
||||
i := int64(1024)
|
||||
assert.Equal(t, i, Int64Value(Int64(i)))
|
||||
|
||||
assert.Equal(t, int64(0), Int64Value(nil))
|
||||
}
|
||||
|
||||
var testCasesInt64Slice = [][]int64{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestInt64Slice(t *testing.T) {
|
||||
for idx, in := range testCasesInt64Slice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int64Slice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Int64ValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesInt64ValueSlice = [][]*int64{}
|
||||
|
||||
func TestInt64ValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesInt64ValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int64ValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := Int64Slice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesInt64Map = []map[string]int64{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestInt64Map(t *testing.T) {
|
||||
for idx, in := range testCasesInt64Map {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int64Map(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Int64ValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt32Value(t *testing.T) {
|
||||
i := int32(1024)
|
||||
assert.Equal(t, i, Int32Value(Int32(i)))
|
||||
|
||||
assert.Equal(t, int32(0), Int32Value(nil))
|
||||
}
|
||||
|
||||
var testCasesInt32Slice = [][]int32{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestInt32Slice(t *testing.T) {
|
||||
for idx, in := range testCasesInt32Slice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int32Slice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Int32ValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesInt32ValueSlice = [][]*int32{}
|
||||
|
||||
func TestInt32ValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesInt32ValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int32ValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := Int32Slice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesInt32Map = []map[string]int32{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestInt32Map(t *testing.T) {
|
||||
for idx, in := range testCasesInt32Map {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int32Map(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Int32ValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloat64Value(t *testing.T) {
|
||||
i := float64(1024)
|
||||
assert.Equal(t, i, Float64Value(Float64(i)))
|
||||
|
||||
assert.Equal(t, float64(0), Float64Value(nil))
|
||||
}
|
||||
|
||||
var testCasesFloat64Slice = [][]float64{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestFloat64Slice(t *testing.T) {
|
||||
for idx, in := range testCasesFloat64Slice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float64Slice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Float64ValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesFloat64ValueSlice = [][]*float64{}
|
||||
|
||||
func TestFloat64ValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesFloat64ValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float64ValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := Float64Slice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesFloat64Map = []map[string]float64{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestFloat64Map(t *testing.T) {
|
||||
for idx, in := range testCasesFloat64Map {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float64Map(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Float64ValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloat32Value(t *testing.T) {
|
||||
i := float32(1024)
|
||||
assert.Equal(t, i, Float32Value(Float32(i)))
|
||||
|
||||
assert.Equal(t, float32(0), Float32Value(nil))
|
||||
}
|
||||
|
||||
var testCasesFloat32Slice = [][]float32{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestFloat32Slice(t *testing.T) {
|
||||
for idx, in := range testCasesFloat32Slice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float32Slice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Float32ValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesFloat32ValueSlice = [][]*float32{}
|
||||
|
||||
func TestFloat32ValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesFloat32ValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float32ValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := Float32Slice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesFloat32Map = []map[string]float32{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestFloat32Map(t *testing.T) {
|
||||
for idx, in := range testCasesFloat32Map {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float32Map(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Float32ValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeValue(t *testing.T) {
|
||||
tm := time.Time{}
|
||||
assert.Equal(t, tm, TimeValue(Time(tm)))
|
||||
|
||||
assert.Equal(t, time.Time{}, TimeValue(nil))
|
||||
}
|
||||
|
||||
var testCasesTimeSlice = [][]time.Time{
|
||||
{time.Now(), time.Now().AddDate(100, 0, 0)},
|
||||
}
|
||||
|
||||
func TestTimeSlice(t *testing.T) {
|
||||
for idx, in := range testCasesTimeSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := TimeValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeValueSlice = [][]*time.Time{}
|
||||
|
||||
func TestTimeValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesTimeValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := TimeSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeMap = []map[string]time.Time{
|
||||
{"a": time.Now().AddDate(-100, 0, 0), "b": time.Now()},
|
||||
}
|
||||
|
||||
func TestTimeMap(t *testing.T) {
|
||||
for idx, in := range testCasesTimeMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := TimeValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
28
vendor/github.com/pengsrc/go-shared/glide.lock
generated
vendored
Normal file
28
vendor/github.com/pengsrc/go-shared/glide.lock
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
hash: d9fb8784d4c53a209ba12b5be1dc51d43b925ff53a06b5df850a9f7afa5e3e08
|
||||
updated: 2017-04-11T15:44:30.513321945+08:00
|
||||
imports:
|
||||
- name: github.com/davecgh/go-spew
|
||||
version: 346938d642f2ec3594ed81d874461961cd0faa76
|
||||
subpackages:
|
||||
- spew
|
||||
- name: github.com/Jeffail/gabs
|
||||
version: 2a3aa15961d5fee6047b8151b67ac2f08ba2c48c
|
||||
- name: github.com/pmezard/go-difflib
|
||||
version: 792786c7400a136282c1664665ae0a8db921c6c2
|
||||
subpackages:
|
||||
- difflib
|
||||
- name: github.com/Sirupsen/logrus
|
||||
version: d26492970760ca5d33129d2d799e34be5c4782eb
|
||||
- name: github.com/stretchr/testify
|
||||
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
|
||||
subpackages:
|
||||
- assert
|
||||
- name: golang.org/x/sys
|
||||
version: f3918c30c5c2cb527c0b071a27c35120a6c0719a
|
||||
repo: https://github.com/golang/sys.git
|
||||
subpackages:
|
||||
- unix
|
||||
- name: gopkg.in/yaml.v2
|
||||
version: a5b47d31c556af34a302ce5d659e6fea44d90de0
|
||||
repo: https://github.com/go-yaml/yaml.git
|
||||
testImports: []
|
23
vendor/github.com/pengsrc/go-shared/glide.yaml
generated
vendored
Normal file
23
vendor/github.com/pengsrc/go-shared/glide.yaml
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
package: github.com/pengsrc/go-shared
|
||||
import:
|
||||
# Test
|
||||
- package: github.com/stretchr/testify
|
||||
version: v1.1.4
|
||||
- package: github.com/davecgh/go-spew
|
||||
version: v1.1.0
|
||||
- package: github.com/pmezard/go-difflib
|
||||
version: v1.0.0
|
||||
# JSON
|
||||
- package: github.com/Jeffail/gabs
|
||||
version: 1.0
|
||||
# YAML
|
||||
- package: gopkg.in/yaml.v2
|
||||
version: a5b47d31c556af34a302ce5d659e6fea44d90de0
|
||||
repo: https://github.com/go-yaml/yaml.git
|
||||
# Logging
|
||||
- package: github.com/Sirupsen/logrus
|
||||
version: v0.11.0
|
||||
# GoLang
|
||||
- package: golang.org/x/sys
|
||||
version: f3918c30c5c2cb527c0b071a27c35120a6c0719a
|
||||
repo: https://github.com/golang/sys.git
|
50
vendor/github.com/pengsrc/go-shared/json/json.go
generated
vendored
Normal file
50
vendor/github.com/pengsrc/go-shared/json/json.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// Encode encode given interface to json byte slice.
|
||||
func Encode(source interface{}, unescape bool) ([]byte, error) {
|
||||
bytesResult, err := json.Marshal(source)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
if unescape {
|
||||
bytesResult = bytes.Replace(bytesResult, []byte("\\u003c"), []byte("<"), -1)
|
||||
bytesResult = bytes.Replace(bytesResult, []byte("\\u003e"), []byte(">"), -1)
|
||||
bytesResult = bytes.Replace(bytesResult, []byte("\\u0026"), []byte("&"), -1)
|
||||
}
|
||||
|
||||
return bytesResult, nil
|
||||
}
|
||||
|
||||
// Decode decode given json byte slice to corresponding struct.
|
||||
func Decode(content []byte, destinations ...interface{}) (interface{}, error) {
|
||||
var destination interface{}
|
||||
var err error
|
||||
if len(destinations) == 1 {
|
||||
destination = destinations[0]
|
||||
err = json.Unmarshal(content, destination)
|
||||
} else {
|
||||
err = json.Unmarshal(content, &destination)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return destination, err
|
||||
}
|
||||
|
||||
// FormatToReadable formats given json byte slice prettily.
|
||||
func FormatToReadable(source []byte) ([]byte, error) {
|
||||
var out bytes.Buffer
|
||||
err := json.Indent(&out, source, "", " ") // Using 2 space indent
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
return out.Bytes(), nil
|
||||
}
|
79
vendor/github.com/pengsrc/go-shared/json/json_test.go
generated
vendored
Normal file
79
vendor/github.com/pengsrc/go-shared/json/json_test.go
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestJSONDecodeUnknown(t *testing.T) {
|
||||
jsonString := `{
|
||||
"key1" : "This is a string.",
|
||||
"key2" : 10.50,
|
||||
"key3": [null, {"nestedKey1": "Another string"}]
|
||||
}`
|
||||
|
||||
anyData, err := Decode([]byte(jsonString))
|
||||
assert.NoError(t, err)
|
||||
data := anyData.(map[string]interface{})
|
||||
assert.Equal(t, 10.50, data["key2"])
|
||||
|
||||
var anotherData interface{}
|
||||
_, err = Decode([]byte(jsonString), &anotherData)
|
||||
assert.NoError(t, err)
|
||||
data = anyData.(map[string]interface{})
|
||||
assert.Equal(t, 10.50, data["key2"])
|
||||
|
||||
_, err = Decode([]byte(`- - -`), &JSONMustError{})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestJSONDecodeKnown(t *testing.T) {
|
||||
type SampleJSON struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
sampleJSONString := `{"name": "NAME"}`
|
||||
|
||||
sample := SampleJSON{Name: "NaMe", Description: "DeScRiPtIoN"}
|
||||
anyDataPointer, err := Decode([]byte(sampleJSONString), &sample)
|
||||
assert.NoError(t, err)
|
||||
data := anyDataPointer.(*SampleJSON)
|
||||
assert.Equal(t, "NAME", sample.Name)
|
||||
assert.Equal(t, "DeScRiPtIoN", sample.Description)
|
||||
assert.Equal(t, "NAME", (*data).Name)
|
||||
assert.Equal(t, "DeScRiPtIoN", (*data).Description)
|
||||
}
|
||||
|
||||
func TestJSONEncode(t *testing.T) {
|
||||
type SampleJSON struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
sample := SampleJSON{Name: "NaMe", Description: "DeScRiPtIoN"}
|
||||
|
||||
jsonBytes, err := Encode(sample, true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `{"name":"NaMe","description":"DeScRiPtIoN"}`, string(jsonBytes))
|
||||
|
||||
_, err = Encode(&JSONMustError{}, true)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestJSONFormatToReadable(t *testing.T) {
|
||||
sampleJSONString := `{"name": "NAME"}`
|
||||
|
||||
jsonBytes, err := FormatToReadable([]byte(sampleJSONString))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "{\n \"name\": \"NAME\"\n}", string(jsonBytes))
|
||||
|
||||
_, err = FormatToReadable([]byte(`XXXXX`))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
type JSONMustError struct{}
|
||||
|
||||
func (*JSONMustError) MarshalJSON() ([]byte, error) {
|
||||
return []byte{}, errors.New("marshal error")
|
||||
}
|
358
vendor/github.com/pengsrc/go-shared/logger/logger.go
generated
vendored
Normal file
358
vendor/github.com/pengsrc/go-shared/logger/logger.go
generated
vendored
Normal file
|
@ -0,0 +1,358 @@
|
|||
// Package logger provides support for logging to stdout and stderr.
|
||||
package logger
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
|
||||
"github.com/pengsrc/go-shared/convert"
|
||||
"github.com/pengsrc/go-shared/reopen"
|
||||
)
|
||||
|
||||
// LogFormatter is used to format log entry.
|
||||
type LogFormatter struct{}
|
||||
|
||||
// Format formats a given log entry, returns byte slice and error.
|
||||
func (c *LogFormatter) Format(entry *log.Entry) ([]byte, error) {
|
||||
level := strings.ToUpper(entry.Level.String())
|
||||
if level == "WARNING" {
|
||||
level = "WARN"
|
||||
}
|
||||
if len(level) < 5 {
|
||||
level = strings.Repeat(" ", 5-len(level)) + level
|
||||
}
|
||||
|
||||
return []byte(
|
||||
fmt.Sprintf(
|
||||
"[%s #%d] %s -- : %s\n",
|
||||
convert.TimeToString(time.Now(), convert.ISO8601Milli),
|
||||
os.Getpid(),
|
||||
level,
|
||||
entry.Message,
|
||||
),
|
||||
), nil
|
||||
}
|
||||
|
||||
// NewLogFormatter creates a new log formatter.
|
||||
func NewLogFormatter() *LogFormatter {
|
||||
return &LogFormatter{}
|
||||
}
|
||||
|
||||
// ErrorHook presents error hook.
|
||||
type ErrorHook struct {
|
||||
levels []log.Level
|
||||
|
||||
out io.Writer
|
||||
formatter log.Formatter
|
||||
}
|
||||
|
||||
// Levels returns error log levels.
|
||||
func (eh *ErrorHook) Levels() []log.Level {
|
||||
return eh.levels
|
||||
}
|
||||
|
||||
// Fire triggers before logging.
|
||||
func (eh *ErrorHook) Fire(entry *log.Entry) error {
|
||||
formatted, err := eh.formatter.Format(entry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = eh.out.Write(formatted)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewErrorHook creates new error hook.
|
||||
func NewErrorHook(out io.Writer) *ErrorHook {
|
||||
return &ErrorHook{
|
||||
levels: []log.Level{
|
||||
log.WarnLevel,
|
||||
log.ErrorLevel,
|
||||
log.FatalLevel,
|
||||
log.PanicLevel,
|
||||
},
|
||||
out: out,
|
||||
formatter: NewLogFormatter(),
|
||||
}
|
||||
}
|
||||
|
||||
// Logger presents a logger.
|
||||
type Logger struct {
|
||||
origLogger *log.Logger
|
||||
|
||||
out io.Writer
|
||||
errOut io.Writer
|
||||
|
||||
bufferedOut Flusher
|
||||
bufferedErrOut Flusher
|
||||
}
|
||||
|
||||
// Flusher defines a interface with Flush() method.
|
||||
type Flusher interface {
|
||||
Flush()
|
||||
}
|
||||
|
||||
// GetLevel get the log level string.
|
||||
func (l *Logger) GetLevel() string {
|
||||
return l.origLogger.Level.String()
|
||||
}
|
||||
|
||||
// SetLevel sets the log level. Valid levels are "debug", "info", "warn", "error", and "fatal".
|
||||
func (l *Logger) SetLevel(level string) {
|
||||
lvl, err := log.ParseLevel(level)
|
||||
if err != nil {
|
||||
l.Fatal(fmt.Sprintf(`log level not valid: "%s"`, level))
|
||||
}
|
||||
l.origLogger.Level = lvl
|
||||
}
|
||||
|
||||
// Flush writes buffered logs.
|
||||
func (l *Logger) Flush() {
|
||||
if l.bufferedOut != nil {
|
||||
l.bufferedOut.Flush()
|
||||
}
|
||||
if l.bufferedErrOut != nil {
|
||||
l.bufferedErrOut.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
// Debug logs a message with severity DEBUG.
|
||||
func (l *Logger) Debug(message string) {
|
||||
l.output(l.origLogger.Debug, message)
|
||||
}
|
||||
|
||||
// Info logs a message with severity INFO.
|
||||
func (l *Logger) Info(message string) {
|
||||
l.output(l.origLogger.Info, message)
|
||||
}
|
||||
|
||||
// Warn logs a message with severity WARN.
|
||||
func (l *Logger) Warn(message string) {
|
||||
l.output(l.origLogger.Warn, message)
|
||||
}
|
||||
|
||||
// Error logs a message with severity ERROR.
|
||||
func (l *Logger) Error(message string) {
|
||||
l.output(l.origLogger.Error, message)
|
||||
}
|
||||
|
||||
// Fatal logs a message with severity ERROR followed by a call to os.Exit().
|
||||
func (l *Logger) Fatal(message string) {
|
||||
l.output(l.origLogger.Fatal, message)
|
||||
}
|
||||
|
||||
// Debugf logs a message with severity DEBUG in format.
|
||||
func (l *Logger) Debugf(format string, v ...interface{}) {
|
||||
l.output(l.origLogger.Debug, format, v...)
|
||||
}
|
||||
|
||||
// Infof logs a message with severity INFO in format.
|
||||
func (l *Logger) Infof(format string, v ...interface{}) {
|
||||
l.output(l.origLogger.Info, format, v...)
|
||||
}
|
||||
|
||||
// Warnf logs a message with severity WARN in format.
|
||||
func (l *Logger) Warnf(format string, v ...interface{}) {
|
||||
l.output(l.origLogger.Warn, format, v...)
|
||||
}
|
||||
|
||||
// Errorf logs a message with severity ERROR in format.
|
||||
func (l *Logger) Errorf(format string, v ...interface{}) {
|
||||
l.output(l.origLogger.Error, format, v...)
|
||||
}
|
||||
|
||||
// Fatalf logs a message with severity ERROR in format followed by a call to
|
||||
// os.Exit().
|
||||
func (l *Logger) Fatalf(format string, v ...interface{}) {
|
||||
l.output(l.origLogger.Fatal, format, v...)
|
||||
}
|
||||
|
||||
func (l *Logger) output(origin func(...interface{}), formatOrMessage string, v ...interface{}) {
|
||||
if len(v) > 0 {
|
||||
origin(fmt.Sprintf(formatOrMessage, v...))
|
||||
} else {
|
||||
origin(formatOrMessage)
|
||||
}
|
||||
}
|
||||
|
||||
// CheckLevel checks whether the log level is valid.
|
||||
func CheckLevel(level string) error {
|
||||
if _, err := log.ParseLevel(level); err != nil {
|
||||
return fmt.Errorf(`log level not valid: "%s"`, level)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewFileLogger creates a logger that write into file.
|
||||
func NewFileLogger(filePath string, level ...string) (*Logger, error) {
|
||||
return NewFileLoggerWithErr(filePath, "", level...)
|
||||
}
|
||||
|
||||
// NewFileLoggerWithErr creates a logger that write into files.
|
||||
func NewFileLoggerWithErr(filePath, errFilePath string, level ...string) (*Logger, error) {
|
||||
if err := checkDir(path.Dir(filePath)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if errFilePath != "" {
|
||||
if err := checkDir(path.Dir(errFilePath)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out, err := reopen.NewFileWriter(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var errOut *reopen.FileWriter
|
||||
if errFilePath != "" {
|
||||
errOut, err = reopen.NewFileWriter(errFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
c := make(chan os.Signal)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-c:
|
||||
out.Reopen()
|
||||
if errOut != nil {
|
||||
errOut.Reopen()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
signal.Notify(c, syscall.SIGHUP)
|
||||
|
||||
if errOut == nil {
|
||||
return NewLoggerWithErr(out, nil, level...)
|
||||
}
|
||||
return NewLoggerWithErr(out, errOut, level...)
|
||||
}
|
||||
|
||||
// NewBufferedFileLogger creates a logger that write into file with buffer.
|
||||
func NewBufferedFileLogger(filePath string, level ...string) (*Logger, error) {
|
||||
return NewBufferedFileLoggerWithErr(filePath, "", level...)
|
||||
}
|
||||
|
||||
// NewBufferedFileLoggerWithErr creates a logger that write into files with buffer.
|
||||
func NewBufferedFileLoggerWithErr(filePath, errFilePath string, level ...string) (*Logger, error) {
|
||||
if err := checkDir(path.Dir(filePath)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if errFilePath != "" {
|
||||
if err := checkDir(path.Dir(errFilePath)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out, err := reopen.NewFileWriter(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var errOut *reopen.FileWriter
|
||||
if errFilePath != "" {
|
||||
errOut, err = reopen.NewFileWriter(errFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
bufferedOut := reopen.NewBufferedFileWriter(out)
|
||||
var bufferedErrOut *reopen.BufferedFileWriter
|
||||
if errOut != nil {
|
||||
bufferedErrOut = reopen.NewBufferedFileWriter(errOut)
|
||||
}
|
||||
|
||||
c := make(chan os.Signal)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-c:
|
||||
bufferedOut.Reopen()
|
||||
if bufferedErrOut != nil {
|
||||
bufferedErrOut.Reopen()
|
||||
}
|
||||
case <-time.After(10 * time.Second):
|
||||
bufferedOut.Flush()
|
||||
if bufferedErrOut != nil {
|
||||
bufferedErrOut.Flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
signal.Notify(c, syscall.SIGHUP)
|
||||
|
||||
if bufferedErrOut == nil {
|
||||
return NewLoggerWithErr(bufferedOut, nil, level...)
|
||||
}
|
||||
return NewLoggerWithErr(bufferedOut, bufferedErrOut, level...)
|
||||
}
|
||||
|
||||
// NewTerminalLogger creates a logger that write into terminal.
|
||||
func NewTerminalLogger(level ...string) (*Logger, error) {
|
||||
return NewLogger(os.Stdout, level...)
|
||||
}
|
||||
|
||||
// NewTerminalLoggerWithErr creates a logger that write into terminal.
|
||||
func NewTerminalLoggerWithErr(level ...string) (*Logger, error) {
|
||||
return NewLoggerWithErr(os.Stdout, os.Stderr, level...)
|
||||
}
|
||||
|
||||
// NewLogger creates a new logger for given out and level, and the level is
|
||||
// optional.
|
||||
func NewLogger(out io.Writer, level ...string) (*Logger, error) {
|
||||
return NewLoggerWithErr(out, nil, level...)
|
||||
}
|
||||
|
||||
// NewLoggerWithErr creates a new logger for given out, err out, level, and the
|
||||
// err out can be nil, and the level is optional.
|
||||
func NewLoggerWithErr(out, errOut io.Writer, level ...string) (*Logger, error) {
|
||||
if out == nil {
|
||||
return nil, errors.New(`must specify the output for logger`)
|
||||
}
|
||||
l := &Logger{
|
||||
origLogger: &log.Logger{
|
||||
Out: out,
|
||||
Formatter: NewLogFormatter(),
|
||||
Hooks: log.LevelHooks{},
|
||||
Level: log.WarnLevel,
|
||||
},
|
||||
out: out,
|
||||
errOut: errOut,
|
||||
}
|
||||
|
||||
if errOut != nil {
|
||||
l.origLogger.Hooks.Add(NewErrorHook(l.errOut))
|
||||
}
|
||||
|
||||
if len(level) == 1 {
|
||||
if err := CheckLevel(level[0]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l.SetLevel(level[0])
|
||||
}
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func checkDir(dir string) error {
|
||||
if info, err := os.Stat(dir); err != nil {
|
||||
return fmt.Errorf(`directory not exists: %s`, dir)
|
||||
} else if !info.IsDir() {
|
||||
return fmt.Errorf(`path is not directory: %s`, dir)
|
||||
}
|
||||
return nil
|
||||
}
|
218
vendor/github.com/pengsrc/go-shared/logger/logger_test.go
generated
vendored
Normal file
218
vendor/github.com/pengsrc/go-shared/logger/logger_test.go
generated
vendored
Normal file
|
@ -0,0 +1,218 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCheckLevel(t *testing.T) {
|
||||
assert.NoError(t, CheckLevel("warn"))
|
||||
assert.Error(t, CheckLevel("invalid"))
|
||||
}
|
||||
|
||||
func TestSetAndGetLevel(t *testing.T) {
|
||||
l, err := NewTerminalLogger()
|
||||
assert.NoError(t, err)
|
||||
|
||||
l.SetLevel("error")
|
||||
assert.Equal(t, "error", l.GetLevel())
|
||||
}
|
||||
|
||||
func TestNewFileLogger(t *testing.T) {
|
||||
logFile := "/tmp/logger-test/test.log"
|
||||
dir := path.Dir(logFile)
|
||||
err := os.MkdirAll(dir, 0775)
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
l, err := NewFileLogger(logFile, "debug")
|
||||
assert.NoError(t, err)
|
||||
|
||||
l.Debug("file - debug")
|
||||
l.Info("file - info")
|
||||
l.Warn("file - warn")
|
||||
l.Error("file - error")
|
||||
|
||||
log, err := ioutil.ReadFile(logFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 5, len(strings.Split(string(log), "\n")))
|
||||
|
||||
// Move log file.
|
||||
movedLogFile := fmt.Sprintf(`%s.move`, logFile)
|
||||
os.Rename(logFile, movedLogFile)
|
||||
|
||||
l.Error("file - error")
|
||||
|
||||
log, err = ioutil.ReadFile(movedLogFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 6, len(strings.Split(string(log), "\n")))
|
||||
|
||||
// Reopen.
|
||||
syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
l.Warn("file - warn")
|
||||
l.Error("file - error")
|
||||
|
||||
log, err = ioutil.ReadFile(logFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 3, len(strings.Split(string(log), "\n")))
|
||||
}
|
||||
|
||||
func TestNewFileLoggerWithWf(t *testing.T) {
|
||||
logFile := "/tmp/logger-test/test.log"
|
||||
errLogFile := "/tmp/logger-test/test.log.wf"
|
||||
dir := path.Dir(logFile)
|
||||
err := os.MkdirAll(dir, 0775)
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
l, err := NewFileLoggerWithErr(logFile, errLogFile, "debug")
|
||||
assert.NoError(t, err)
|
||||
|
||||
l.Debug("file - debug")
|
||||
l.Info("file - info")
|
||||
l.Warn("file - warn")
|
||||
l.Error("file - error")
|
||||
|
||||
log, err := ioutil.ReadFile(logFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 5, len(strings.Split(string(log), "\n")))
|
||||
|
||||
errLog, err := ioutil.ReadFile(errLogFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 3, len(strings.Split(string(errLog), "\n")))
|
||||
|
||||
// Move log file.
|
||||
movedLogFile := fmt.Sprintf(`%s.move`, logFile)
|
||||
os.Rename(logFile, movedLogFile)
|
||||
|
||||
movedErrLogFile := fmt.Sprintf(`%s.move`, errLogFile)
|
||||
os.Rename(errLogFile, movedErrLogFile)
|
||||
|
||||
l.Error("file - error")
|
||||
|
||||
log, err = ioutil.ReadFile(movedLogFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 6, len(strings.Split(string(log), "\n")))
|
||||
|
||||
errLog, err = ioutil.ReadFile(movedErrLogFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 4, len(strings.Split(string(errLog), "\n")))
|
||||
|
||||
// Reopen.
|
||||
syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
l.Warn("file - warn")
|
||||
l.Error("file - error")
|
||||
|
||||
log, err = ioutil.ReadFile(logFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 3, len(strings.Split(string(log), "\n")))
|
||||
|
||||
errLog, err = ioutil.ReadFile(errLogFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 3, len(strings.Split(string(errLog), "\n")))
|
||||
}
|
||||
|
||||
func TestBufferedFileLogger(t *testing.T) {
|
||||
logFile := "/tmp/logger-test/test.log"
|
||||
dir := path.Dir(logFile)
|
||||
err := os.MkdirAll(dir, 0775)
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
l, err := NewBufferedFileLogger(logFile, "debug")
|
||||
assert.NoError(t, err)
|
||||
|
||||
l.Debug("file - debug")
|
||||
l.Info("file - info")
|
||||
l.Warn("file - warn")
|
||||
l.Error("file - error")
|
||||
|
||||
log, err := ioutil.ReadFile(logFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(strings.Split(string(log), "\n")))
|
||||
|
||||
// Wait timeout.
|
||||
//time.Sleep(10*time.Second + 10*time.Millisecond)
|
||||
//
|
||||
//log, err = ioutil.ReadFile(logFile)
|
||||
//assert.NoError(t, err)
|
||||
//assert.Equal(t, 5, len(strings.Split(string(log), "\n")))
|
||||
}
|
||||
|
||||
func TestBufferedFileLoggerWithErr(t *testing.T) {
|
||||
logFile := "/tmp/logger-test/test.log"
|
||||
errLogFile := "/tmp/logger-test/test.log.wf"
|
||||
dir := path.Dir(logFile)
|
||||
err := os.MkdirAll(dir, 0775)
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
errL, err := NewBufferedFileLoggerWithErr(logFile, errLogFile, "debug")
|
||||
assert.NoError(t, err)
|
||||
|
||||
errL.Debug("file - debug")
|
||||
errL.Info("file - info")
|
||||
errL.Warn("file - warn")
|
||||
errL.Error("file - error")
|
||||
|
||||
log, err := ioutil.ReadFile(logFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(strings.Split(string(log), "\n")))
|
||||
|
||||
errLog, err := ioutil.ReadFile(errLogFile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(strings.Split(string(errLog), "\n")))
|
||||
|
||||
// Wait timeout.
|
||||
//time.Sleep(10*time.Second + 10*time.Millisecond)
|
||||
//
|
||||
//log, err = ioutil.ReadFile(logFile)
|
||||
//assert.NoError(t, err)
|
||||
//assert.Equal(t, 5, len(strings.Split(string(log), "\n")))
|
||||
//
|
||||
//errLog, err = ioutil.ReadFile(errLogFile)
|
||||
//assert.NoError(t, err)
|
||||
//assert.Equal(t, 3, len(strings.Split(string(errLog), "\n")))
|
||||
}
|
||||
|
||||
func TestTerminalLogger(t *testing.T) {
|
||||
l, err := NewTerminalLogger("debug")
|
||||
assert.NoError(t, err)
|
||||
|
||||
l.Debug("terminal - debug")
|
||||
l.Info("terminal - info")
|
||||
l.Warn("terminal - warn")
|
||||
l.Error("terminal - error")
|
||||
|
||||
l.Debugf("terminal - debug - %d", time.Now().Unix())
|
||||
l.Infof("terminal - info - %d", time.Now().Unix())
|
||||
l.Warnf("terminal - warn - %d", time.Now().Unix())
|
||||
l.Errorf("terminal - error - %d", time.Now().Unix())
|
||||
}
|
||||
|
||||
func TestTerminalLoggerWithErr(t *testing.T) {
|
||||
errL, err := NewTerminalLoggerWithErr("debug")
|
||||
assert.NoError(t, err)
|
||||
|
||||
errL.Debug("terminal - debug - err")
|
||||
errL.Info("terminal - info - err")
|
||||
errL.Warn("terminal - warn - err")
|
||||
errL.Error("terminal - error - err")
|
||||
|
||||
errL.Debugf("terminal - debug - err - %d", time.Now().Unix())
|
||||
errL.Infof("terminal - info - err - %d", time.Now().Unix())
|
||||
errL.Warnf("terminal - warn - err - %d", time.Now().Unix())
|
||||
errL.Errorf("terminal - error - err - %d", time.Now().Unix())
|
||||
}
|
49
vendor/github.com/pengsrc/go-shared/pid/pidfile.go
generated
vendored
Normal file
49
vendor/github.com/pengsrc/go-shared/pid/pidfile.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Package pid provides structure and helper functions to create and remove
|
||||
// PID file. A PID file is usually a file used to store the process ID of a
|
||||
// running process.
|
||||
package pid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// File is a file used to store the process ID of a running process.
|
||||
type File struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func checkPIDFileAlreadyExists(path string) error {
|
||||
if pidByte, err := ioutil.ReadFile(path); err == nil {
|
||||
pidString := strings.TrimSpace(string(pidByte))
|
||||
if pid, err := strconv.Atoi(pidString); err == nil {
|
||||
if processExists(pid) {
|
||||
return fmt.Errorf("pid file found, ensure server is not running or delete %s", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// New creates a PID file using the specified path.
|
||||
func New(path string) (*File, error) {
|
||||
if err := checkPIDFileAlreadyExists(path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ioutil.WriteFile(path, []byte(fmt.Sprintf("%d", os.Getpid())), 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &File{path: path}, nil
|
||||
}
|
||||
|
||||
// Remove removes the File.
|
||||
func (file File) Remove() error {
|
||||
if err := os.Remove(file.path); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
14
vendor/github.com/pengsrc/go-shared/pid/pidfile_darwin.go
generated
vendored
Normal file
14
vendor/github.com/pengsrc/go-shared/pid/pidfile_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// +build darwin
|
||||
|
||||
package pid
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func processExists(pid int) bool {
|
||||
// OS X does not have a proc filesystem.
|
||||
// Use kill -0 pid to judge if the process exists.
|
||||
err := syscall.Kill(pid, 0)
|
||||
return err == nil
|
||||
}
|
38
vendor/github.com/pengsrc/go-shared/pid/pidfile_test.go
generated
vendored
Normal file
38
vendor/github.com/pengsrc/go-shared/pid/pidfile_test.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
package pid
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewAndRemove(t *testing.T) {
|
||||
dir, err := ioutil.TempDir(os.TempDir(), "test-pidfile")
|
||||
if err != nil {
|
||||
t.Fatal("Could not create test directory")
|
||||
}
|
||||
|
||||
path := filepath.Join(dir, "testfile")
|
||||
file, err := New(path)
|
||||
if err != nil {
|
||||
t.Fatal("Could not create test file", err)
|
||||
}
|
||||
|
||||
_, err = New(path)
|
||||
if err == nil {
|
||||
t.Fatal("Test file creation not blocked")
|
||||
}
|
||||
|
||||
if err := file.Remove(); err != nil {
|
||||
t.Fatal("Could not delete created test file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveInvalidPath(t *testing.T) {
|
||||
file := File{path: filepath.Join("foo", "bar")}
|
||||
|
||||
if err := file.Remove(); err == nil {
|
||||
t.Fatal("Non-existing file doesn't give an error on delete")
|
||||
}
|
||||
}
|
16
vendor/github.com/pengsrc/go-shared/pid/pidfile_unix.go
generated
vendored
Normal file
16
vendor/github.com/pengsrc/go-shared/pid/pidfile_unix.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
// +build !windows,!darwin
|
||||
|
||||
package pid
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func processExists(pid int) bool {
|
||||
if _, err := os.Stat(filepath.Join("/proc", strconv.Itoa(pid))); err == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
23
vendor/github.com/pengsrc/go-shared/pid/pidfile_windows.go
generated
vendored
Normal file
23
vendor/github.com/pengsrc/go-shared/pid/pidfile_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
package pid
|
||||
|
||||
import "syscall"
|
||||
|
||||
const (
|
||||
processQueryLimitedInformation = 0x1000
|
||||
|
||||
stillActive = 259
|
||||
)
|
||||
|
||||
func processExists(pid int) bool {
|
||||
h, err := syscall.OpenProcess(processQueryLimitedInformation, false, uint32(pid))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
var c uint32
|
||||
err = syscall.GetExitCodeProcess(h, &c)
|
||||
syscall.Close(h)
|
||||
if err != nil {
|
||||
return c == stillActive
|
||||
}
|
||||
return true
|
||||
}
|
176
vendor/github.com/pengsrc/go-shared/reopen/reopen.go
generated
vendored
Normal file
176
vendor/github.com/pengsrc/go-shared/reopen/reopen.go
generated
vendored
Normal file
|
@ -0,0 +1,176 @@
|
|||
package reopen
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Reopener interface defines something that can be reopened.
|
||||
type Reopener interface {
|
||||
Reopen() error
|
||||
}
|
||||
|
||||
// Writer is a writer that also can be reopened.
|
||||
type Writer interface {
|
||||
Reopener
|
||||
io.Writer
|
||||
}
|
||||
|
||||
// WriteCloser is a io.WriteCloser that can also be reopened.
|
||||
type WriteCloser interface {
|
||||
Reopener
|
||||
io.WriteCloser
|
||||
}
|
||||
|
||||
// FileWriter that can also be reopened.
|
||||
type FileWriter struct {
|
||||
// Ensures close/reopen/write are not called at the same time, protects f
|
||||
mu sync.Mutex
|
||||
f *os.File
|
||||
mode os.FileMode
|
||||
name string
|
||||
}
|
||||
|
||||
// Close calls the under lying File.Close().
|
||||
func (f *FileWriter) Close() error {
|
||||
f.mu.Lock()
|
||||
err := f.f.Close()
|
||||
f.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// Reopen the file.
|
||||
func (f *FileWriter) Reopen() error {
|
||||
f.mu.Lock()
|
||||
err := f.reopen()
|
||||
f.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// Write implements the stander io.Writer interface.
|
||||
func (f *FileWriter) Write(p []byte) (int, error) {
|
||||
f.mu.Lock()
|
||||
n, err := f.f.Write(p)
|
||||
f.mu.Unlock()
|
||||
return n, err
|
||||
}
|
||||
|
||||
// reopen with mutex free.
|
||||
func (f *FileWriter) reopen() error {
|
||||
if f.f != nil {
|
||||
f.f.Close()
|
||||
f.f = nil
|
||||
}
|
||||
ff, err := os.OpenFile(f.name, os.O_WRONLY|os.O_APPEND|os.O_CREATE, f.mode)
|
||||
if err != nil {
|
||||
f.f = nil
|
||||
return err
|
||||
}
|
||||
f.f = ff
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewFileWriter opens a file for appending and writing and can be reopened.
|
||||
// It is a ReopenWriteCloser...
|
||||
func NewFileWriter(name string) (*FileWriter, error) {
|
||||
// Standard default mode
|
||||
return NewFileWriterMode(name, 0644)
|
||||
}
|
||||
|
||||
// NewFileWriterMode opens a Reopener file with a specific permission.
|
||||
func NewFileWriterMode(name string, mode os.FileMode) (*FileWriter, error) {
|
||||
writer := FileWriter{
|
||||
f: nil,
|
||||
name: name,
|
||||
mode: mode,
|
||||
}
|
||||
err := writer.reopen()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &writer, nil
|
||||
}
|
||||
|
||||
// BufferedFileWriter is buffer writer than can be reopened.
|
||||
type BufferedFileWriter struct {
|
||||
mu sync.Mutex
|
||||
OrigWriter *FileWriter
|
||||
BufWriter *bufio.Writer
|
||||
}
|
||||
|
||||
// Reopen implement Reopener.
|
||||
func (bw *BufferedFileWriter) Reopen() error {
|
||||
bw.mu.Lock()
|
||||
bw.BufWriter.Flush()
|
||||
|
||||
// Use non-mutex version since we are using this one.
|
||||
err := bw.OrigWriter.reopen()
|
||||
|
||||
bw.BufWriter.Reset(io.Writer(bw.OrigWriter))
|
||||
bw.mu.Unlock()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Close flushes the internal buffer and closes the destination file.
|
||||
func (bw *BufferedFileWriter) Close() error {
|
||||
bw.mu.Lock()
|
||||
bw.BufWriter.Flush()
|
||||
bw.OrigWriter.f.Close()
|
||||
bw.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write implements io.Writer (and reopen.Writer).
|
||||
func (bw *BufferedFileWriter) Write(p []byte) (int, error) {
|
||||
bw.mu.Lock()
|
||||
n, err := bw.BufWriter.Write(p)
|
||||
|
||||
// Special Case... if the used space in the buffer is LESS than
|
||||
// the input, then we did a flush in the middle of the line
|
||||
// and the full log line was not sent on its way.
|
||||
if bw.BufWriter.Buffered() < len(p) {
|
||||
bw.BufWriter.Flush()
|
||||
}
|
||||
|
||||
bw.mu.Unlock()
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Flush flushes the buffer.
|
||||
func (bw *BufferedFileWriter) Flush() {
|
||||
bw.mu.Lock()
|
||||
bw.BufWriter.Flush()
|
||||
bw.OrigWriter.f.Sync()
|
||||
bw.mu.Unlock()
|
||||
}
|
||||
|
||||
// flushDaemon periodically flushes the log file buffers.
|
||||
func (bw *BufferedFileWriter) flushDaemon(interval time.Duration) {
|
||||
for range time.NewTicker(interval).C {
|
||||
bw.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
const bufferSize = 256 * 1024
|
||||
const flushInterval = 30 * time.Second
|
||||
|
||||
// NewBufferedFileWriter opens a buffered file that is periodically flushed.
|
||||
func NewBufferedFileWriter(w *FileWriter) *BufferedFileWriter {
|
||||
return NewBufferedFileWriterSize(w, bufferSize, flushInterval)
|
||||
}
|
||||
|
||||
// NewBufferedFileWriterSize opens a buffered file with the given size that is periodically
|
||||
// flushed on the given interval.
|
||||
func NewBufferedFileWriterSize(w *FileWriter, size int, flush time.Duration) *BufferedFileWriter {
|
||||
bw := BufferedFileWriter{
|
||||
OrigWriter: w,
|
||||
BufWriter: bufio.NewWriterSize(w, size),
|
||||
}
|
||||
go bw.flushDaemon(flush)
|
||||
return &bw
|
||||
}
|
124
vendor/github.com/pengsrc/go-shared/reopen/reopen_test.go
generated
vendored
Normal file
124
vendor/github.com/pengsrc/go-shared/reopen/reopen_test.go
generated
vendored
Normal file
|
@ -0,0 +1,124 @@
|
|||
package reopen
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestReopenAppend tests that we always append to an existing file
|
||||
func TestReopenAppend(t *testing.T) {
|
||||
filename := "/tmp/reopen_test_foo"
|
||||
defer os.Remove(filename)
|
||||
|
||||
// Create a sample file using normal means.
|
||||
orig, err := os.Create(filename)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create initial file %s: %s", filename, err)
|
||||
}
|
||||
_, err = orig.Write([]byte("line0\n"))
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to write initial line %s: %s", filename, err)
|
||||
}
|
||||
err = orig.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to close initial file: %s", err)
|
||||
}
|
||||
|
||||
// Test that making a new File appends.
|
||||
f, err := NewFileWriter(filename)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create %s", filename)
|
||||
}
|
||||
_, err = f.Write([]byte("line1\n"))
|
||||
if err != nil {
|
||||
t.Errorf("Got write error1: %s", err)
|
||||
}
|
||||
|
||||
// Test that reopen always appends.
|
||||
err = f.Reopen()
|
||||
if err != nil {
|
||||
t.Errorf("Got reopen error %s: %s", filename, err)
|
||||
}
|
||||
_, err = f.Write([]byte("line2\n"))
|
||||
if err != nil {
|
||||
t.Errorf("Got write error2 on %s: %s", filename, err)
|
||||
}
|
||||
|
||||
// Close file.
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
t.Errorf("Got closing error for %s: %s", filename, err)
|
||||
}
|
||||
|
||||
// Read file, make sure it contains line0, line1, line2.
|
||||
out, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable read in final file %s: %s", filename, err)
|
||||
}
|
||||
outStr := string(out)
|
||||
if outStr != "line0\nline1\nline2\n" {
|
||||
t.Errorf("Result was %s", outStr)
|
||||
}
|
||||
}
|
||||
|
||||
// TestChangeINode tests that reopen works when inode is swapped out.
|
||||
func TestChangeINODE(t *testing.T) {
|
||||
filename := "/tmp/reopen_test_foo"
|
||||
moveFilename := "/tmp/reopen_test_foo.orig"
|
||||
defer os.Remove(filename)
|
||||
defer os.Remove(moveFilename)
|
||||
|
||||
// Step 1 -- Create a sample file using normal means.
|
||||
orig, err := os.Create(filename)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create initial file %s: %s", filename, err)
|
||||
}
|
||||
err = orig.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to close initial file: %s", err)
|
||||
}
|
||||
|
||||
// Step 2 -- Test that making a new File appends.
|
||||
f, err := NewFileWriter(filename)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create %s", filename)
|
||||
}
|
||||
_, err = f.Write([]byte("line1\n"))
|
||||
if err != nil {
|
||||
t.Errorf("Got write error1: %s", err)
|
||||
}
|
||||
|
||||
// Step 3 -- Now move file.
|
||||
err = os.Rename(filename, moveFilename)
|
||||
if err != nil {
|
||||
t.Errorf("Renaming error: %s", err)
|
||||
}
|
||||
f.Write([]byte("after1\n"))
|
||||
|
||||
// Step Test that reopen always appends.
|
||||
err = f.Reopen()
|
||||
if err != nil {
|
||||
t.Errorf("Got reopen error %s: %s", filename, err)
|
||||
}
|
||||
_, err = f.Write([]byte("line2\n"))
|
||||
if err != nil {
|
||||
t.Errorf("Got write error2 on %s: %s", filename, err)
|
||||
}
|
||||
|
||||
// Close file.
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
t.Errorf("Got closing error for %s: %s", filename, err)
|
||||
}
|
||||
|
||||
// Read file, make sure it contains line0, line1, line2.
|
||||
out, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable read in final file %s: %s", filename, err)
|
||||
}
|
||||
outStr := string(out)
|
||||
if outStr != "line2\n" {
|
||||
t.Errorf("Result was %s", outStr)
|
||||
}
|
||||
}
|
151
vendor/github.com/pengsrc/go-shared/rest/rest.go
generated
vendored
Normal file
151
vendor/github.com/pengsrc/go-shared/rest/rest.go
generated
vendored
Normal file
|
@ -0,0 +1,151 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/Jeffail/gabs"
|
||||
)
|
||||
|
||||
// Method contains the supported HTTP verbs.
|
||||
type Method string
|
||||
|
||||
// Supported HTTP verbs.
|
||||
const (
|
||||
Get Method = "GET"
|
||||
Post Method = "POST"
|
||||
Put Method = "PUT"
|
||||
Patch Method = "PATCH"
|
||||
Delete Method = "DELETE"
|
||||
)
|
||||
|
||||
// Request holds the request to an API Call.
|
||||
type Request struct {
|
||||
Method Method
|
||||
BaseURL string // e.g. https://api.service.com
|
||||
Headers map[string]string
|
||||
QueryParams map[string]string
|
||||
Body []byte
|
||||
}
|
||||
|
||||
// Response holds the response from an API call.
|
||||
type Response struct {
|
||||
StatusCode int // e.g. 200
|
||||
Headers http.Header // e.g. map[X-Rate-Limit:[600]]
|
||||
Body string // e.g. {"result: success"}
|
||||
JSON *gabs.Container
|
||||
}
|
||||
|
||||
// ParseJSON parses the response body to JSON container.
|
||||
func (r *Response) ParseJSON() error {
|
||||
if strings.Contains(r.Headers.Get("Content-Type"), "application/json") {
|
||||
json, err := gabs.ParseJSON([]byte(r.Body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.JSON = json
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("response body is not JSON")
|
||||
}
|
||||
|
||||
// DefaultClient is used if no custom HTTP client is defined
|
||||
var DefaultClient = &Client{HTTPClient: http.DefaultClient}
|
||||
|
||||
// Client allows modification of client headers, redirect policy
|
||||
// and other settings
|
||||
// See https://golang.org/pkg/net/http
|
||||
type Client struct {
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// The following functions enable the ability to define a
|
||||
// custom HTTP Client
|
||||
|
||||
// MakeRequest makes the API call.
|
||||
func (c *Client) MakeRequest(req *http.Request) (*http.Response, error) {
|
||||
return c.HTTPClient.Do(req)
|
||||
}
|
||||
|
||||
// API is the main interface to the API.
|
||||
func (c *Client) API(r *Request) (*Response, error) {
|
||||
// Build the HTTP request object.
|
||||
req, err := BuildRequestObject(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build the HTTP client and make the request.
|
||||
res, err := c.MakeRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build Response object.
|
||||
response, err := BuildResponse(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// AddQueryParameters adds query parameters to the URL.
|
||||
func AddQueryParameters(baseURL string, queryParams map[string]string) string {
|
||||
baseURL += "?"
|
||||
params := url.Values{}
|
||||
for key, value := range queryParams {
|
||||
params.Add(key, value)
|
||||
}
|
||||
return baseURL + params.Encode()
|
||||
}
|
||||
|
||||
// BuildRequestObject creates the HTTP request object.
|
||||
func BuildRequestObject(r *Request) (*http.Request, error) {
|
||||
// Add any query parameters to the URL.
|
||||
if len(r.QueryParams) != 0 {
|
||||
r.BaseURL = AddQueryParameters(r.BaseURL, r.QueryParams)
|
||||
}
|
||||
req, err := http.NewRequest(string(r.Method), r.BaseURL, bytes.NewBuffer(r.Body))
|
||||
for key, value := range r.Headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
_, exists := req.Header["Content-Type"]
|
||||
if len(r.Body) > 0 && !exists {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
return req, err
|
||||
}
|
||||
|
||||
// BuildResponse builds the response struct.
|
||||
func BuildResponse(r *http.Response) (*Response, error) {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
response := Response{
|
||||
StatusCode: r.StatusCode,
|
||||
Body: string(body),
|
||||
Headers: r.Header,
|
||||
}
|
||||
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// MakeRequest makes the API call.
|
||||
func MakeRequest(r *http.Request) (*http.Response, error) {
|
||||
return DefaultClient.HTTPClient.Do(r)
|
||||
}
|
||||
|
||||
// API is the main interface to the API.
|
||||
func API(request *Request) (*Response, error) {
|
||||
return DefaultClient.API(request)
|
||||
}
|
138
vendor/github.com/pengsrc/go-shared/rest/rest_test.go
generated
vendored
Normal file
138
vendor/github.com/pengsrc/go-shared/rest/rest_test.go
generated
vendored
Normal file
|
@ -0,0 +1,138 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBuildURL(t *testing.T) {
|
||||
testURL := AddQueryParameters(
|
||||
"http://api.test.com",
|
||||
map[string]string{
|
||||
"test": "1",
|
||||
"test2": "2",
|
||||
},
|
||||
)
|
||||
assert.Equal(t, "http://api.test.com?test=1&test2=2", testURL)
|
||||
}
|
||||
|
||||
func TestBuildRequest(t *testing.T) {
|
||||
request := Request{
|
||||
Method: Get,
|
||||
BaseURL: "http://api.test.com",
|
||||
Headers: map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer APK_KEY",
|
||||
},
|
||||
QueryParams: map[string]string{
|
||||
"test": "1",
|
||||
"test2": "2",
|
||||
},
|
||||
}
|
||||
req, err := BuildRequestObject(&request)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, req)
|
||||
}
|
||||
|
||||
func TestBuildResponse(t *testing.T) {
|
||||
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/not+json")
|
||||
fmt.Fprintln(w, "{\"message\": \"success\"}")
|
||||
}))
|
||||
defer fakeServer.Close()
|
||||
|
||||
request := Request{
|
||||
Method: Get,
|
||||
BaseURL: fakeServer.URL,
|
||||
}
|
||||
req, err := BuildRequestObject(&request)
|
||||
assert.NoError(t, err)
|
||||
|
||||
res, err := MakeRequest(req)
|
||||
assert.NoError(t, err)
|
||||
|
||||
response, err := BuildResponse(res)
|
||||
assert.NoError(t, err)
|
||||
err = response.ParseJSON()
|
||||
assert.Error(t, err)
|
||||
|
||||
assert.Equal(t, 200, response.StatusCode)
|
||||
assert.NotEqual(t, 0, len(response.Body))
|
||||
assert.NotEqual(t, 0, len(response.Headers))
|
||||
assert.Nil(t, response.JSON)
|
||||
}
|
||||
|
||||
func TestRest(t *testing.T) {
|
||||
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
fmt.Fprintln(w, "{\"message\": \"success\"}")
|
||||
}))
|
||||
defer fakeServer.Close()
|
||||
|
||||
request := Request{
|
||||
Method: Get,
|
||||
BaseURL: fakeServer.URL + "/test_endpoint",
|
||||
Headers: map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer APK_KEY",
|
||||
},
|
||||
QueryParams: map[string]string{
|
||||
"test": "1",
|
||||
"test2": "2",
|
||||
},
|
||||
}
|
||||
response, err := API(&request)
|
||||
assert.NoError(t, err)
|
||||
err = response.ParseJSON()
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 200, response.StatusCode)
|
||||
assert.NotEqual(t, 0, len(response.Body))
|
||||
assert.NotEqual(t, 0, len(response.Headers))
|
||||
assert.Equal(t, "success", response.JSON.Path("message").Data().(string))
|
||||
}
|
||||
|
||||
func TestDefaultContentType(t *testing.T) {
|
||||
request := Request{
|
||||
Method: Get,
|
||||
BaseURL: "http://localhost",
|
||||
Body: []byte(`{"hello": "world"}`),
|
||||
}
|
||||
req, err := BuildRequestObject(&request)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "application/json", req.Header.Get("Content-Type"))
|
||||
}
|
||||
|
||||
func TestCustomContentType(t *testing.T) {
|
||||
request := Request{
|
||||
Method: Get,
|
||||
BaseURL: "http://localhost",
|
||||
Headers: map[string]string{"Content-Type": "custom"},
|
||||
Body: []byte("Hello World"),
|
||||
}
|
||||
res, err := BuildRequestObject(&request)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "custom", res.Header.Get("Content-Type"))
|
||||
}
|
||||
|
||||
func TestCustomHTTPClient(t *testing.T) {
|
||||
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
time.Sleep(time.Millisecond * 20)
|
||||
fmt.Fprintln(w, "{\"message\": \"success\"}")
|
||||
}))
|
||||
defer fakeServer.Close()
|
||||
|
||||
request := Request{
|
||||
Method: Get,
|
||||
BaseURL: fakeServer.URL + "/test_endpoint",
|
||||
}
|
||||
customClient := &Client{&http.Client{Timeout: time.Millisecond * 10}}
|
||||
_, err := customClient.API(&request)
|
||||
assert.True(t, strings.Contains(err.Error(), "Client.Timeout exceeded while awaiting headers"))
|
||||
}
|
32
vendor/github.com/pengsrc/go-shared/yaml/yaml.go
generated
vendored
Normal file
32
vendor/github.com/pengsrc/go-shared/yaml/yaml.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Encode encode given interface to yaml byte slice.
|
||||
func Encode(source interface{}) ([]byte, error) {
|
||||
bytesResult, err := yaml.Marshal(source)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
return bytesResult, nil
|
||||
}
|
||||
|
||||
// Decode decode given yaml byte slice to corresponding struct.
|
||||
func Decode(content []byte, destinations ...interface{}) (interface{}, error) {
|
||||
var destination interface{}
|
||||
var err error
|
||||
if len(destinations) == 1 {
|
||||
destination = destinations[0]
|
||||
err = yaml.Unmarshal(content, destination)
|
||||
} else {
|
||||
err = yaml.Unmarshal(content, &destination)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return destination, err
|
||||
}
|
72
vendor/github.com/pengsrc/go-shared/yaml/yaml_test.go
generated
vendored
Normal file
72
vendor/github.com/pengsrc/go-shared/yaml/yaml_test.go
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestYAMLDecodeUnknown(t *testing.T) {
|
||||
yamlString := `
|
||||
key1: "This is a string." # Single Line Comment
|
||||
key2: 10.50
|
||||
key3:
|
||||
- null
|
||||
- nestedKey1: Anothor string
|
||||
`
|
||||
|
||||
anyData, err := Decode([]byte(yamlString))
|
||||
assert.NoError(t, err)
|
||||
data := anyData.(map[interface{}]interface{})
|
||||
assert.Equal(t, 10.50, data["key2"])
|
||||
}
|
||||
|
||||
func TestYAMLDecodeKnown(t *testing.T) {
|
||||
type SampleYAML struct {
|
||||
Name string `yaml:"name"`
|
||||
Description string `yaml:"description"`
|
||||
}
|
||||
sampleYAMLString := `name: "NAME"`
|
||||
|
||||
sample := SampleYAML{Name: "NaMe", Description: "DeScRiPtIoN"}
|
||||
anyDataPointer, err := Decode([]byte(sampleYAMLString), &sample)
|
||||
assert.NoError(t, err)
|
||||
data := anyDataPointer.(*SampleYAML)
|
||||
assert.Equal(t, "NAME", sample.Name)
|
||||
assert.Equal(t, "DeScRiPtIoN", sample.Description)
|
||||
assert.Equal(t, "NAME", (*data).Name)
|
||||
assert.Equal(t, "DeScRiPtIoN", (*data).Description)
|
||||
|
||||
_, err = Decode([]byte(`- - -`), &YAMLMustError{})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestYAMLDecodeEmpty(t *testing.T) {
|
||||
yamlString := ""
|
||||
|
||||
anyData, err := Decode([]byte(yamlString))
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, anyData)
|
||||
}
|
||||
|
||||
func TestYAMLEncode(t *testing.T) {
|
||||
type SampleYAML struct {
|
||||
Name string `yaml:"name"`
|
||||
Description string `yaml:"description"`
|
||||
}
|
||||
sample := SampleYAML{Name: "NaMe", Description: "DeScRiPtIoN"}
|
||||
|
||||
yamlBytes, err := Encode(sample)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "name: NaMe\ndescription: DeScRiPtIoN\n", string(yamlBytes))
|
||||
|
||||
_, err = Encode(&YAMLMustError{})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
type YAMLMustError struct{}
|
||||
|
||||
func (*YAMLMustError) MarshalYAML() (interface{}, error) {
|
||||
return nil, errors.New("marshal error")
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue