Этот коммит содержится в:
Christopher Speller
2017-11-13 09:09:58 -08:00
коммит произвёл GitHub
родитель 7304a61ef5
Коммит 1329aa51b6
474 изменённых файлов: 84159 добавлений и 8829 удалений

Просмотреть файл

@@ -443,7 +443,7 @@ clean: stop-docker
cd $(BUILD_WEBAPP_DIR) && $(MAKE) clean cd $(BUILD_WEBAPP_DIR) && $(MAKE) clean
rm -rf api/data find . -type d -name data | xargs rm -r
rm -rf logs rm -rf logs
rm -f mattermost.log rm -f mattermost.log

Просмотреть файл

@@ -19,12 +19,8 @@ import (
// Enterprise Deps // Enterprise Deps
_ "github.com/dgryski/dgoogauth" _ "github.com/dgryski/dgoogauth"
_ "github.com/go-ldap/ldap" _ "github.com/go-ldap/ldap"
_ "github.com/mattermost/rsc/qr"
// Tmp deps for adding
_ "github.com/dimchansky/utfbom"
_ "github.com/hashicorp/memberlist" _ "github.com/hashicorp/memberlist"
_ "gopkg.in/gomail.v2" _ "github.com/mattermost/rsc/qr"
_ "gopkg.in/olivere/elastic.v5" _ "gopkg.in/olivere/elastic.v5"
) )

67
glide.lock сгенерированный
Просмотреть файл

@@ -1,11 +1,11 @@
hash: a63bdc06107e9917f943ab3af7d55d64702bc745e3a5dd0affa2c012a8d8e07f hash: 247f32b2f130a845591b5e1b573ae301517d0e5275dd17678969917155dd1c61
updated: 2017-09-29T08:20:31.615625246-07:00 updated: 2017-11-10T12:37:36.496151071-08:00
imports: imports:
- name: github.com/alecthomas/log4go - name: github.com/alecthomas/log4go
version: 3fbce08846379ec7f4f6bc7fce6dd01ce28fae4c version: 3fbce08846379ec7f4f6bc7fce6dd01ce28fae4c
repo: https://github.com/mattermost/log4go.git repo: https://github.com/mattermost/log4go.git
- name: github.com/armon/go-metrics - name: github.com/armon/go-metrics
version: 0a12dc6f6b9da6da644031a1b9b5a85478c5ee27 version: 9a4b6e10bed6220a1665955aa2b75afc91eb10b3
- name: github.com/beorn7/perks - name: github.com/beorn7/perks
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
subpackages: subpackages:
@@ -21,7 +21,7 @@ imports:
- name: github.com/dimchansky/utfbom - name: github.com/dimchansky/utfbom
version: 6c6132ff69f0f6c088739067407b5d32c52e1d0f version: 6c6132ff69f0f6c088739067407b5d32c52e1d0f
- name: github.com/disintegration/imaging - name: github.com/disintegration/imaging
version: c3956f26e8f5f2370428d573648fedc717fbe51e version: dd50a3ee9985ccd313a2f03c398fcaedc96dc707
- name: github.com/dyatlov/go-opengraph - name: github.com/dyatlov/go-opengraph
version: 41a3523719dfbe7e8f853fbd4061867543db5270 version: 41a3523719dfbe7e8f853fbd4061867543db5270
subpackages: subpackages:
@@ -29,11 +29,11 @@ imports:
- name: github.com/fsnotify/fsnotify - name: github.com/fsnotify/fsnotify
version: 629574ca2a5df945712d3079857300b5e4da0236 version: 629574ca2a5df945712d3079857300b5e4da0236
- name: github.com/go-ini/ini - name: github.com/go-ini/ini
version: c787282c39ac1fc618827141a1f762240def08a3 version: f280b3ba517bf5fc98922624f21fb0e7a92adaec
- name: github.com/go-ldap/ldap - name: github.com/go-ldap/ldap
version: 8168ee085ee43257585e50c6441aadf54ecb2c9f version: 8168ee085ee43257585e50c6441aadf54ecb2c9f
- name: github.com/go-redis/redis - name: github.com/go-redis/redis
version: 8e6b51ec3a92ec095dcbd2439c7a3eec6b6cb586 version: d0f86971b5d61de9cebd2616b932acb7ba14d957
subpackages: subpackages:
- internal - internal
- internal/consistenthash - internal/consistenthash
@@ -48,15 +48,15 @@ imports:
- raster - raster
- truetype - truetype
- name: github.com/golang/protobuf - name: github.com/golang/protobuf
version: 130e6b02ab059e7b717a096f397c5b60111cae74 version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9
subpackages: subpackages:
- proto - proto
- name: github.com/gorilla/context - name: github.com/gorilla/context
version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42
- name: github.com/gorilla/handlers - name: github.com/gorilla/handlers
version: a4043c62cc2329bacda331d33fc908ab11ef0ec3 version: 90663712d74cb411cbef281bc1e08c19d1a76145
- name: github.com/gorilla/mux - name: github.com/gorilla/mux
version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7 version: 7f08801859139f86dfafd1c296e2cba9a80d292e
- name: github.com/gorilla/websocket - name: github.com/gorilla/websocket
version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b
- name: github.com/hashicorp/errwrap - name: github.com/hashicorp/errwrap
@@ -70,13 +70,13 @@ imports:
- name: github.com/hashicorp/go-multierror - name: github.com/hashicorp/go-multierror
version: 83588e72410abfbe4df460eeb6f30841ae47d4c4 version: 83588e72410abfbe4df460eeb6f30841ae47d4c4
- name: github.com/hashicorp/go-sockaddr - name: github.com/hashicorp/go-sockaddr
version: 41949a141473f6340abc6ba0fcd0f89da6f6f837 version: 9b4c5fa5b10a683339a270d664474b9f4aee62fc
- name: github.com/hashicorp/golang-lru - name: github.com/hashicorp/golang-lru
version: 0a025b7e63adc15a622f29b0b2c4c3848243bbf6 version: 0a025b7e63adc15a622f29b0b2c4c3848243bbf6
subpackages: subpackages:
- simplelru - simplelru
- name: github.com/hashicorp/hcl - name: github.com/hashicorp/hcl
version: 68e816d1c783414e79bc65b3994d9ab6b0a722ab version: 23c074d0eceb2b8a5bfdbb271ab780cde70f05a8
subpackages: subpackages:
- hcl/ast - hcl/ast
- hcl/parser - hcl/parser
@@ -87,17 +87,17 @@ imports:
- json/scanner - json/scanner
- json/token - json/token
- name: github.com/hashicorp/memberlist - name: github.com/hashicorp/memberlist
version: 687988a0b5daaf7ed5051e5e374aef27f8254822 version: caa5d20d6a642b7543b3745e54031a96008bee57
- name: github.com/inconshreveable/mousetrap - name: github.com/inconshreveable/mousetrap
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
- name: github.com/jehiah/go-strftime - name: github.com/jehiah/go-strftime
version: 834e15c05a45371503440cc195bbd05c9a0968d9 version: 834e15c05a45371503440cc195bbd05c9a0968d9
- name: github.com/lib/pq - name: github.com/lib/pq
version: b77235e3890a962fe8a6f8c4c7198679ca7814e7 version: b609790bd85edf8e9ab7e0f8912750a786177bcf
subpackages: subpackages:
- oid - oid
- name: github.com/magiconair/properties - name: github.com/magiconair/properties
version: 8d7837e64d3c1ee4e54a880c5a920ab4316fc90a version: 49d762b9817ba1c2e9d0c69183c2b4a8b8f1d934
- name: github.com/mattermost/gorp - name: github.com/mattermost/gorp
version: 995ddf2264c4ad45fbaf342f7500e4787ebae84a version: 995ddf2264c4ad45fbaf342f7500e4787ebae84a
- name: github.com/mattermost/html2text - name: github.com/mattermost/html2text
@@ -113,7 +113,7 @@ imports:
subpackages: subpackages:
- pbutil - pbutil
- name: github.com/miekg/dns - name: github.com/miekg/dns
version: aade52d68e0bf400ae55afd3adadffce3b027043 version: 9fc4eb252eedf0ef8adc05169ce35da5e31beaba
subpackages: subpackages:
- internal/socket - internal/socket
- name: github.com/minio/go-homedir - name: github.com/minio/go-homedir
@@ -128,24 +128,24 @@ imports:
- pkg/s3utils - pkg/s3utils
- pkg/set - pkg/set
- name: github.com/mitchellh/mapstructure - name: github.com/mitchellh/mapstructure
version: d0303fe809921458f417bcf828397a65db30a7e4 version: 06020f85339e21b2478f756a78e295255ffa4d6a
- name: github.com/mssola/user_agent - name: github.com/mssola/user_agent
version: a2f39d5a9b15ecc1fa1005b6aae73cd83da240ef version: a2f39d5a9b15ecc1fa1005b6aae73cd83da240ef
- name: github.com/nicksnyder/go-i18n - name: github.com/nicksnyder/go-i18n
version: ca33e78c8a430e2df435b02f63a3944fa8e9ea11 version: 0dc1626d56435e9d605a29875701721c54bc9bbd
subpackages: subpackages:
- i18n - i18n
- i18n/bundle - i18n/bundle
- i18n/language - i18n/language
- i18n/translation - i18n/translation
- name: github.com/NYTimes/gziphandler - name: github.com/NYTimes/gziphandler
version: 97ae7fbaf81620fe97840685304a78a306a39c64 version: 843330b8a375e6460183b08e030190b1a1eaea13
- name: github.com/pborman/uuid - name: github.com/pborman/uuid
version: e790cca94e6cc75c7064b1332e63811d4aae1a53 version: e790cca94e6cc75c7064b1332e63811d4aae1a53
- name: github.com/pelletier/go-toml - name: github.com/pelletier/go-toml
version: 16398bac157da96aa88f98a2df640c7f32af1da2 version: 4e9e0ee19b60b13eb79915933f44d8ed5f268bdd
- name: github.com/pkg/errors - name: github.com/pkg/errors
version: 2b3a18b5f0fb6b4f9190549597d3f962c02bc5eb version: f15c970de5b76fac0b59abb32d62c17cc7bed265
- name: github.com/pmezard/go-difflib - name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
subpackages: subpackages:
@@ -159,11 +159,11 @@ imports:
subpackages: subpackages:
- go - go
- name: github.com/prometheus/common - name: github.com/prometheus/common
version: 2f17f4a9d485bf34b4bfaccc273805040e4f86c8 version: e3fb1a1acd7605367a2b378bc2e2f893c05174b7
subpackages: subpackages:
- expfmt - expfmt
- name: github.com/prometheus/procfs - name: github.com/prometheus/procfs
version: e645f4e5aaa8506fc71d6edbc5c4ff02c04c46f2 version: a6e9df898b1336106c743392c48ee0b71f5c4efa
- name: github.com/rsc/letsencrypt - name: github.com/rsc/letsencrypt
version: 33926faef6d434b854ea994228f11d0185faa0c1 version: 33926faef6d434b854ea994228f11d0185faa0c1
- name: github.com/rwcarlsen/goexif - name: github.com/rwcarlsen/goexif
@@ -178,19 +178,19 @@ imports:
- name: github.com/segmentio/backo-go - name: github.com/segmentio/backo-go
version: 204274ad699c0983a70203a566887f17a717fef4 version: 204274ad699c0983a70203a566887f17a717fef4
- name: github.com/spf13/afero - name: github.com/spf13/afero
version: ee1bd8ee15a1306d1f9201acc41ef39cd9f99a1b version: 5660eeed305fe5f69c8fc6cf899132a459a97064
subpackages: subpackages:
- mem - mem
- name: github.com/spf13/cast - name: github.com/spf13/cast
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
- name: github.com/spf13/cobra - name: github.com/spf13/cobra
version: b78744579491c1ceeaaa3b40205e56b0591b93a3 version: 2da4a54c5ceefcee7ca5dd0eea1e18a3b6366489
- name: github.com/spf13/jwalterweatherman - name: github.com/spf13/jwalterweatherman
version: 12bd96e66386c1960ab0f74ced1362f66f552f7b version: 12bd96e66386c1960ab0f74ced1362f66f552f7b
- name: github.com/spf13/pflag - name: github.com/spf13/pflag
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66 version: e57e3eeb33f795204c1ca35f56c44f83227c6e66
- name: github.com/spf13/viper - name: github.com/spf13/viper
version: 25b30aa063fc18e48662b86996252eabdcf2f0c7 version: 4dddf7c62e16bce5807744018f5b753bfe21bbd2
- name: github.com/stretchr/objx - name: github.com/stretchr/objx
version: cbeaeb16a013161a98496fad62933b1d21786672 version: cbeaeb16a013161a98496fad62933b1d21786672
- name: github.com/stretchr/testify - name: github.com/stretchr/testify
@@ -203,19 +203,19 @@ imports:
- name: github.com/tylerb/graceful - name: github.com/tylerb/graceful
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
- name: github.com/xenolf/lego - name: github.com/xenolf/lego
version: 5a2fd5039fbba3c06b640be91a2c436bc23f74e8 version: aa94fb4696349fd6f35168dabe3ab030ddf3e484
subpackages: subpackages:
- acme - acme
- name: github.com/xtgo/uuid - name: github.com/xtgo/uuid
version: a0b114877d4caeffbd7f87e3757c17fce570fea7 version: a0b114877d4caeffbd7f87e3757c17fce570fea7
- name: golang.org/x/crypto - name: golang.org/x/crypto
version: 76eec36fa14229c4b25bb894c2d0e591527af429 version: 6a293f2d4b14b8e6d3f0539e383f6d0d30fce3fd
subpackages: subpackages:
- bcrypt - bcrypt
- blowfish - blowfish
- ocsp - ocsp
- name: golang.org/x/image - name: golang.org/x/image
version: 334384d9e19178a0488c9360d94d183c1ef0f711 version: f7e31b4ea2e3413ab91b4e7d2dc83e5f8d19a44c
subpackages: subpackages:
- bmp - bmp
- font - font
@@ -223,18 +223,17 @@ imports:
- tiff - tiff
- tiff/lzw - tiff/lzw
- name: golang.org/x/net - name: golang.org/x/net
version: 0a9397675ba34b2845f758fe3cd68828369c6517 version: a337091b0525af65de94df2eb7e98bd9962dcbe2
subpackages: subpackages:
- context - context
- html - html
- html/atom - html/atom
- publicsuffix
- name: golang.org/x/sys - name: golang.org/x/sys
version: 314a259e304ff91bd6985da2a7149bbf91237993 version: 1e2299c37cc91a509f1b12369872d27be0ce98a6
subpackages: subpackages:
- unix - unix
- name: golang.org/x/text - name: golang.org/x/text
version: 1cbadb444a806fd9430d14ad08967ed91da4fa0a version: 88f656faf3f37f690df1a32515b479415e1a6769
subpackages: subpackages:
- transform - transform
- unicode/norm - unicode/norm
@@ -249,7 +248,7 @@ imports:
- name: gopkg.in/gomail.v2 - name: gopkg.in/gomail.v2
version: 41f3572897373c5538c50a2402db15db079fa4fd version: 41f3572897373c5538c50a2402db15db079fa4fd
- name: gopkg.in/olivere/elastic.v5 - name: gopkg.in/olivere/elastic.v5
version: 2a08d39723b7f4df92b96e2dff891a60952714d6 version: 171ce647da4acfb30ffc99981d66d80bdea6bcee
subpackages: subpackages:
- config - config
- uritemplates - uritemplates
@@ -259,7 +258,7 @@ imports:
- cipher - cipher
- json - json
- name: gopkg.in/throttled/throttled.v2 - name: gopkg.in/throttled/throttled.v2
version: b5675e93f9d999b22f92d859a5bf2138d3641af4 version: c4642cff38719000a875f10166ecb9599b002f96
subpackages: subpackages:
- store/memstore - store/memstore
- name: gopkg.in/yaml.v2 - name: gopkg.in/yaml.v2

Просмотреть файл

@@ -5,7 +5,7 @@ import:
repo: https://github.com/mattermost/log4go.git repo: https://github.com/mattermost/log4go.git
- package: github.com/dgryski/dgoogauth - package: github.com/dgryski/dgoogauth
- package: github.com/disintegration/imaging - package: github.com/disintegration/imaging
version: v1.2.2 version: v1.2.4
- package: github.com/dyatlov/go-opengraph - package: github.com/dyatlov/go-opengraph
subpackages: subpackages:
- opengraph - opengraph
@@ -17,9 +17,9 @@ import:
version: v1.3 version: v1.3
- package: github.com/golang/freetype - package: github.com/golang/freetype
- package: github.com/gorilla/handlers - package: github.com/gorilla/handlers
version: v1.2.1 version: v1.3.0
- package: github.com/gorilla/mux - package: github.com/gorilla/mux
version: v1.5.0 version: v1.6.0
- package: github.com/gorilla/websocket - package: github.com/gorilla/websocket
version: v1.2.0 version: v1.2.0
- package: github.com/lib/pq - package: github.com/lib/pq
@@ -30,7 +30,7 @@ import:
version: v3.0.3 version: v3.0.3
- package: github.com/mssola/user_agent - package: github.com/mssola/user_agent
- package: github.com/nicksnyder/go-i18n - package: github.com/nicksnyder/go-i18n
version: v1.9.0 version: v1.10.0
subpackages: subpackages:
- i18n - i18n
- package: github.com/pborman/uuid - package: github.com/pborman/uuid
@@ -55,7 +55,7 @@ import:
subpackages: subpackages:
- bmp - bmp
- package: gopkg.in/throttled/throttled.v2 - package: gopkg.in/throttled/throttled.v2
version: v2.0.3 version: v2.1.0
subpackages: subpackages:
- store/memstore - store/memstore
- package: github.com/prometheus/client_golang - package: github.com/prometheus/client_golang
@@ -81,11 +81,11 @@ import:
- package: github.com/prometheus/procfs - package: github.com/prometheus/procfs
- package: github.com/cpanato/html2text - package: github.com/cpanato/html2text
- package: gopkg.in/olivere/elastic.v5 - package: gopkg.in/olivere/elastic.v5
version: v5.0.48 version: v5.0.53
- package: github.com/mattermost/gorp - package: github.com/mattermost/gorp
version: 995ddf2264c4ad45fbaf342f7500e4787ebae84a version: 995ddf2264c4ad45fbaf342f7500e4787ebae84a
- package: github.com/go-redis/redis - package: github.com/go-redis/redis
version: v6.7.1 version: v6.7.3
- package: github.com/stretchr/testify - package: github.com/stretchr/testify
version: v1.1.4 version: v1.1.4
subpackages: subpackages:

12
vendor/github.com/NYTimes/gziphandler/gzip.go сгенерированный поставляемый
Просмотреть файл

@@ -82,6 +82,7 @@ type GzipResponseWriter struct {
buf []byte // Holds the first part of the write before reaching the minSize or the end of the write. buf []byte // Holds the first part of the write before reaching the minSize or the end of the write.
contentTypes []string // Only compress if the response is one of these content-types. All are accepted if empty. contentTypes []string // Only compress if the response is one of these content-types. All are accepted if empty.
flushed bool // Indicate if the stream was already flushed
} }
// Write appends data to the gzip writer. // Write appends data to the gzip writer.
@@ -150,7 +151,9 @@ func (w *GzipResponseWriter) startGzip() error {
// WriteHeader just saves the response code until close or GZIP effective writes. // WriteHeader just saves the response code until close or GZIP effective writes.
func (w *GzipResponseWriter) WriteHeader(code int) { func (w *GzipResponseWriter) WriteHeader(code int) {
w.code = code if w.code == 0 {
w.code = code
}
} }
// init graps a new gzip writer from the gzipWriterPool and writes the correct // init graps a new gzip writer from the gzipWriterPool and writes the correct
@@ -167,7 +170,8 @@ func (w *GzipResponseWriter) init() {
func (w *GzipResponseWriter) Close() error { func (w *GzipResponseWriter) Close() error {
if w.gw == nil { if w.gw == nil {
// Gzip not trigged yet, write out regular response. // Gzip not trigged yet, write out regular response.
if w.code != 0 { // WriteHeader only if it wasn't already wrote by a Flush
if !w.flushed && w.code != 0 {
w.ResponseWriter.WriteHeader(w.code) w.ResponseWriter.WriteHeader(w.code)
} }
if w.buf != nil { if w.buf != nil {
@@ -195,7 +199,11 @@ func (w *GzipResponseWriter) Flush() {
} }
if fw, ok := w.ResponseWriter.(http.Flusher); ok { if fw, ok := w.ResponseWriter.(http.Flusher); ok {
if !w.flushed && w.code != 0 {
w.ResponseWriter.WriteHeader(w.code)
}
fw.Flush() fw.Flush()
w.flushed = true
} }
} }

33
vendor/github.com/NYTimes/gziphandler/gzip_test.go сгенерированный поставляемый
Просмотреть файл

@@ -306,6 +306,39 @@ func TestStatusCodes(t *testing.T) {
} }
} }
func TestStatusCodesFlushed(t *testing.T) {
handler := GzipHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusNotFound)
rw.(http.Flusher).Flush()
rw.Write([]byte("Not found"))
}))
r := httptest.NewRequest(http.MethodGet, "/", nil)
r.Header.Set(acceptEncoding, "gzip")
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
result := w.Result()
if result.StatusCode != http.StatusNotFound {
t.Errorf("StatusCode should have been 404 but was %d", result.StatusCode)
}
}
func TestIgnoreSubsequentWriteHeader(t *testing.T) {
handler := GzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500)
w.WriteHeader(404)
}))
r := httptest.NewRequest("GET", "/", nil)
r.Header.Set("Accept-Encoding", "gzip")
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
result := w.Result()
if result.StatusCode != 500 {
t.Errorf("StatusCode should have been 500 but was %d", result.StatusCode)
}
}
func TestDontWriteWhenNotWrittenTo(t *testing.T) { func TestDontWriteWhenNotWrittenTo(t *testing.T) {
// When using gzip as middleware without ANY writes in the handler, // When using gzip as middleware without ANY writes in the handler,
// ensure the gzip middleware doesn't touch the actual ResponseWriter // ensure the gzip middleware doesn't touch the actual ResponseWriter

4
vendor/github.com/armon/go-metrics/inmem.go сгенерированный поставляемый
Просмотреть файл

@@ -70,7 +70,7 @@ func NewIntervalMetrics(intv time.Time) *IntervalMetrics {
// about a sample // about a sample
type AggregateSample struct { type AggregateSample struct {
Count int // The count of emitted pairs Count int // The count of emitted pairs
Rate float64 `json:"-"` // The count of emitted pairs per time unit (usually 1 second) Rate float64 // The values rate per time unit (usually 1 second)
Sum float64 // The sum of values Sum float64 // The sum of values
SumSq float64 `json:"-"` // The sum of squared values SumSq float64 `json:"-"` // The sum of squared values
Min float64 // Minimum value Min float64 // Minimum value
@@ -107,7 +107,7 @@ func (a *AggregateSample) Ingest(v float64, rateDenom float64) {
if v > a.Max || a.Count == 1 { if v > a.Max || a.Count == 1 {
a.Max = v a.Max = v
} }
a.Rate = float64(a.Count) / rateDenom a.Rate = float64(a.Sum) / rateDenom
a.LastUpdated = time.Now() a.LastUpdated = time.Now()
} }

8
vendor/github.com/armon/go-metrics/inmem_endpoint_test.go сгенерированный поставляемый
Просмотреть файл

@@ -61,7 +61,7 @@ func TestDisplayMetrics(t *testing.T) {
Max: 22, Max: 22,
Sum: 42, Sum: 42,
SumSq: 884, SumSq: 884,
Rate: 200, Rate: 4200,
}, },
Mean: 21, Mean: 21,
Stddev: 1.4142135623730951, Stddev: 1.4142135623730951,
@@ -75,7 +75,7 @@ func TestDisplayMetrics(t *testing.T) {
Max: 40, Max: 40,
Sum: 60, Sum: 60,
SumSq: 2000, SumSq: 2000,
Rate: 200, Rate: 6000,
}, },
Mean: 30, Mean: 30,
Stddev: 14.142135623730951, Stddev: 14.142135623730951,
@@ -92,7 +92,7 @@ func TestDisplayMetrics(t *testing.T) {
Max: 24, Max: 24,
Sum: 44, Sum: 44,
SumSq: 976, SumSq: 976,
Rate: 200, Rate: 4400,
}, },
Mean: 22, Mean: 22,
Stddev: 2.8284271247461903, Stddev: 2.8284271247461903,
@@ -106,7 +106,7 @@ func TestDisplayMetrics(t *testing.T) {
Max: 33, Max: 33,
Sum: 56, Sum: 56,
SumSq: 1618, SumSq: 1618,
Rate: 200, Rate: 5600,
}, },
Mean: 28, Mean: 28,
Stddev: 7.0710678118654755, Stddev: 7.0710678118654755,

2
vendor/github.com/armon/go-metrics/inmem_test.go сгенерированный поставляемый
Просмотреть файл

@@ -53,7 +53,7 @@ func TestInmemSink(t *testing.T) {
if agg.Count != 2 { if agg.Count != 2 {
t.Fatalf("bad val: %v", agg) t.Fatalf("bad val: %v", agg)
} }
if agg.Rate != 200 { if agg.Rate != 4200 {
t.Fatalf("bad val: %v", agg.Rate) t.Fatalf("bad val: %v", agg.Rate)
} }
if agg.Sum != 42 { if agg.Sum != 42 {

312
vendor/github.com/disintegration/imaging/clone.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,312 @@
package imaging
import (
"image"
"image/color"
)
// Clone returns a copy of the given image.
func Clone(img image.Image) *image.NRGBA {
dstBounds := img.Bounds().Sub(img.Bounds().Min)
dst := image.NewNRGBA(dstBounds)
switch src := img.(type) {
case *image.NRGBA:
copyNRGBA(dst, src)
case *image.NRGBA64:
copyNRGBA64(dst, src)
case *image.RGBA:
copyRGBA(dst, src)
case *image.RGBA64:
copyRGBA64(dst, src)
case *image.Gray:
copyGray(dst, src)
case *image.Gray16:
copyGray16(dst, src)
case *image.YCbCr:
copyYCbCr(dst, src)
case *image.Paletted:
copyPaletted(dst, src)
default:
copyImage(dst, src)
}
return dst
}
func copyNRGBA(dst *image.NRGBA, src *image.NRGBA) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
rowSize := dstW * 4
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
copy(dst.Pix[di:di+rowSize], src.Pix[si:si+rowSize])
}
})
}
func copyNRGBA64(dst *image.NRGBA, src *image.NRGBA64) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
dst.Pix[di+0] = src.Pix[si+0]
dst.Pix[di+1] = src.Pix[si+2]
dst.Pix[di+2] = src.Pix[si+4]
dst.Pix[di+3] = src.Pix[si+6]
di += 4
si += 8
}
}
})
}
func copyRGBA(dst *image.NRGBA, src *image.RGBA) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
a := src.Pix[si+3]
dst.Pix[di+3] = a
switch a {
case 0:
dst.Pix[di+0] = 0
dst.Pix[di+1] = 0
dst.Pix[di+2] = 0
case 0xff:
dst.Pix[di+0] = src.Pix[si+0]
dst.Pix[di+1] = src.Pix[si+1]
dst.Pix[di+2] = src.Pix[si+2]
default:
var tmp uint16
tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a)
dst.Pix[di+0] = uint8(tmp)
tmp = uint16(src.Pix[si+1]) * 0xff / uint16(a)
dst.Pix[di+1] = uint8(tmp)
tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a)
dst.Pix[di+2] = uint8(tmp)
}
di += 4
si += 4
}
}
})
}
func copyRGBA64(dst *image.NRGBA, src *image.RGBA64) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
a := src.Pix[si+6]
dst.Pix[di+3] = a
switch a {
case 0:
dst.Pix[di+0] = 0
dst.Pix[di+1] = 0
dst.Pix[di+2] = 0
case 0xff:
dst.Pix[di+0] = src.Pix[si+0]
dst.Pix[di+1] = src.Pix[si+2]
dst.Pix[di+2] = src.Pix[si+4]
default:
var tmp uint16
tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a)
dst.Pix[di+0] = uint8(tmp)
tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a)
dst.Pix[di+1] = uint8(tmp)
tmp = uint16(src.Pix[si+4]) * 0xff / uint16(a)
dst.Pix[di+2] = uint8(tmp)
}
di += 4
si += 8
}
}
})
}
func copyGray(dst *image.NRGBA, src *image.Gray) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := src.Pix[si]
dst.Pix[di+0] = c
dst.Pix[di+1] = c
dst.Pix[di+2] = c
dst.Pix[di+3] = 0xff
di += 4
si++
}
}
})
}
func copyGray16(dst *image.NRGBA, src *image.Gray16) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := src.Pix[si]
dst.Pix[di+0] = c
dst.Pix[di+1] = c
dst.Pix[di+2] = c
dst.Pix[di+3] = 0xff
di += 4
si += 2
}
}
})
}
func copyYCbCr(dst *image.NRGBA, src *image.YCbCr) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
srcY := srcMinY + dstY
di := dst.PixOffset(0, dstY)
for dstX := 0; dstX < dstW; dstX++ {
srcX := srcMinX + dstX
siy := (srcY-srcMinY)*src.YStride + (srcX - srcMinX)
var sic int
switch src.SubsampleRatio {
case image.YCbCrSubsampleRatio444:
sic = (srcY-srcMinY)*src.CStride + (srcX - srcMinX)
case image.YCbCrSubsampleRatio422:
sic = (srcY-srcMinY)*src.CStride + (srcX/2 - srcMinX/2)
case image.YCbCrSubsampleRatio420:
sic = (srcY/2-srcMinY/2)*src.CStride + (srcX/2 - srcMinX/2)
case image.YCbCrSubsampleRatio440:
sic = (srcY/2-srcMinY/2)*src.CStride + (srcX - srcMinX)
default:
sic = src.COffset(srcX, srcY)
}
y := int32(src.Y[siy])
cb := int32(src.Cb[sic]) - 128
cr := int32(src.Cr[sic]) - 128
r := (y<<16 + 91881*cr + 1<<15) >> 16
if r > 255 {
r = 255
} else if r < 0 {
r = 0
}
g := (y<<16 - 22554*cb - 46802*cr + 1<<15) >> 16
if g > 255 {
g = 255
} else if g < 0 {
g = 0
}
b := (y<<16 + 116130*cb + 1<<15) >> 16
if b > 255 {
b = 255
} else if b < 0 {
b = 0
}
dst.Pix[di+0] = uint8(r)
dst.Pix[di+1] = uint8(g)
dst.Pix[di+2] = uint8(b)
dst.Pix[di+3] = 255
di += 4
}
}
})
}
func copyPaletted(dst *image.NRGBA, src *image.Paletted) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
plen := len(src.Palette)
pnew := make([]color.NRGBA, plen)
for i := 0; i < plen; i++ {
pnew[i] = color.NRGBAModel.Convert(src.Palette[i]).(color.NRGBA)
}
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := pnew[src.Pix[si]]
dst.Pix[di+0] = c.R
dst.Pix[di+1] = c.G
dst.Pix[di+2] = c.B
dst.Pix[di+3] = c.A
di += 4
si++
}
}
})
}
func copyImage(dst *image.NRGBA, src image.Image) {
srcMinX := src.Bounds().Min.X
srcMinY := src.Bounds().Min.Y
dstW := dst.Bounds().Dx()
dstH := dst.Bounds().Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := color.NRGBAModel.Convert(src.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA)
dst.Pix[di+0] = c.R
dst.Pix[di+1] = c.G
dst.Pix[di+2] = c.B
dst.Pix[di+3] = c.A
di += 4
}
}
})
}
// toNRGBA converts any image type to *image.NRGBA with min-point at (0, 0).
func toNRGBA(img image.Image) *image.NRGBA {
if img, ok := img.(*image.NRGBA); ok && img.Bounds().Min.Eq(image.ZP) {
return img
}
return Clone(img)
}

247
vendor/github.com/disintegration/imaging/clone_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,247 @@
package imaging
import (
"image"
"image/color"
"testing"
)
func TestClone(t *testing.T) {
td := []struct {
desc string
src image.Image
want *image.NRGBA
}{
{
"Clone NRGBA",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
},
{
"Clone NRGBA64",
&image.NRGBA64{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 8,
Pix: []uint8{
0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff,
},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
},
{
"Clone RGBA",
&image.RGBA{
Rect: image.Rect(-1, -1, 0, 2),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 3),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
},
{
"Clone RGBA64",
&image.RGBA64{
Rect: image.Rect(-1, -1, 0, 2),
Stride: 1 * 8,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff,
},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 3),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
},
{
"Clone Gray",
&image.Gray{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 1,
Pix: []uint8{0x11, 0xee},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff},
},
},
{
"Clone Gray16",
&image.Gray16{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 2,
Pix: []uint8{0x11, 0x11, 0xee, 0xee},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff},
},
},
{
"Clone Alpha",
&image.Alpha{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 1,
Pix: []uint8{0x11, 0xee},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{0xff, 0xff, 0xff, 0x11, 0xff, 0xff, 0xff, 0xee},
},
},
{
"Clone YCbCr",
&image.YCbCr{
Rect: image.Rect(-1, -1, 5, 0),
SubsampleRatio: image.YCbCrSubsampleRatio444,
YStride: 6,
CStride: 6,
Y: []uint8{0x00, 0xff, 0x7f, 0x26, 0x4b, 0x0e},
Cb: []uint8{0x80, 0x80, 0x80, 0x6b, 0x56, 0xc0},
Cr: []uint8{0x80, 0x80, 0x80, 0xc0, 0x4b, 0x76},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 6, 1),
Stride: 6 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff,
0x7f, 0x7f, 0x7f, 0xff,
0x7f, 0x00, 0x00, 0xff,
0x00, 0x7f, 0x00, 0xff,
0x00, 0x00, 0x7f, 0xff,
},
},
},
{
"Clone YCbCr 444",
&image.YCbCr{
Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
Cb: []uint8{0x55, 0xd4, 0xff, 0x8e, 0x2c, 0x01, 0x6b, 0xaa, 0xc0, 0x95, 0x56, 0x40, 0x80, 0x80, 0x80, 0x80},
Cr: []uint8{0xff, 0xeb, 0x6b, 0x36, 0x15, 0x95, 0xc0, 0xb5, 0x76, 0x41, 0x4b, 0x8c, 0x80, 0x80, 0x80, 0x80},
YStride: 4,
CStride: 4,
SubsampleRatio: image.YCbCrSubsampleRatio444,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
&image.NRGBA{
Pix: []uint8{0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x49, 0xe1, 0xca, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, 0x7f, 0x0, 0x0, 0xff, 0x7f, 0x0, 0x7f, 0xff, 0x0, 0x0, 0x7f, 0xff, 0x0, 0x7f, 0x7f, 0xff, 0x0, 0x7f, 0x0, 0xff, 0x82, 0x7f, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
Stride: 16,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
},
{
"Clone YCbCr 440",
&image.YCbCr{
Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
Cb: []uint8{0x2c, 0x01, 0x6b, 0xaa, 0x80, 0x80, 0x80, 0x80},
Cr: []uint8{0x15, 0x95, 0xc0, 0xb5, 0x80, 0x80, 0x80, 0x80},
YStride: 4,
CStride: 4,
SubsampleRatio: image.YCbCrSubsampleRatio440,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
&image.NRGBA{
Pix: []uint8{0x0, 0xb5, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x77, 0x0, 0x0, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0x0, 0xff, 0x1, 0xff, 0xff, 0xff, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
Stride: 16,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
},
{
"Clone YCbCr 422",
&image.YCbCr{
Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
Cb: []uint8{0xd4, 0x8e, 0x01, 0xaa, 0x95, 0x40, 0x80, 0x80},
Cr: []uint8{0xeb, 0x36, 0x95, 0xb5, 0x41, 0x8c, 0x80, 0x80},
YStride: 4,
CStride: 2,
SubsampleRatio: image.YCbCrSubsampleRatio422,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
&image.NRGBA{
Pix: []uint8{0xe2, 0x0, 0xe1, 0xff, 0xff, 0x0, 0xfe, 0xff, 0x0, 0x4d, 0x36, 0xff, 0x49, 0xe1, 0xca, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0x0, 0x34, 0x33, 0xff, 0x1, 0x7f, 0x7e, 0xff, 0x5c, 0x58, 0x0, 0xff, 0x82, 0x7e, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
Stride: 16,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
},
{
"Clone YCbCr 420",
&image.YCbCr{
Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
Cb: []uint8{0x01, 0xaa, 0x80, 0x80},
Cr: []uint8{0x95, 0xb5, 0x80, 0x80},
YStride: 4, CStride: 2,
SubsampleRatio: image.YCbCrSubsampleRatio420,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
&image.NRGBA{
Pix: []uint8{0x69, 0x69, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x67, 0x0, 0x67, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
Stride: 16,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
},
{
"Clone Paletted",
&image.Paletted{
Rect: image.Rect(-1, -1, 5, 0),
Stride: 6 * 1,
Palette: color.Palette{
color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xff},
color.NRGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
color.NRGBA{R: 0x7f, G: 0x7f, B: 0x7f, A: 0xff},
color.NRGBA{R: 0x7f, G: 0x00, B: 0x00, A: 0xff},
color.NRGBA{R: 0x00, G: 0x7f, B: 0x00, A: 0xff},
color.NRGBA{R: 0x00, G: 0x00, B: 0x7f, A: 0xff},
},
Pix: []uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 6, 1),
Stride: 6 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff,
0x7f, 0x7f, 0x7f, 0xff,
0x7f, 0x00, 0x00, 0xff,
0x00, 0x7f, 0x00, 0xff,
0x00, 0x00, 0x7f, 0xff,
},
},
},
}
for _, d := range td {
got := Clone(d.src)
want := d.want
delta := 0
if _, ok := d.src.(*image.YCbCr); ok {
delta = 1
}
if !compareNRGBA(got, want, delta) {
t.Errorf("test [%s] failed: %#v", d.desc, got)
}
}
}

266
vendor/github.com/disintegration/imaging/helpers.go сгенерированный поставляемый
Просмотреть файл

@@ -165,269 +165,3 @@ func New(width, height int, fillColor color.Color) *image.NRGBA {
return dst return dst
} }
// Clone returns a copy of the given image.
func Clone(img image.Image) *image.NRGBA {
dstBounds := img.Bounds().Sub(img.Bounds().Min)
dst := image.NewNRGBA(dstBounds)
switch src := img.(type) {
case *image.NRGBA:
copyNRGBA(dst, src)
case *image.NRGBA64:
copyNRGBA64(dst, src)
case *image.RGBA:
copyRGBA(dst, src)
case *image.RGBA64:
copyRGBA64(dst, src)
case *image.Gray:
copyGray(dst, src)
case *image.Gray16:
copyGray16(dst, src)
case *image.YCbCr:
copyYCbCr(dst, src)
case *image.Paletted:
copyPaletted(dst, src)
default:
copyImage(dst, src)
}
return dst
}
func copyNRGBA(dst *image.NRGBA, src *image.NRGBA) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
rowSize := dstW * 4
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
copy(dst.Pix[di:di+rowSize], src.Pix[si:si+rowSize])
}
})
}
func copyNRGBA64(dst *image.NRGBA, src *image.NRGBA64) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
dst.Pix[di+0] = src.Pix[si+0]
dst.Pix[di+1] = src.Pix[si+2]
dst.Pix[di+2] = src.Pix[si+4]
dst.Pix[di+3] = src.Pix[si+6]
di += 4
si += 8
}
}
})
}
func copyRGBA(dst *image.NRGBA, src *image.RGBA) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
a := src.Pix[si+3]
dst.Pix[di+3] = a
switch a {
case 0:
dst.Pix[di+0] = 0
dst.Pix[di+1] = 0
dst.Pix[di+2] = 0
case 0xff:
dst.Pix[di+0] = src.Pix[si+0]
dst.Pix[di+1] = src.Pix[si+1]
dst.Pix[di+2] = src.Pix[si+2]
default:
var tmp uint16
tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a)
dst.Pix[di+0] = uint8(tmp)
tmp = uint16(src.Pix[si+1]) * 0xff / uint16(a)
dst.Pix[di+1] = uint8(tmp)
tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a)
dst.Pix[di+2] = uint8(tmp)
}
di += 4
si += 4
}
}
})
}
func copyRGBA64(dst *image.NRGBA, src *image.RGBA64) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
a := src.Pix[si+6]
dst.Pix[di+3] = a
switch a {
case 0:
dst.Pix[di+0] = 0
dst.Pix[di+1] = 0
dst.Pix[di+2] = 0
case 0xff:
dst.Pix[di+0] = src.Pix[si+0]
dst.Pix[di+1] = src.Pix[si+2]
dst.Pix[di+2] = src.Pix[si+4]
default:
var tmp uint16
tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a)
dst.Pix[di+0] = uint8(tmp)
tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a)
dst.Pix[di+1] = uint8(tmp)
tmp = uint16(src.Pix[si+4]) * 0xff / uint16(a)
dst.Pix[di+2] = uint8(tmp)
}
di += 4
si += 8
}
}
})
}
func copyGray(dst *image.NRGBA, src *image.Gray) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := src.Pix[si]
dst.Pix[di+0] = c
dst.Pix[di+1] = c
dst.Pix[di+2] = c
dst.Pix[di+3] = 0xff
di += 4
si++
}
}
})
}
func copyGray16(dst *image.NRGBA, src *image.Gray16) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := src.Pix[si]
dst.Pix[di+0] = c
dst.Pix[di+1] = c
dst.Pix[di+2] = c
dst.Pix[di+3] = 0xff
di += 4
si += 2
}
}
})
}
func copyYCbCr(dst *image.NRGBA, src *image.YCbCr) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
for dstX := 0; dstX < dstW; dstX++ {
srcX := srcMinX + dstX
srcY := srcMinY + dstY
siy := src.YOffset(srcX, srcY)
sic := src.COffset(srcX, srcY)
r, g, b := color.YCbCrToRGB(src.Y[siy], src.Cb[sic], src.Cr[sic])
dst.Pix[di+0] = r
dst.Pix[di+1] = g
dst.Pix[di+2] = b
dst.Pix[di+3] = 0xff
di += 4
}
}
})
}
func copyPaletted(dst *image.NRGBA, src *image.Paletted) {
srcMinX := src.Rect.Min.X
srcMinY := src.Rect.Min.Y
dstW := dst.Rect.Dx()
dstH := dst.Rect.Dy()
plen := len(src.Palette)
pnew := make([]color.NRGBA, plen)
for i := 0; i < plen; i++ {
pnew[i] = color.NRGBAModel.Convert(src.Palette[i]).(color.NRGBA)
}
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
si := src.PixOffset(srcMinX, srcMinY+dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := pnew[src.Pix[si]]
dst.Pix[di+0] = c.R
dst.Pix[di+1] = c.G
dst.Pix[di+2] = c.B
dst.Pix[di+3] = c.A
di += 4
si++
}
}
})
}
func copyImage(dst *image.NRGBA, src image.Image) {
srcMinX := src.Bounds().Min.X
srcMinY := src.Bounds().Min.Y
dstW := dst.Bounds().Dx()
dstH := dst.Bounds().Dy()
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
di := dst.PixOffset(0, dstY)
for dstX := 0; dstX < dstW; dstX++ {
c := color.NRGBAModel.Convert(src.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA)
dst.Pix[di+0] = c.R
dst.Pix[di+1] = c.G
dst.Pix[di+2] = c.B
dst.Pix[di+3] = c.A
di += 4
}
}
})
}
// toNRGBA converts any image type to *image.NRGBA with min-point at (0, 0).
func toNRGBA(img image.Image) *image.NRGBA {
if img, ok := img.(*image.NRGBA); ok && img.Bounds().Min.Eq(image.ZP) {
return img
}
return Clone(img)
}

240
vendor/github.com/disintegration/imaging/helpers_test.go сгенерированный поставляемый
Просмотреть файл

@@ -140,246 +140,6 @@ func TestNew(t *testing.T) {
} }
} }
func TestClone(t *testing.T) {
td := []struct {
desc string
src image.Image
want *image.NRGBA
}{
{
"Clone NRGBA",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
},
{
"Clone NRGBA64",
&image.NRGBA64{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 8,
Pix: []uint8{
0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff,
},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
},
{
"Clone RGBA",
&image.RGBA{
Rect: image.Rect(-1, -1, 0, 2),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 3),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
},
{
"Clone RGBA64",
&image.RGBA64{
Rect: image.Rect(-1, -1, 0, 2),
Stride: 1 * 8,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff,
},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 3),
Stride: 1 * 4,
Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff},
},
},
{
"Clone Gray",
&image.Gray{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 1,
Pix: []uint8{0x11, 0xee},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff},
},
},
{
"Clone Gray16",
&image.Gray16{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 2,
Pix: []uint8{0x11, 0x11, 0xee, 0xee},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff},
},
},
{
"Clone Alpha",
&image.Alpha{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 1,
Pix: []uint8{0x11, 0xee},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{0xff, 0xff, 0xff, 0x11, 0xff, 0xff, 0xff, 0xee},
},
},
{
"Clone YCbCr",
&image.YCbCr{
Rect: image.Rect(-1, -1, 5, 0),
SubsampleRatio: image.YCbCrSubsampleRatio444,
YStride: 6,
CStride: 6,
Y: []uint8{0x00, 0xff, 0x7f, 0x26, 0x4b, 0x0e},
Cb: []uint8{0x80, 0x80, 0x80, 0x6b, 0x56, 0xc0},
Cr: []uint8{0x80, 0x80, 0x80, 0xc0, 0x4b, 0x76},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 6, 1),
Stride: 6 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff,
0x7f, 0x7f, 0x7f, 0xff,
0x7f, 0x00, 0x00, 0xff,
0x00, 0x7f, 0x00, 0xff,
0x00, 0x00, 0x7f, 0xff,
},
},
},
{
"Clone YCbCr 444",
&image.YCbCr{
Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
Cb: []uint8{0x55, 0xd4, 0xff, 0x8e, 0x2c, 0x01, 0x6b, 0xaa, 0xc0, 0x95, 0x56, 0x40, 0x80, 0x80, 0x80, 0x80},
Cr: []uint8{0xff, 0xeb, 0x6b, 0x36, 0x15, 0x95, 0xc0, 0xb5, 0x76, 0x41, 0x4b, 0x8c, 0x80, 0x80, 0x80, 0x80},
YStride: 4,
CStride: 4,
SubsampleRatio: image.YCbCrSubsampleRatio444,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
&image.NRGBA{
Pix: []uint8{0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x49, 0xe1, 0xca, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, 0x7f, 0x0, 0x0, 0xff, 0x7f, 0x0, 0x7f, 0xff, 0x0, 0x0, 0x7f, 0xff, 0x0, 0x7f, 0x7f, 0xff, 0x0, 0x7f, 0x0, 0xff, 0x82, 0x7f, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
Stride: 16,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
},
{
"Clone YCbCr 440",
&image.YCbCr{
Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
Cb: []uint8{0x2c, 0x01, 0x6b, 0xaa, 0x80, 0x80, 0x80, 0x80},
Cr: []uint8{0x15, 0x95, 0xc0, 0xb5, 0x80, 0x80, 0x80, 0x80},
YStride: 4,
CStride: 4,
SubsampleRatio: image.YCbCrSubsampleRatio440,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
&image.NRGBA{
Pix: []uint8{0x0, 0xb5, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x77, 0x0, 0x0, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0x0, 0xff, 0x1, 0xff, 0xff, 0xff, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
Stride: 16,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
},
{
"Clone YCbCr 422",
&image.YCbCr{
Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
Cb: []uint8{0xd4, 0x8e, 0x01, 0xaa, 0x95, 0x40, 0x80, 0x80},
Cr: []uint8{0xeb, 0x36, 0x95, 0xb5, 0x41, 0x8c, 0x80, 0x80},
YStride: 4,
CStride: 2,
SubsampleRatio: image.YCbCrSubsampleRatio422,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
&image.NRGBA{
Pix: []uint8{0xe2, 0x0, 0xe1, 0xff, 0xff, 0x0, 0xfe, 0xff, 0x0, 0x4d, 0x36, 0xff, 0x49, 0xe1, 0xca, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0x0, 0x34, 0x33, 0xff, 0x1, 0x7f, 0x7e, 0xff, 0x5c, 0x58, 0x0, 0xff, 0x82, 0x7e, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
Stride: 16,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
},
{
"Clone YCbCr 420",
&image.YCbCr{
Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
Cb: []uint8{0x01, 0xaa, 0x80, 0x80},
Cr: []uint8{0x95, 0xb5, 0x80, 0x80},
YStride: 4, CStride: 2,
SubsampleRatio: image.YCbCrSubsampleRatio420,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
&image.NRGBA{
Pix: []uint8{0x69, 0x69, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x67, 0x0, 0x67, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
Stride: 16,
Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
},
},
{
"Clone Paletted",
&image.Paletted{
Rect: image.Rect(-1, -1, 5, 0),
Stride: 6 * 1,
Palette: color.Palette{
color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xff},
color.NRGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
color.NRGBA{R: 0x7f, G: 0x7f, B: 0x7f, A: 0xff},
color.NRGBA{R: 0x7f, G: 0x00, B: 0x00, A: 0xff},
color.NRGBA{R: 0x00, G: 0x7f, B: 0x00, A: 0xff},
color.NRGBA{R: 0x00, G: 0x00, B: 0x7f, A: 0xff},
},
Pix: []uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5},
},
&image.NRGBA{
Rect: image.Rect(0, 0, 6, 1),
Stride: 6 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff,
0x7f, 0x7f, 0x7f, 0xff,
0x7f, 0x00, 0x00, 0xff,
0x00, 0x7f, 0x00, 0xff,
0x00, 0x00, 0x7f, 0xff,
},
},
},
}
for _, d := range td {
got := Clone(d.src)
want := d.want
delta := 0
if _, ok := d.src.(*image.YCbCr); ok {
delta = 1
}
if !compareNRGBA(got, want, delta) {
t.Errorf("test [%s] failed: %#v", d.desc, got)
}
}
}
func TestFormats(t *testing.T) { func TestFormats(t *testing.T) {
formatNames := map[Format]string{ formatNames := map[Format]string{
JPEG: "JPEG", JPEG: "JPEG",

2
vendor/github.com/disintegration/imaging/histogram.go сгенерированный поставляемый
Просмотреть файл

@@ -28,7 +28,7 @@ func Histogram(img image.Image) [256]float64 {
g := src.Pix[i+1] g := src.Pix[i+1]
b := src.Pix[i+2] b := src.Pix[i+2]
var y float32 = 0.299*float32(r) + 0.587*float32(g) + 0.114*float32(b) y := 0.299*float32(r) + 0.587*float32(g) + 0.114*float32(b)
histogram[int(y+0.5)]++ histogram[int(y+0.5)]++
total++ total++

10
vendor/github.com/disintegration/imaging/resize.go сгенерированный поставляемый
Просмотреть файл

@@ -19,6 +19,7 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWei
ru := math.Ceil(scale * filter.Support) ru := math.Ceil(scale * filter.Support)
out := make([][]indexWeight, dstSize) out := make([][]indexWeight, dstSize)
tmp := make([]indexWeight, 0, dstSize*int(ru+2)*2)
for v := 0; v < dstSize; v++ { for v := 0; v < dstSize; v++ {
fu := (float64(v)+0.5)*du - 0.5 fu := (float64(v)+0.5)*du - 0.5
@@ -37,14 +38,17 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWei
w := filter.Kernel((float64(u) - fu) / scale) w := filter.Kernel((float64(u) - fu) / scale)
if w != 0 { if w != 0 {
sum += w sum += w
out[v] = append(out[v], indexWeight{index: u, weight: w}) tmp = append(tmp, indexWeight{index: u, weight: w})
} }
} }
if sum != 0 { if sum != 0 {
for i := range out[v] { for i := range tmp {
out[v][i].weight /= sum tmp[i].weight /= sum
} }
} }
out[v] = tmp
tmp = tmp[len(tmp):]
} }
return out return out

4
vendor/github.com/disintegration/imaging/transform.go сгенерированный поставляемый
Просмотреть файл

@@ -235,7 +235,7 @@ func Rotate(img image.Image, angle float64, bgColor color.Color) *image.NRGBA {
dstYOff := float64(dstH)/2 - 0.5 dstYOff := float64(dstH)/2 - 0.5
bgColorNRGBA := color.NRGBAModel.Convert(bgColor).(color.NRGBA) bgColorNRGBA := color.NRGBAModel.Convert(bgColor).(color.NRGBA)
sin, cos := math.Sincos(math.Pi * float64(angle) / 180) sin, cos := math.Sincos(math.Pi * angle / 180)
parallel(dstH, func(partStart, partEnd int) { parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ { for dstY := partStart; dstY < partEnd; dstY++ {
@@ -259,7 +259,7 @@ func rotatedSize(w, h int, angle float64) (int, int) {
return 0, 0 return 0, 0
} }
sin, cos := math.Sincos(math.Pi * float64(angle) / 180) sin, cos := math.Sincos(math.Pi * angle / 180)
x1, y1 := rotatePoint(float64(w-1), 0, sin, cos) x1, y1 := rotatePoint(float64(w-1), 0, sin, cos)
x2, y2 := rotatePoint(float64(w-1), float64(h-1), sin, cos) x2, y2 := rotatePoint(float64(w-1), float64(h-1), sin, cos)
x3, y3 := rotatePoint(0, float64(h-1), sin, cos) x3, y3 := rotatePoint(0, float64(h-1), sin, cos)

5
vendor/github.com/go-ini/ini/.github/ISSUE_TEMPLATE.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,5 @@
### Please give general description of the problem
### Please provide code snippets to reproduce the problem described above
### Do you have any suggestion to fix the problem?

3
vendor/github.com/go-ini/ini/.github/PULL_REQUEST_TEMPLATE.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,3 @@
### What problem should be fixed?
### Have you added test cases to catch the problem?

1
vendor/github.com/go-ini/ini/.gitignore сгенерированный поставляемый
Просмотреть файл

@@ -3,3 +3,4 @@ ini.sublime-project
ini.sublime-workspace ini.sublime-workspace
testdata/conf_reflect.ini testdata/conf_reflect.ini
.idea .idea
/.vscode

4
vendor/github.com/go-ini/ini/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -5,9 +5,11 @@ go:
- 1.6.x - 1.6.x
- 1.7.x - 1.7.x
- 1.8.x - 1.8.x
- master - 1.9.x
script: script:
- go get golang.org/x/tools/cmd/cover - go get golang.org/x/tools/cmd/cover
- go get github.com/smartystreets/goconvey - go get github.com/smartystreets/goconvey
- mkdir -p $HOME/gopath/src/gopkg.in
- ln -s $HOME/gopath/src/github.com/go-ini/ini $HOME/gopath/src/gopkg.in/ini.v1
- go test -v -cover -race - go test -v -cover -race

2
vendor/github.com/go-ini/ini/LICENSE сгенерированный поставляемый
Просмотреть файл

@@ -176,7 +176,7 @@ 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 the same "printed page" as the copyright notice for easier identification within
third-party archives. third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright 2014 Unknwon
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

5
vendor/github.com/go-ini/ini/Makefile сгенерированный поставляемый
Просмотреть файл

@@ -1,4 +1,4 @@
.PHONY: build test bench vet .PHONY: build test bench vet coverage
build: vet bench build: vet bench
@@ -10,3 +10,6 @@ bench:
vet: vet:
go vet go vet
coverage:
go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out

29
vendor/github.com/go-ini/ini/README.md сгенерированный поставляемый
Просмотреть файл

@@ -101,7 +101,7 @@ skip-name-resolve
By default, this is considered as missing value. But if you know you're going to deal with those cases, you can assign advanced load options: By default, this is considered as missing value. But if you know you're going to deal with those cases, you can assign advanced load options:
```go ```go
cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf")) cfg, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
``` ```
The value of those keys are always `true`, and when you save to a file, it will keep in the same foramt as you read. The value of those keys are always `true`, and when you save to a file, it will keep in the same foramt as you read.
@@ -125,7 +125,7 @@ If you want to save a value with `#` or `;`, please quote them with ``` ` ``` or
Alternatively, you can use following `LoadOptions` to completely ignore inline comments: Alternatively, you can use following `LoadOptions` to completely ignore inline comments:
```go ```go
cfg, err := LoadSources(LoadOptions{IgnoreInlineComment: true}, "app.ini")) cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, "app.ini"))
``` ```
### Working with sections ### Working with sections
@@ -329,6 +329,20 @@ foo = "some value" // foo: some value
bar = 'some value' // bar: some value bar = 'some value' // bar: some value
``` ```
Sometimes you downloaded file from [Crowdin](https://crowdin.com/) has values like the following (value is surrounded by double quotes and quotes in the value are escaped):
```ini
create_repo="created repository <a href=\"%s\">%s</a>"
```
How do you transform this to regular format automatically?
```go
cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
cfg.Section("<name of your section>").Key("create_repo").String()
// You got: created repository <a href="%s">%s</a>
```
That's all? Hmm, no. That's all? Hmm, no.
#### Helper methods of working with values #### Helper methods of working with values
@@ -480,7 +494,7 @@ cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use `LoadOptions.UnparsableSections`: Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use `LoadOptions.UnparsableSections`:
```go ```go
cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS] cfg, err := ini.LoadSources(ini.LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`)) <1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
body := cfg.Section("COMMENTS").Body() body := cfg.Section("COMMENTS").Body()
@@ -573,7 +587,7 @@ Why not?
```go ```go
type Embeded struct { type Embeded struct {
Dates []time.Time `delim:"|"` Dates []time.Time `delim:"|" comment:"Time data"`
Places []string `ini:"places,omitempty"` Places []string `ini:"places,omitempty"`
None []int `ini:",omitempty"` None []int `ini:",omitempty"`
} }
@@ -581,10 +595,10 @@ type Embeded struct {
type Author struct { type Author struct {
Name string `ini:"NAME"` Name string `ini:"NAME"`
Male bool Male bool
Age int Age int `comment:"Author's age"`
GPA float64 GPA float64
NeverMind string `ini:"-"` NeverMind string `ini:"-"`
*Embeded *Embeded `comment:"Embeded section"`
} }
func main() { func main() {
@@ -605,10 +619,13 @@ So, what do I get?
```ini ```ini
NAME = Unknwon NAME = Unknwon
Male = true Male = true
; Author's age
Age = 21 Age = 21
GPA = 2.8 GPA = 2.8
; Embeded section
[Embeded] [Embeded]
; Time data
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00 Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
places = HangZhou,Boston places = HangZhou,Boston
``` ```

29
vendor/github.com/go-ini/ini/README_ZH.md сгенерированный поставляемый
Просмотреть файл

@@ -94,7 +94,7 @@ skip-name-resolve
默认情况下这被认为是缺失值而无法完成解析,但可以通过高级的加载选项对它们进行处理: 默认情况下这被认为是缺失值而无法完成解析,但可以通过高级的加载选项对它们进行处理:
```go ```go
cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf")) cfg, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
``` ```
这些键的值永远为 `true`,且在保存到文件时也只会输出键名。 这些键的值永远为 `true`,且在保存到文件时也只会输出键名。
@@ -118,7 +118,7 @@ key, err := sec.NewBooleanKey("skip-host-cache")
除此之外,您还可以通过 `LoadOptions` 完全忽略行内注释: 除此之外,您还可以通过 `LoadOptions` 完全忽略行内注释:
```go ```go
cfg, err := LoadSources(LoadOptions{IgnoreInlineComment: true}, "app.ini")) cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, "app.ini"))
``` ```
### 操作分区Section ### 操作分区Section
@@ -322,6 +322,20 @@ foo = "some value" // foo: some value
bar = 'some value' // bar: some value bar = 'some value' // bar: some value
``` ```
有时您会获得像从 [Crowdin](https://crowdin.com/) 网站下载的文件那样具有特殊格式的值(值使用双引号括起来,内部的双引号被转义):
```ini
create_repo="创建了仓库 <a href=\"%s\">%s</a>"
```
那么,怎么自动地将这类值进行处理呢?
```go
cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
cfg.Section("<name of your section>").Key("create_repo").String()
// You got: 创建了仓库 <a href="%s">%s</a>
```
这就是全部了?哈哈,当然不是。 这就是全部了?哈哈,当然不是。
#### 操作键值的辅助方法 #### 操作键值的辅助方法
@@ -473,7 +487,7 @@ cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
如果遇到一些比较特殊的分区,它们不包含常见的键值对,而是没有固定格式的纯文本,则可以使用 `LoadOptions.UnparsableSections` 进行处理: 如果遇到一些比较特殊的分区,它们不包含常见的键值对,而是没有固定格式的纯文本,则可以使用 `LoadOptions.UnparsableSections` 进行处理:
```go ```go
cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS] cfg, err := LoadSources(ini.LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`)) <1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
body := cfg.Section("COMMENTS").Body() body := cfg.Section("COMMENTS").Body()
@@ -564,7 +578,7 @@ p := &Person{
```go ```go
type Embeded struct { type Embeded struct {
Dates []time.Time `delim:"|"` Dates []time.Time `delim:"|" comment:"Time data"`
Places []string `ini:"places,omitempty"` Places []string `ini:"places,omitempty"`
None []int `ini:",omitempty"` None []int `ini:",omitempty"`
} }
@@ -572,10 +586,10 @@ type Embeded struct {
type Author struct { type Author struct {
Name string `ini:"NAME"` Name string `ini:"NAME"`
Male bool Male bool
Age int Age int `comment:"Author's age"`
GPA float64 GPA float64
NeverMind string `ini:"-"` NeverMind string `ini:"-"`
*Embeded *Embeded `comment:"Embeded section"`
} }
func main() { func main() {
@@ -596,10 +610,13 @@ func main() {
```ini ```ini
NAME = Unknwon NAME = Unknwon
Male = true Male = true
; Author's age
Age = 21 Age = 21
GPA = 2.8 GPA = 2.8
; Embeded section
[Embeded] [Embeded]
; Time data
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00 Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
places = HangZhou,Boston places = HangZhou,Boston
``` ```

118
vendor/github.com/go-ini/ini/bench_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,118 @@
// Copyright 2017 Unknwon
//
// 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.
package ini_test
import (
"testing"
"gopkg.in/ini.v1"
)
func newTestFile(block bool) *ini.File {
c, _ := ini.Load([]byte(_CONF_DATA))
c.BlockMode = block
return c
}
func Benchmark_Key_Value(b *testing.B) {
c := newTestFile(true)
for i := 0; i < b.N; i++ {
c.Section("").Key("NAME").Value()
}
}
func Benchmark_Key_Value_NonBlock(b *testing.B) {
c := newTestFile(false)
for i := 0; i < b.N; i++ {
c.Section("").Key("NAME").Value()
}
}
func Benchmark_Key_Value_ViaSection(b *testing.B) {
c := newTestFile(true)
sec := c.Section("")
for i := 0; i < b.N; i++ {
sec.Key("NAME").Value()
}
}
func Benchmark_Key_Value_ViaSection_NonBlock(b *testing.B) {
c := newTestFile(false)
sec := c.Section("")
for i := 0; i < b.N; i++ {
sec.Key("NAME").Value()
}
}
func Benchmark_Key_Value_Direct(b *testing.B) {
c := newTestFile(true)
key := c.Section("").Key("NAME")
for i := 0; i < b.N; i++ {
key.Value()
}
}
func Benchmark_Key_Value_Direct_NonBlock(b *testing.B) {
c := newTestFile(false)
key := c.Section("").Key("NAME")
for i := 0; i < b.N; i++ {
key.Value()
}
}
func Benchmark_Key_String(b *testing.B) {
c := newTestFile(true)
for i := 0; i < b.N; i++ {
_ = c.Section("").Key("NAME").String()
}
}
func Benchmark_Key_String_NonBlock(b *testing.B) {
c := newTestFile(false)
for i := 0; i < b.N; i++ {
_ = c.Section("").Key("NAME").String()
}
}
func Benchmark_Key_String_ViaSection(b *testing.B) {
c := newTestFile(true)
sec := c.Section("")
for i := 0; i < b.N; i++ {
_ = sec.Key("NAME").String()
}
}
func Benchmark_Key_String_ViaSection_NonBlock(b *testing.B) {
c := newTestFile(false)
sec := c.Section("")
for i := 0; i < b.N; i++ {
_ = sec.Key("NAME").String()
}
}
func Benchmark_Key_SetValue(b *testing.B) {
c := newTestFile(true)
for i := 0; i < b.N; i++ {
c.Section("").Key("NAME").SetValue("10")
}
}
func Benchmark_Key_SetValue_VisSection(b *testing.B) {
c := newTestFile(true)
sec := c.Section("")
for i := 0; i < b.N; i++ {
sec.Key("NAME").SetValue("10")
}
}

392
vendor/github.com/go-ini/ini/file.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,392 @@
// Copyright 2017 Unknwon
//
// 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.
package ini
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"strings"
"sync"
)
// File represents a combination of a or more INI file(s) in memory.
type File struct {
options LoadOptions
dataSources []dataSource
// Should make things safe, but sometimes doesn't matter.
BlockMode bool
lock sync.RWMutex
// To keep data in order.
sectionList []string
// Actual data is stored here.
sections map[string]*Section
NameMapper
ValueMapper
}
// newFile initializes File object with given data sources.
func newFile(dataSources []dataSource, opts LoadOptions) *File {
return &File{
BlockMode: true,
dataSources: dataSources,
sections: make(map[string]*Section),
sectionList: make([]string, 0, 10),
options: opts,
}
}
// Empty returns an empty file object.
func Empty() *File {
// Ignore error here, we sure our data is good.
f, _ := Load([]byte(""))
return f
}
// NewSection creates a new section.
func (f *File) NewSection(name string) (*Section, error) {
if len(name) == 0 {
return nil, errors.New("error creating new section: empty section name")
} else if f.options.Insensitive && name != DEFAULT_SECTION {
name = strings.ToLower(name)
}
if f.BlockMode {
f.lock.Lock()
defer f.lock.Unlock()
}
if inSlice(name, f.sectionList) {
return f.sections[name], nil
}
f.sectionList = append(f.sectionList, name)
f.sections[name] = newSection(f, name)
return f.sections[name], nil
}
// NewRawSection creates a new section with an unparseable body.
func (f *File) NewRawSection(name, body string) (*Section, error) {
section, err := f.NewSection(name)
if err != nil {
return nil, err
}
section.isRawSection = true
section.rawBody = body
return section, nil
}
// NewSections creates a list of sections.
func (f *File) NewSections(names ...string) (err error) {
for _, name := range names {
if _, err = f.NewSection(name); err != nil {
return err
}
}
return nil
}
// GetSection returns section by given name.
func (f *File) GetSection(name string) (*Section, error) {
if len(name) == 0 {
name = DEFAULT_SECTION
}
if f.options.Insensitive {
name = strings.ToLower(name)
}
if f.BlockMode {
f.lock.RLock()
defer f.lock.RUnlock()
}
sec := f.sections[name]
if sec == nil {
return nil, fmt.Errorf("section '%s' does not exist", name)
}
return sec, nil
}
// Section assumes named section exists and returns a zero-value when not.
func (f *File) Section(name string) *Section {
sec, err := f.GetSection(name)
if err != nil {
// Note: It's OK here because the only possible error is empty section name,
// but if it's empty, this piece of code won't be executed.
sec, _ = f.NewSection(name)
return sec
}
return sec
}
// Section returns list of Section.
func (f *File) Sections() []*Section {
sections := make([]*Section, len(f.sectionList))
for i := range f.sectionList {
sections[i] = f.Section(f.sectionList[i])
}
return sections
}
// ChildSections returns a list of child sections of given section name.
func (f *File) ChildSections(name string) []*Section {
return f.Section(name).ChildSections()
}
// SectionStrings returns list of section names.
func (f *File) SectionStrings() []string {
list := make([]string, len(f.sectionList))
copy(list, f.sectionList)
return list
}
// DeleteSection deletes a section.
func (f *File) DeleteSection(name string) {
if f.BlockMode {
f.lock.Lock()
defer f.lock.Unlock()
}
if len(name) == 0 {
name = DEFAULT_SECTION
}
for i, s := range f.sectionList {
if s == name {
f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...)
delete(f.sections, name)
return
}
}
}
func (f *File) reload(s dataSource) error {
r, err := s.ReadCloser()
if err != nil {
return err
}
defer r.Close()
return f.parse(r)
}
// Reload reloads and parses all data sources.
func (f *File) Reload() (err error) {
for _, s := range f.dataSources {
if err = f.reload(s); err != nil {
// In loose mode, we create an empty default section for nonexistent files.
if os.IsNotExist(err) && f.options.Loose {
f.parse(bytes.NewBuffer(nil))
continue
}
return err
}
}
return nil
}
// Append appends one or more data sources and reloads automatically.
func (f *File) Append(source interface{}, others ...interface{}) error {
ds, err := parseDataSource(source)
if err != nil {
return err
}
f.dataSources = append(f.dataSources, ds)
for _, s := range others {
ds, err = parseDataSource(s)
if err != nil {
return err
}
f.dataSources = append(f.dataSources, ds)
}
return f.Reload()
}
func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
equalSign := "="
if PrettyFormat {
equalSign = " = "
}
// Use buffer to make sure target is safe until finish encoding.
buf := bytes.NewBuffer(nil)
for i, sname := range f.sectionList {
sec := f.Section(sname)
if len(sec.Comment) > 0 {
if sec.Comment[0] != '#' && sec.Comment[0] != ';' {
sec.Comment = "; " + sec.Comment
} else {
sec.Comment = sec.Comment[:1] + " " + strings.TrimSpace(sec.Comment[1:])
}
if _, err := buf.WriteString(sec.Comment + LineBreak); err != nil {
return nil, err
}
}
if i > 0 || DefaultHeader {
if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
return nil, err
}
} else {
// Write nothing if default section is empty
if len(sec.keyList) == 0 {
continue
}
}
if sec.isRawSection {
if _, err := buf.WriteString(sec.rawBody); err != nil {
return nil, err
}
if PrettySection {
// Put a line between sections
if _, err := buf.WriteString(LineBreak); err != nil {
return nil, err
}
}
continue
}
// Count and generate alignment length and buffer spaces using the
// longest key. Keys may be modifed if they contain certain characters so
// we need to take that into account in our calculation.
alignLength := 0
if PrettyFormat {
for _, kname := range sec.keyList {
keyLength := len(kname)
// First case will surround key by ` and second by """
if strings.ContainsAny(kname, "\"=:") {
keyLength += 2
} else if strings.Contains(kname, "`") {
keyLength += 6
}
if keyLength > alignLength {
alignLength = keyLength
}
}
}
alignSpaces := bytes.Repeat([]byte(" "), alignLength)
KEY_LIST:
for _, kname := range sec.keyList {
key := sec.Key(kname)
if len(key.Comment) > 0 {
if len(indent) > 0 && sname != DEFAULT_SECTION {
buf.WriteString(indent)
}
if key.Comment[0] != '#' && key.Comment[0] != ';' {
key.Comment = "; " + key.Comment
} else {
key.Comment = key.Comment[:1] + " " + strings.TrimSpace(key.Comment[1:])
}
if _, err := buf.WriteString(key.Comment + LineBreak); err != nil {
return nil, err
}
}
if len(indent) > 0 && sname != DEFAULT_SECTION {
buf.WriteString(indent)
}
switch {
case key.isAutoIncrement:
kname = "-"
case strings.ContainsAny(kname, "\"=:"):
kname = "`" + kname + "`"
case strings.Contains(kname, "`"):
kname = `"""` + kname + `"""`
}
for _, val := range key.ValueWithShadows() {
if _, err := buf.WriteString(kname); err != nil {
return nil, err
}
if key.isBooleanType {
if kname != sec.keyList[len(sec.keyList)-1] {
buf.WriteString(LineBreak)
}
continue KEY_LIST
}
// Write out alignment spaces before "=" sign
if PrettyFormat {
buf.Write(alignSpaces[:alignLength-len(kname)])
}
// In case key value contains "\n", "`", "\"", "#" or ";"
if strings.ContainsAny(val, "\n`") {
val = `"""` + val + `"""`
} else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") {
val = "`" + val + "`"
}
if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil {
return nil, err
}
}
}
if PrettySection {
// Put a line between sections
if _, err := buf.WriteString(LineBreak); err != nil {
return nil, err
}
}
}
return buf, nil
}
// WriteToIndent writes content into io.Writer with given indention.
// If PrettyFormat has been set to be true,
// it will align "=" sign with spaces under each section.
func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) {
buf, err := f.writeToBuffer(indent)
if err != nil {
return 0, err
}
return buf.WriteTo(w)
}
// WriteTo writes file content into io.Writer.
func (f *File) WriteTo(w io.Writer) (int64, error) {
return f.WriteToIndent(w, "")
}
// SaveToIndent writes content to file system with given value indention.
func (f *File) SaveToIndent(filename, indent string) error {
// Note: Because we are truncating with os.Create,
// so it's safer to save to a temporary file location and rename afte done.
buf, err := f.writeToBuffer(indent)
if err != nil {
return err
}
return ioutil.WriteFile(filename, buf.Bytes(), 0666)
}
// SaveTo writes content to file system.
func (f *File) SaveTo(filename string) error {
return f.SaveToIndent(filename, "")
}

355
vendor/github.com/go-ini/ini/file_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,355 @@
// Copyright 2017 Unknwon
//
// 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.
package ini_test
import (
"bytes"
"testing"
. "github.com/smartystreets/goconvey/convey"
"gopkg.in/ini.v1"
)
func TestEmpty(t *testing.T) {
Convey("Create an empty object", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
// Should only have the default section
So(len(f.Sections()), ShouldEqual, 1)
// Default section should not contain any key
So(len(f.Section("").Keys()), ShouldBeZeroValue)
})
}
func TestFile_NewSection(t *testing.T) {
Convey("Create a new section", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
sec, err := f.NewSection("author")
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(sec.Name(), ShouldEqual, "author")
So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "author"})
Convey("With duplicated name", func() {
sec, err := f.NewSection("author")
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
// Does nothing if section already exists
So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "author"})
})
Convey("With empty string", func() {
_, err := f.NewSection("")
So(err, ShouldNotBeNil)
})
})
}
func TestFile_NewRawSection(t *testing.T) {
Convey("Create a new raw section", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000`)
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(sec.Name(), ShouldEqual, "comments")
So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "comments"})
So(f.Section("comments").Body(), ShouldEqual, `1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000`)
Convey("With duplicated name", func() {
sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000`)
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "comments"})
// Overwrite previous existed section
So(f.Section("comments").Body(), ShouldEqual, `1111111111111111111000000000000000001110000`)
})
Convey("With empty string", func() {
_, err := f.NewRawSection("", "")
So(err, ShouldNotBeNil)
})
})
}
func TestFile_NewSections(t *testing.T) {
Convey("Create new sections", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
So(f.NewSections("package", "author"), ShouldBeNil)
So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "package", "author"})
Convey("With duplicated name", func() {
So(f.NewSections("author", "features"), ShouldBeNil)
// Ignore section already exists
So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "package", "author", "features"})
})
Convey("With empty string", func() {
So(f.NewSections("", ""), ShouldNotBeNil)
})
})
}
func TestFile_GetSection(t *testing.T) {
Convey("Get a section", t, func() {
f, err := ini.Load(_FULL_CONF)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
sec, err := f.GetSection("author")
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(sec.Name(), ShouldEqual, "author")
Convey("Section not exists", func() {
_, err := f.GetSection("404")
So(err, ShouldNotBeNil)
})
})
}
func TestFile_Section(t *testing.T) {
Convey("Get a section", t, func() {
f, err := ini.Load(_FULL_CONF)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
sec := f.Section("author")
So(sec, ShouldNotBeNil)
So(sec.Name(), ShouldEqual, "author")
Convey("Section not exists", func() {
sec := f.Section("404")
So(sec, ShouldNotBeNil)
So(sec.Name(), ShouldEqual, "404")
})
})
Convey("Get default section in lower case with insensitive load", t, func() {
f, err := ini.InsensitiveLoad([]byte(`
[default]
NAME = ini
VERSION = v1`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").Key("name").String(), ShouldEqual, "ini")
So(f.Section("").Key("version").String(), ShouldEqual, "v1")
})
}
func TestFile_Sections(t *testing.T) {
Convey("Get all sections", t, func() {
f, err := ini.Load(_FULL_CONF)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
secs := f.Sections()
names := []string{ini.DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"}
So(len(secs), ShouldEqual, len(names))
for i, name := range names {
So(secs[i].Name(), ShouldEqual, name)
}
})
}
func TestFile_ChildSections(t *testing.T) {
Convey("Get child sections by parent name", t, func() {
f, err := ini.Load([]byte(`
[node]
[node.biz1]
[node.biz2]
[node.biz3]
[node.bizN]
`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
children := f.ChildSections("node")
names := []string{"node.biz1", "node.biz2", "node.biz3", "node.bizN"}
So(len(children), ShouldEqual, len(names))
for i, name := range names {
So(children[i].Name(), ShouldEqual, name)
}
})
}
func TestFile_SectionStrings(t *testing.T) {
Convey("Get all section names", t, func() {
f, err := ini.Load(_FULL_CONF)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"})
})
}
func TestFile_DeleteSection(t *testing.T) {
Convey("Delete a section", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
f.NewSections("author", "package", "features")
f.DeleteSection("features")
f.DeleteSection("")
So(f.SectionStrings(), ShouldResemble, []string{"author", "package"})
})
}
func TestFile_Append(t *testing.T) {
Convey("Append a data source", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
So(f.Append(_MINIMAL_CONF, []byte(`
[author]
NAME = Unknwon`)), ShouldBeNil)
Convey("With bad input", func() {
So(f.Append(123), ShouldNotBeNil)
So(f.Append(_MINIMAL_CONF, 123), ShouldNotBeNil)
})
})
}
func TestFile_WriteTo(t *testing.T) {
Convey("Write content to somewhere", t, func() {
f, err := ini.Load(_FULL_CONF)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
f.Section("author").Comment = `Information about package author
# Bio can be written in multiple lines.`
f.Section("author").Key("NAME").Comment = "This is author name"
f.Section("note").NewBooleanKey("boolean_key")
f.Section("note").NewKey("more", "notes")
var buf bytes.Buffer
_, err = f.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `; Package name
NAME = ini
; Package version
VERSION = v1
; Package import path
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
; Information about package author
# Bio can be written in multiple lines.
[author]
; This is author name
NAME = Unknwon
E-MAIL = u@gogs.io
GITHUB = https://github.com/%(NAME)s
# Succeeding comment
BIO = """Gopher.
Coding addict.
Good man.
"""
[package]
CLONE_URL = https://%(IMPORT_PATH)s
[package.sub]
UNUSED_KEY = should be deleted
[features]
- = Support read/write comments of keys and sections
- = Support auto-increment of key names
- = Support load multiple files to overwrite key values
[types]
STRING = str
BOOL = true
BOOL_FALSE = false
FLOAT64 = 1.25
INT = 10
TIME = 2015-01-01T20:17:05Z
DURATION = 2h45m
UINT = 3
[array]
STRINGS = en, zh, de
FLOAT64S = 1.1, 2.2, 3.3
INTS = 1, 2, 3
UINTS = 1, 2, 3
TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
[note]
empty_lines = next line is empty
boolean_key
more = notes
; Comment before the section
; This is a comment for the section too
[comments]
; Comment before key
key = value
; This is a comment for key2
key2 = value2
key3 = "one", "two", "three"
[string escapes]
key1 = value1, value2, value3
key2 = value1\, value2
key3 = val\ue1, value2
key4 = value1\\, value\\\\2
key5 = value1\,, value2
key6 = aaa bbb\ and\ space ccc
[advance]
value with quotes = some value
value quote2 again = some value
includes comment sign = `+"`"+"my#password"+"`"+`
includes comment sign2 = `+"`"+"my;password"+"`"+`
true = 2+3=5
`+"`"+`1+1=2`+"`"+` = true
`+"`"+`6+1=7`+"`"+` = true
"""`+"`"+`5+5`+"`"+`""" = 10
`+"`"+`"6+6"`+"`"+` = 12
`+"`"+`7-2=4`+"`"+` = false
ADDRESS = """404 road,
NotFound, State, 50000"""
two_lines = how about continuation lines?
lots_of_lines = 1 2 3 4
`)
})
}
func TestFile_SaveTo(t *testing.T) {
Convey("Write content to somewhere", t, func() {
f, err := ini.Load(_FULL_CONF)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.SaveTo("testdata/conf_out.ini"), ShouldBeNil)
So(f.SaveToIndent("testdata/conf_out.ini", "\t"), ShouldBeNil)
})
}

376
vendor/github.com/go-ini/ini/ini.go сгенерированный поставляемый
Просмотреть файл

@@ -17,15 +17,12 @@ package ini
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"regexp" "regexp"
"runtime" "runtime"
"strings"
"sync"
) )
const ( const (
@@ -35,7 +32,7 @@ const (
// Maximum allowed depth when recursively substituing variable names. // Maximum allowed depth when recursively substituing variable names.
_DEPTH_VALUES = 99 _DEPTH_VALUES = 99
_VERSION = "1.28.2" _VERSION = "1.30.3"
) )
// Version returns current package version literal. // Version returns current package version literal.
@@ -92,18 +89,6 @@ func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) {
return os.Open(s.name) return os.Open(s.name)
} }
type bytesReadCloser struct {
reader io.Reader
}
func (rc *bytesReadCloser) Read(p []byte) (n int, err error) {
return rc.reader.Read(p)
}
func (rc *bytesReadCloser) Close() error {
return nil
}
// sourceData represents an object that contains content in memory. // sourceData represents an object that contains content in memory.
type sourceData struct { type sourceData struct {
data []byte data []byte
@@ -122,38 +107,6 @@ func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) {
return s.reader, nil return s.reader, nil
} }
// File represents a combination of a or more INI file(s) in memory.
type File struct {
// Should make things safe, but sometimes doesn't matter.
BlockMode bool
// Make sure data is safe in multiple goroutines.
lock sync.RWMutex
// Allow combination of multiple data sources.
dataSources []dataSource
// Actual data is stored here.
sections map[string]*Section
// To keep data in order.
sectionList []string
options LoadOptions
NameMapper
ValueMapper
}
// newFile initializes File object with given data sources.
func newFile(dataSources []dataSource, opts LoadOptions) *File {
return &File{
BlockMode: true,
dataSources: dataSources,
sections: make(map[string]*Section),
sectionList: make([]string, 0, 10),
options: opts,
}
}
func parseDataSource(source interface{}) (dataSource, error) { func parseDataSource(source interface{}) (dataSource, error) {
switch s := source.(type) { switch s := source.(type) {
case string: case string:
@@ -181,6 +134,8 @@ type LoadOptions struct {
AllowBooleanKeys bool AllowBooleanKeys bool
// AllowShadows indicates whether to keep track of keys with same name under same section. // AllowShadows indicates whether to keep track of keys with same name under same section.
AllowShadows bool AllowShadows bool
// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
UnescapeValueDoubleQuotes bool
// Some INI formats allow group blocks that store a block of raw content that doesn't otherwise // Some INI formats allow group blocks that store a block of raw content that doesn't otherwise
// conform to key/value pairs. Specify the names of those blocks here. // conform to key/value pairs. Specify the names of those blocks here.
UnparseableSections []string UnparseableSections []string
@@ -229,328 +184,3 @@ func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) {
func ShadowLoad(source interface{}, others ...interface{}) (*File, error) { func ShadowLoad(source interface{}, others ...interface{}) (*File, error) {
return LoadSources(LoadOptions{AllowShadows: true}, source, others...) return LoadSources(LoadOptions{AllowShadows: true}, source, others...)
} }
// Empty returns an empty file object.
func Empty() *File {
// Ignore error here, we sure our data is good.
f, _ := Load([]byte(""))
return f
}
// NewSection creates a new section.
func (f *File) NewSection(name string) (*Section, error) {
if len(name) == 0 {
return nil, errors.New("error creating new section: empty section name")
} else if f.options.Insensitive && name != DEFAULT_SECTION {
name = strings.ToLower(name)
}
if f.BlockMode {
f.lock.Lock()
defer f.lock.Unlock()
}
if inSlice(name, f.sectionList) {
return f.sections[name], nil
}
f.sectionList = append(f.sectionList, name)
f.sections[name] = newSection(f, name)
return f.sections[name], nil
}
// NewRawSection creates a new section with an unparseable body.
func (f *File) NewRawSection(name, body string) (*Section, error) {
section, err := f.NewSection(name)
if err != nil {
return nil, err
}
section.isRawSection = true
section.rawBody = body
return section, nil
}
// NewSections creates a list of sections.
func (f *File) NewSections(names ...string) (err error) {
for _, name := range names {
if _, err = f.NewSection(name); err != nil {
return err
}
}
return nil
}
// GetSection returns section by given name.
func (f *File) GetSection(name string) (*Section, error) {
if len(name) == 0 {
name = DEFAULT_SECTION
} else if f.options.Insensitive {
name = strings.ToLower(name)
}
if f.BlockMode {
f.lock.RLock()
defer f.lock.RUnlock()
}
sec := f.sections[name]
if sec == nil {
return nil, fmt.Errorf("section '%s' does not exist", name)
}
return sec, nil
}
// Section assumes named section exists and returns a zero-value when not.
func (f *File) Section(name string) *Section {
sec, err := f.GetSection(name)
if err != nil {
// Note: It's OK here because the only possible error is empty section name,
// but if it's empty, this piece of code won't be executed.
sec, _ = f.NewSection(name)
return sec
}
return sec
}
// Section returns list of Section.
func (f *File) Sections() []*Section {
sections := make([]*Section, len(f.sectionList))
for i := range f.sectionList {
sections[i] = f.Section(f.sectionList[i])
}
return sections
}
// ChildSections returns a list of child sections of given section name.
func (f *File) ChildSections(name string) []*Section {
return f.Section(name).ChildSections()
}
// SectionStrings returns list of section names.
func (f *File) SectionStrings() []string {
list := make([]string, len(f.sectionList))
copy(list, f.sectionList)
return list
}
// DeleteSection deletes a section.
func (f *File) DeleteSection(name string) {
if f.BlockMode {
f.lock.Lock()
defer f.lock.Unlock()
}
if len(name) == 0 {
name = DEFAULT_SECTION
}
for i, s := range f.sectionList {
if s == name {
f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...)
delete(f.sections, name)
return
}
}
}
func (f *File) reload(s dataSource) error {
r, err := s.ReadCloser()
if err != nil {
return err
}
defer r.Close()
return f.parse(r)
}
// Reload reloads and parses all data sources.
func (f *File) Reload() (err error) {
for _, s := range f.dataSources {
if err = f.reload(s); err != nil {
// In loose mode, we create an empty default section for nonexistent files.
if os.IsNotExist(err) && f.options.Loose {
f.parse(bytes.NewBuffer(nil))
continue
}
return err
}
}
return nil
}
// Append appends one or more data sources and reloads automatically.
func (f *File) Append(source interface{}, others ...interface{}) error {
ds, err := parseDataSource(source)
if err != nil {
return err
}
f.dataSources = append(f.dataSources, ds)
for _, s := range others {
ds, err = parseDataSource(s)
if err != nil {
return err
}
f.dataSources = append(f.dataSources, ds)
}
return f.Reload()
}
func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
equalSign := "="
if PrettyFormat {
equalSign = " = "
}
// Use buffer to make sure target is safe until finish encoding.
buf := bytes.NewBuffer(nil)
for i, sname := range f.sectionList {
sec := f.Section(sname)
if len(sec.Comment) > 0 {
if sec.Comment[0] != '#' && sec.Comment[0] != ';' {
sec.Comment = "; " + sec.Comment
}
if _, err := buf.WriteString(sec.Comment + LineBreak); err != nil {
return nil, err
}
}
if i > 0 || DefaultHeader {
if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
return nil, err
}
} else {
// Write nothing if default section is empty
if len(sec.keyList) == 0 {
continue
}
}
if sec.isRawSection {
if _, err := buf.WriteString(sec.rawBody); err != nil {
return nil, err
}
continue
}
// Count and generate alignment length and buffer spaces using the
// longest key. Keys may be modifed if they contain certain characters so
// we need to take that into account in our calculation.
alignLength := 0
if PrettyFormat {
for _, kname := range sec.keyList {
keyLength := len(kname)
// First case will surround key by ` and second by """
if strings.ContainsAny(kname, "\"=:") {
keyLength += 2
} else if strings.Contains(kname, "`") {
keyLength += 6
}
if keyLength > alignLength {
alignLength = keyLength
}
}
}
alignSpaces := bytes.Repeat([]byte(" "), alignLength)
KEY_LIST:
for _, kname := range sec.keyList {
key := sec.Key(kname)
if len(key.Comment) > 0 {
if len(indent) > 0 && sname != DEFAULT_SECTION {
buf.WriteString(indent)
}
if key.Comment[0] != '#' && key.Comment[0] != ';' {
key.Comment = "; " + key.Comment
}
if _, err := buf.WriteString(key.Comment + LineBreak); err != nil {
return nil, err
}
}
if len(indent) > 0 && sname != DEFAULT_SECTION {
buf.WriteString(indent)
}
switch {
case key.isAutoIncrement:
kname = "-"
case strings.ContainsAny(kname, "\"=:"):
kname = "`" + kname + "`"
case strings.Contains(kname, "`"):
kname = `"""` + kname + `"""`
}
for _, val := range key.ValueWithShadows() {
if _, err := buf.WriteString(kname); err != nil {
return nil, err
}
if key.isBooleanType {
if kname != sec.keyList[len(sec.keyList)-1] {
buf.WriteString(LineBreak)
}
continue KEY_LIST
}
// Write out alignment spaces before "=" sign
if PrettyFormat {
buf.Write(alignSpaces[:alignLength-len(kname)])
}
// In case key value contains "\n", "`", "\"", "#" or ";"
if strings.ContainsAny(val, "\n`") {
val = `"""` + val + `"""`
} else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") {
val = "`" + val + "`"
}
if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil {
return nil, err
}
}
}
if PrettySection {
// Put a line between sections
if _, err := buf.WriteString(LineBreak); err != nil {
return nil, err
}
}
}
return buf, nil
}
// WriteToIndent writes content into io.Writer with given indention.
// If PrettyFormat has been set to be true,
// it will align "=" sign with spaces under each section.
func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) {
buf, err := f.writeToBuffer(indent)
if err != nil {
return 0, err
}
return buf.WriteTo(w)
}
// WriteTo writes file content into io.Writer.
func (f *File) WriteTo(w io.Writer) (int64, error) {
return f.WriteToIndent(w, "")
}
// SaveToIndent writes content to file system with given value indention.
func (f *File) SaveToIndent(filename, indent string) error {
// Note: Because we are truncating with os.Create,
// so it's safer to save to a temporary file location and rename afte done.
buf, err := f.writeToBuffer(indent)
if err != nil {
return err
}
return ioutil.WriteFile(filename, buf.Bytes(), 0666)
}
// SaveTo writes content to file system.
func (f *File) SaveTo(filename string) error {
return f.SaveToIndent(filename, "")
}

35
vendor/github.com/go-ini/ini/ini_internal_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,35 @@
// Copyright 2017 Unknwon
//
// 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.
package ini
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func Test_Version(t *testing.T) {
Convey("Get version", t, func() {
So(Version(), ShouldEqual, _VERSION)
})
}
func Test_isSlice(t *testing.T) {
Convey("Check if a string is in the slice", t, func() {
ss := []string{"a", "b", "c"}
So(inSlice("a", ss), ShouldBeTrue)
So(inSlice("d", ss), ShouldBeFalse)
})
}

730
vendor/github.com/go-ini/ini/ini_test.go сгенерированный поставляемый
Просмотреть файл

@@ -12,480 +12,312 @@
// License for the specific language governing permissions and limitations // License for the specific language governing permissions and limitations
// under the License. // under the License.
package ini package ini_test
import ( import (
"bytes" "bytes"
"io/ioutil" "io/ioutil"
"strings"
"testing" "testing"
"time"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/ini.v1"
) )
func Test_Version(t *testing.T) { const (
Convey("Get version", t, func() { _CONF_DATA = `
So(Version(), ShouldEqual, _VERSION) ; Package name
}) NAME = ini
} ; Package version
VERSION = v1
const _CONF_DATA = ` ; Package import path
; Package name IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
NAME = ini
; Package version # Information about package author
VERSION = v1 # Bio can be written in multiple lines.
; Package import path [author]
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s NAME = Unknwon ; Succeeding comment
E-MAIL = fake@localhost
# Information about package author
# Bio can be written in multiple lines.
[author]
NAME = Unknwon ; Succeeding comment
E-MAIL = fake@localhost
GITHUB = https://github.com/%(NAME)s
BIO = """Gopher.
Coding addict.
Good man.
""" # Succeeding comment
[package]
CLONE_URL = https://%(IMPORT_PATH)s
[package.sub]
UNUSED_KEY = should be deleted
[features]
-: Support read/write comments of keys and sections
-: Support auto-increment of key names
-: Support load multiple files to overwrite key values
[types]
STRING = str
BOOL = true
BOOL_FALSE = false
FLOAT64 = 1.25
INT = 10
TIME = 2015-01-01T20:17:05Z
DURATION = 2h45m
UINT = 3
[array]
STRINGS = en, zh, de
FLOAT64S = 1.1, 2.2, 3.3
INTS = 1, 2, 3
UINTS = 1, 2, 3
TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
[note]
empty_lines = next line is empty\
; Comment before the section
[comments] ; This is a comment for the section too
; Comment before key
key = "value"
key2 = "value2" ; This is a comment for key2
key3 = "one", "two", "three"
[advance]
value with quotes = "some value"
value quote2 again = 'some value'
includes comment sign = ` + "`" + "my#password" + "`" + `
includes comment sign2 = ` + "`" + "my;password" + "`" + `
true = 2+3=5
"1+1=2" = true
"""6+1=7""" = true
"""` + "`" + `5+5` + "`" + `""" = 10
` + "`" + `"6+6"` + "`" + ` = 12
` + "`" + `7-2=4` + "`" + ` = false
ADDRESS = ` + "`" + `404 road,
NotFound, State, 50000` + "`" + `
two_lines = how about \
continuation lines?
lots_of_lines = 1 \
2 \
3 \
4 \
`
func Test_Load(t *testing.T) {
Convey("Load from data sources", t, func() {
Convey("Load with empty data", func() {
So(Empty(), ShouldNotBeNil)
})
Convey("Load with multiple data sources", func() {
cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini", ioutil.NopCloser(bytes.NewReader([]byte(_CONF_DATA))))
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
f, err := Load([]byte(_CONF_DATA), "testdata/404.ini")
So(err, ShouldNotBeNil)
So(f, ShouldBeNil)
})
Convey("Load with io.ReadCloser", func() {
cfg, err := Load(ioutil.NopCloser(bytes.NewReader([]byte(_CONF_DATA))))
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
So(cfg.Section("").Key("NAME").String(), ShouldEqual, "ini")
})
})
Convey("Bad load process", t, func() {
Convey("Load from invalid data sources", func() {
_, err := Load(_CONF_DATA)
So(err, ShouldNotBeNil)
f, err := Load("testdata/404.ini")
So(err, ShouldNotBeNil)
So(f, ShouldBeNil)
_, err = Load(1)
So(err, ShouldNotBeNil)
_, err = Load([]byte(""), 1)
So(err, ShouldNotBeNil)
})
Convey("Load with bad section name", func() {
_, err := Load([]byte("[]"))
So(err, ShouldNotBeNil)
_, err = Load([]byte("["))
So(err, ShouldNotBeNil)
})
Convey("Load with bad keys", func() {
_, err := Load([]byte(`"""name`))
So(err, ShouldNotBeNil)
_, err = Load([]byte(`"""name"""`))
So(err, ShouldNotBeNil)
_, err = Load([]byte(`""=1`))
So(err, ShouldNotBeNil)
_, err = Load([]byte(`=`))
So(err, ShouldNotBeNil)
_, err = Load([]byte(`name`))
So(err, ShouldNotBeNil)
})
Convey("Load with bad values", func() {
_, err := Load([]byte(`name="""Unknwon`))
So(err, ShouldNotBeNil)
})
})
Convey("Get section and key insensitively", t, func() {
cfg, err := InsensitiveLoad([]byte(_CONF_DATA), "testdata/conf.ini")
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
sec, err := cfg.GetSection("Author")
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
key, err := sec.GetKey("E-mail")
So(err, ShouldBeNil)
So(key, ShouldNotBeNil)
})
Convey("Load with ignoring continuation lines", t, func() {
cfg, err := LoadSources(LoadOptions{IgnoreContinuation: true}, []byte(`key1=a\b\
key2=c\d\`))
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
So(cfg.Section("").Key("key1").String(), ShouldEqual, `a\b\`)
So(cfg.Section("").Key("key2").String(), ShouldEqual, `c\d\`)
})
Convey("Load with ignoring inline comments", t, func() {
cfg, err := LoadSources(LoadOptions{IgnoreInlineComment: true}, []byte(`key1=value ;comment
key2=value #comment2`))
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
So(cfg.Section("").Key("key1").String(), ShouldEqual, `value ;comment`)
So(cfg.Section("").Key("key2").String(), ShouldEqual, `value #comment2`)
var buf bytes.Buffer
cfg.WriteTo(&buf)
So(buf.String(), ShouldEqual, `key1 = value ;comment
key2 = value #comment2
`)
})
Convey("Load with boolean type keys", t, func() {
cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, []byte(`key1=hello
key2
#key3
key4
key5`))
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
So(strings.Join(cfg.Section("").KeyStrings(), ","), ShouldEqual, "key1,key2,key4,key5")
So(cfg.Section("").Key("key2").MustBool(false), ShouldBeTrue)
var buf bytes.Buffer
cfg.WriteTo(&buf)
// there is always a trailing \n at the end of the section
So(buf.String(), ShouldEqual, `key1 = hello
key2
#key3
key4
key5
`)
})
}
func Test_File_ChildSections(t *testing.T) {
Convey("Find child sections by parent name", t, func() {
cfg, err := Load([]byte(`
[node]
[node.biz1]
[node.biz2]
[node.biz3]
[node.bizN]
`))
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
children := cfg.ChildSections("node")
names := make([]string, len(children))
for i := range children {
names[i] = children[i].name
}
So(strings.Join(names, ","), ShouldEqual, "node.biz1,node.biz2,node.biz3,node.bizN")
})
}
func Test_LooseLoad(t *testing.T) {
Convey("Loose load from data sources", t, func() {
Convey("Loose load mixed with nonexistent file", func() {
cfg, err := LooseLoad("testdata/404.ini")
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
var fake struct {
Name string `ini:"name"`
}
So(cfg.MapTo(&fake), ShouldBeNil)
cfg, err = LooseLoad([]byte("name=Unknwon"), "testdata/404.ini")
So(err, ShouldBeNil)
So(cfg.Section("").Key("name").String(), ShouldEqual, "Unknwon")
So(cfg.MapTo(&fake), ShouldBeNil)
So(fake.Name, ShouldEqual, "Unknwon")
})
})
}
func Test_File_Append(t *testing.T) {
Convey("Append data sources", t, func() {
cfg, err := Load([]byte(""))
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
So(cfg.Append([]byte(""), []byte("")), ShouldBeNil)
Convey("Append bad data sources", func() {
So(cfg.Append(1), ShouldNotBeNil)
So(cfg.Append([]byte(""), 1), ShouldNotBeNil)
})
})
}
func Test_File_WriteTo(t *testing.T) {
Convey("Write to somewhere", t, func() {
var buf bytes.Buffer
cfg := Empty()
cfg.WriteTo(&buf)
})
}
func Test_File_SaveTo_WriteTo(t *testing.T) {
Convey("Save file", t, func() {
cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
cfg.Section("").Key("NAME").Comment = "Package name"
cfg.Section("author").Comment = `Information about package author
# Bio can be written in multiple lines.`
cfg.Section("advanced").Key("val w/ pound").SetValue("my#password")
cfg.Section("advanced").Key("longest key has a colon : yes/no").SetValue("yes")
So(cfg.SaveTo("testdata/conf_out.ini"), ShouldBeNil)
cfg.Section("author").Key("NAME").Comment = "This is author name"
So(cfg.SaveToIndent("testdata/conf_out.ini", "\t"), ShouldBeNil)
var buf bytes.Buffer
_, err = cfg.WriteToIndent(&buf, "\t")
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `; Package name
NAME = ini
; Package version
VERSION = v1
; Package import path
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
; Information about package author
# Bio can be written in multiple lines.
[author]
; This is author name
NAME = Unknwon
E-MAIL = u@gogs.io
GITHUB = https://github.com/%(NAME)s GITHUB = https://github.com/%(NAME)s
# Succeeding comment
BIO = """Gopher. BIO = """Gopher.
Coding addict. Coding addict.
Good man. Good man.
""" """ # Succeeding comment`
_MINIMAL_CONF = "testdata/minimal.ini"
_FULL_CONF = "testdata/full.ini"
_NOT_FOUND_CONF = "testdata/404.ini"
)
[package] func TestLoad(t *testing.T) {
CLONE_URL = https://%(IMPORT_PATH)s Convey("Load from good data sources", t, func() {
f, err := ini.Load([]byte(`
NAME = ini
VERSION = v1
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s`),
"testdata/minimal.ini",
ioutil.NopCloser(bytes.NewReader([]byte(`
[author]
NAME = Unknwon
`))),
)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
[package.sub] // Vaildate values make sure all sources are loaded correctly
UNUSED_KEY = should be deleted sec := f.Section("")
So(sec.Key("NAME").String(), ShouldEqual, "ini")
So(sec.Key("VERSION").String(), ShouldEqual, "v1")
So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1")
[features] sec = f.Section("author")
- = Support read/write comments of keys and sections So(sec.Key("NAME").String(), ShouldEqual, "Unknwon")
- = Support auto-increment of key names So(sec.Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
- = Support load multiple files to overwrite key values })
[types] Convey("Load from bad data sources", t, func() {
STRING = str Convey("Invalid input", func() {
BOOL = true _, err := ini.Load(_NOT_FOUND_CONF)
BOOL_FALSE = false So(err, ShouldNotBeNil)
FLOAT64 = 1.25 })
INT = 10
TIME = 2015-01-01T20:17:05Z
DURATION = 2h45m
UINT = 3
[array] Convey("Unsupported type", func() {
STRINGS = en, zh, de _, err := ini.Load(123)
FLOAT64S = 1.1, 2.2, 3.3 So(err, ShouldNotBeNil)
INTS = 1, 2, 3 })
UINTS = 1, 2, 3
TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
[note]
empty_lines = next line is empty
; Comment before the section
; This is a comment for the section too
[comments]
; Comment before key
key = value
; This is a comment for key2
key2 = value2
key3 = "one", "two", "three"
[advance]
value with quotes = some value
value quote2 again = some value
includes comment sign = `+"`"+"my#password"+"`"+`
includes comment sign2 = `+"`"+"my;password"+"`"+`
true = 2+3=5
`+"`"+`1+1=2`+"`"+` = true
`+"`"+`6+1=7`+"`"+` = true
"""`+"`"+`5+5`+"`"+`""" = 10
`+"`"+`"6+6"`+"`"+` = 12
`+"`"+`7-2=4`+"`"+` = false
ADDRESS = """404 road,
NotFound, State, 50000"""
two_lines = how about continuation lines?
lots_of_lines = 1 2 3 4
[advanced]
val w/ pound = `+"`"+`my#password`+"`"+`
`+"`"+`longest key has a colon : yes/no`+"`"+` = yes
`)
}) })
} }
func Test_File_WriteTo_SectionRaw(t *testing.T) { func TestLoadSources(t *testing.T) {
Convey("Write a INI with a raw section", t, func() { Convey("Load from data sources with options", t, func() {
var buf bytes.Buffer Convey("Ignore nonexistent files", func() {
cfg, err := LoadSources( f, err := ini.LooseLoad(_NOT_FOUND_CONF, _MINIMAL_CONF)
LoadOptions{ So(err, ShouldBeNil)
UnparseableSections: []string{"CORE_LESSON", "COMMENTS"}, So(f, ShouldNotBeNil)
},
"testdata/aicc.ini") Convey("Inverse case", func() {
So(err, ShouldBeNil) _, err = ini.Load(_NOT_FOUND_CONF)
So(cfg, ShouldNotBeNil) So(err, ShouldNotBeNil)
cfg.WriteToIndent(&buf, "\t") })
So(buf.String(), ShouldEqual, `[Core] })
Lesson_Location = 87
Lesson_Status = C Convey("Insensitive to section and key names", func() {
Score = 3 f, err := ini.InsensitiveLoad(_MINIMAL_CONF)
Time = 00:02:30 So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("Author").Key("e-mail").String(), ShouldEqual, "u@gogs.io")
Convey("Write out", func() {
var buf bytes.Buffer
_, err := f.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `[author]
e-mail = u@gogs.io
`)
})
Convey("Inverse case", func() {
f, err := ini.Load(_MINIMAL_CONF)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("Author").Key("e-mail").String(), ShouldBeEmpty)
})
})
Convey("Ignore continuation lines", func() {
f, err := ini.LoadSources(ini.LoadOptions{
IgnoreContinuation: true,
}, []byte(`
key1=a\b\
key2=c\d\
key3=value`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").Key("key1").String(), ShouldEqual, `a\b\`)
So(f.Section("").Key("key2").String(), ShouldEqual, `c\d\`)
So(f.Section("").Key("key3").String(), ShouldEqual, "value")
Convey("Inverse case", func() {
f, err := ini.Load([]byte(`
key1=a\b\
key2=c\d\`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").Key("key1").String(), ShouldEqual, `a\bkey2=c\d`)
})
})
Convey("Ignore inline comments", func() {
f, err := ini.LoadSources(ini.LoadOptions{
IgnoreInlineComment: true,
}, []byte(`
key1=value ;comment
key2=value2 #comment2`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").Key("key1").String(), ShouldEqual, `value ;comment`)
So(f.Section("").Key("key2").String(), ShouldEqual, `value2 #comment2`)
Convey("Inverse case", func() {
f, err := ini.Load([]byte(`
key1=value ;comment
key2=value2 #comment2`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").Key("key1").String(), ShouldEqual, `value`)
So(f.Section("").Key("key1").Comment, ShouldEqual, `;comment`)
So(f.Section("").Key("key2").String(), ShouldEqual, `value2`)
So(f.Section("").Key("key2").Comment, ShouldEqual, `#comment2`)
})
})
Convey("Allow boolean type keys", func() {
f, err := ini.LoadSources(ini.LoadOptions{
AllowBooleanKeys: true,
}, []byte(`
key1=hello
#key2
key3`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").KeyStrings(), ShouldResemble, []string{"key1", "key3"})
So(f.Section("").Key("key3").MustBool(false), ShouldBeTrue)
Convey("Write out", func() {
var buf bytes.Buffer
_, err := f.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `key1 = hello
# key2
key3
`)
})
Convey("Inverse case", func() {
_, err := ini.Load([]byte(`
key1=hello
#key2
key3`))
So(err, ShouldNotBeNil)
})
})
Convey("Allow shadow keys", func() {
f, err := ini.ShadowLoad([]byte(`
[remote "origin"]
url = https://github.com/Antergone/test1.git
url = https://github.com/Antergone/test2.git
fetch = +refs/heads/*:refs/remotes/origin/*`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section(`remote "origin"`).Key("url").String(), ShouldEqual, "https://github.com/Antergone/test1.git")
So(f.Section(`remote "origin"`).Key("url").ValueWithShadows(), ShouldResemble, []string{
"https://github.com/Antergone/test1.git",
"https://github.com/Antergone/test2.git",
})
So(f.Section(`remote "origin"`).Key("fetch").String(), ShouldEqual, "+refs/heads/*:refs/remotes/origin/*")
Convey("Write out", func() {
var buf bytes.Buffer
_, err := f.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `[remote "origin"]
url = https://github.com/Antergone/test1.git
url = https://github.com/Antergone/test2.git
fetch = +refs/heads/*:refs/remotes/origin/*
`)
})
Convey("Inverse case", func() {
f, err := ini.Load([]byte(`
[remote "origin"]
url = https://github.com/Antergone/test1.git
url = https://github.com/Antergone/test2.git`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section(`remote "origin"`).Key("url").String(), ShouldEqual, "https://github.com/Antergone/test2.git")
})
})
Convey("Unescape double quotes inside value", func() {
f, err := ini.LoadSources(ini.LoadOptions{
UnescapeValueDoubleQuotes: true,
}, []byte(`
create_repo="创建了仓库 <a href=\"%s\">%s</a>"`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").Key("create_repo").String(), ShouldEqual, `创建了仓库 <a href="%s">%s</a>`)
Convey("Inverse case", func() {
f, err := ini.Load([]byte(`
create_repo="创建了仓库 <a href=\"%s\">%s</a>"`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").Key("create_repo").String(), ShouldEqual, `"创建了仓库 <a href=\"%s\">%s</a>"`)
})
})
Convey("Allow unparseable sections", func() {
f, err := ini.LoadSources(ini.LoadOptions{
Insensitive: true,
UnparseableSections: []string{"core_lesson", "comments"},
}, []byte(`
Lesson_Location = 87
Lesson_Status = C
Score = 3
Time = 00:02:30
[CORE_LESSON] [CORE_LESSON]
my lesson state data – 1111111111111111111000000000000000001110000 my lesson state data – 1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000 – end my lesson state data 111111111111111111100000000000111000000000 – end my lesson state data
[COMMENTS] [COMMENTS]
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").Key("score").String(), ShouldEqual, "3")
So(f.Section("").Body(), ShouldBeEmpty)
So(f.Section("core_lesson").Body(), ShouldEqual, `my lesson state data – 1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000 – end my lesson state data`)
So(f.Section("comments").Body(), ShouldEqual, `<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`)
Convey("Write out", func() {
var buf bytes.Buffer
_, err := f.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `lesson_location = 87
lesson_status = C
score = 3
time = 00:02:30
[core_lesson]
my lesson state data – 1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000 – end my lesson state data
[comments]
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1> <1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
`) `)
})
Convey("Inverse case", func() {
_, err := ini.Load([]byte(`
[CORE_LESSON]
my lesson state data – 1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000 – end my lesson state data`))
So(err, ShouldNotBeNil)
})
})
}) })
} }
// Helpers for slice tests.
func float64sEqual(values []float64, expected ...float64) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
}
}
func intsEqual(values []int, expected ...int) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
}
}
func int64sEqual(values []int64, expected ...int64) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
}
}
func uintsEqual(values []uint, expected ...uint) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
}
}
func uint64sEqual(values []uint64, expected ...uint64) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
}
}
func timesEqual(values []time.Time, expected ...time.Time) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i].String(), ShouldEqual, v.String())
}
}

40
vendor/github.com/go-ini/ini/key.go сгенерированный поставляемый
Просмотреть файл

@@ -15,6 +15,7 @@
package ini package ini
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"strconv" "strconv"
@@ -25,6 +26,7 @@ import (
// Key represents a key under a section. // Key represents a key under a section.
type Key struct { type Key struct {
s *Section s *Section
Comment string
name string name string
value string value string
isAutoIncrement bool isAutoIncrement bool
@@ -32,8 +34,6 @@ type Key struct {
isShadow bool isShadow bool
shadows []*Key shadows []*Key
Comment string
} }
// newKey simply return a key object with given values. // newKey simply return a key object with given values.
@@ -444,11 +444,39 @@ func (k *Key) Strings(delim string) []string {
return []string{} return []string{}
} }
vals := strings.Split(str, delim) runes := []rune(str)
for i := range vals { vals := make([]string, 0, 2)
// vals[i] = k.transformValue(strings.TrimSpace(vals[i])) var buf bytes.Buffer
vals[i] = strings.TrimSpace(vals[i]) escape := false
idx := 0
for {
if escape {
escape = false
if runes[idx] != '\\' && !strings.HasPrefix(string(runes[idx:]), delim) {
buf.WriteRune('\\')
}
buf.WriteRune(runes[idx])
} else {
if runes[idx] == '\\' {
escape = true
} else if strings.HasPrefix(string(runes[idx:]), delim) {
idx += len(delim) - 1
vals = append(vals, strings.TrimSpace(buf.String()))
buf.Reset()
} else {
buf.WriteRune(runes[idx])
}
}
idx += 1
if idx == len(runes) {
break
}
} }
if buf.Len() > 0 {
vals = append(vals, strings.TrimSpace(buf.String()))
}
return vals return vals
} }

391
vendor/github.com/go-ini/ini/key_test.go сгенерированный поставляемый
Просмотреть файл

@@ -12,26 +12,108 @@
// License for the specific language governing permissions and limitations // License for the specific language governing permissions and limitations
// under the License. // under the License.
package ini package ini_test
import ( import (
"bytes"
"fmt" "fmt"
"strings" "strings"
"testing" "testing"
"time" "time"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/ini.v1"
) )
func Test_Key(t *testing.T) { func TestKey_AddShadow(t *testing.T) {
Convey("Test getting and setting values", t, func() { Convey("Add shadow to a key", t, func() {
cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") f, err := ini.ShadowLoad([]byte(`
[notes]
-: note1`))
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil) So(f, ShouldNotBeNil)
Convey("Get values in default section", func() { k, err := f.Section("").NewKey("NAME", "ini")
sec := cfg.Section("") So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.AddShadow("ini.v1"), ShouldBeNil)
So(k.ValueWithShadows(), ShouldResemble, []string{"ini", "ini.v1"})
Convey("Add shadow to boolean key", func() {
k, err := f.Section("").NewBooleanKey("published")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.AddShadow("beta"), ShouldNotBeNil)
})
Convey("Add shadow to auto-increment key", func() {
So(f.Section("notes").Key("#1").AddShadow("beta"), ShouldNotBeNil)
})
})
Convey("Shadow is not allowed", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.AddShadow("ini.v1"), ShouldNotBeNil)
})
}
// Helpers for slice tests.
func float64sEqual(values []float64, expected ...float64) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
}
}
func intsEqual(values []int, expected ...int) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
}
}
func int64sEqual(values []int64, expected ...int64) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
}
}
func uintsEqual(values []uint, expected ...uint) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
}
}
func uint64sEqual(values []uint64, expected ...uint64) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
}
}
func timesEqual(values []time.Time, expected ...time.Time) {
So(values, ShouldHaveLength, len(expected))
for i, v := range expected {
So(values[i].String(), ShouldEqual, v.String())
}
}
func TestKey_Helpers(t *testing.T) {
Convey("Getting and setting values", t, func() {
f, err := ini.Load(_FULL_CONF)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
Convey("Get string representation", func() {
sec := f.Section("")
So(sec, ShouldNotBeNil) So(sec, ShouldNotBeNil)
So(sec.Key("NAME").Value(), ShouldEqual, "ini") So(sec.Key("NAME").Value(), ShouldEqual, "ini")
So(sec.Key("NAME").String(), ShouldEqual, "ini") So(sec.Key("NAME").String(), ShouldEqual, "ini")
@@ -40,55 +122,65 @@ func Test_Key(t *testing.T) {
}), ShouldEqual, "ini") }), ShouldEqual, "ini")
So(sec.Key("NAME").Comment, ShouldEqual, "; Package name") So(sec.Key("NAME").Comment, ShouldEqual, "; Package name")
So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1") So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1")
Convey("With ValueMapper", func() {
f.ValueMapper = func(in string) string {
if in == "gopkg.in/%(NAME)s.%(VERSION)s" {
return "github.com/go-ini/ini"
}
return in
}
So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "github.com/go-ini/ini")
})
}) })
Convey("Get values in non-default section", func() { Convey("Get values in non-default section", func() {
sec := cfg.Section("author") sec := f.Section("author")
So(sec, ShouldNotBeNil) So(sec, ShouldNotBeNil)
So(sec.Key("NAME").String(), ShouldEqual, "Unknwon") So(sec.Key("NAME").String(), ShouldEqual, "Unknwon")
So(sec.Key("GITHUB").String(), ShouldEqual, "https://github.com/Unknwon") So(sec.Key("GITHUB").String(), ShouldEqual, "https://github.com/Unknwon")
sec = cfg.Section("package") sec = f.Section("package")
So(sec, ShouldNotBeNil) So(sec, ShouldNotBeNil)
So(sec.Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1") So(sec.Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
}) })
Convey("Get auto-increment key names", func() { Convey("Get auto-increment key names", func() {
keys := cfg.Section("features").Keys() keys := f.Section("features").Keys()
for i, k := range keys { for i, k := range keys {
So(k.Name(), ShouldEqual, fmt.Sprintf("#%d", i+1)) So(k.Name(), ShouldEqual, fmt.Sprintf("#%d", i+1))
} }
}) })
Convey("Get parent-keys that are available to the child section", func() { Convey("Get parent-keys that are available to the child section", func() {
parentKeys := cfg.Section("package.sub").ParentKeys() parentKeys := f.Section("package.sub").ParentKeys()
for _, k := range parentKeys { for _, k := range parentKeys {
So(k.Name(), ShouldEqual, "CLONE_URL") So(k.Name(), ShouldEqual, "CLONE_URL")
} }
}) })
Convey("Get overwrite value", func() { Convey("Get overwrite value", func() {
So(cfg.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io") So(f.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
}) })
Convey("Get sections", func() { Convey("Get sections", func() {
sections := cfg.Sections() sections := f.Sections()
for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "advance"} { for i, name := range []string{ini.DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"} {
So(sections[i].Name(), ShouldEqual, name) So(sections[i].Name(), ShouldEqual, name)
} }
}) })
Convey("Get parent section value", func() { Convey("Get parent section value", func() {
So(cfg.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1") So(f.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
So(cfg.Section("package.fake.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1") So(f.Section("package.fake.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
}) })
Convey("Get multiple line value", func() { Convey("Get multiple line value", func() {
So(cfg.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n") So(f.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n")
}) })
Convey("Get values with type", func() { Convey("Get values with type", func() {
sec := cfg.Section("types") sec := f.Section("types")
v1, err := sec.Key("BOOL").Bool() v1, err := sec.Key("BOOL").Bool()
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(v1, ShouldBeTrue) So(v1, ShouldBeTrue)
@@ -168,7 +260,7 @@ func Test_Key(t *testing.T) {
}) })
Convey("Get value with candidates", func() { Convey("Get value with candidates", func() {
sec := cfg.Section("types") sec := f.Section("types")
So(sec.Key("STRING").In("", []string{"str", "arr", "types"}), ShouldEqual, "str") So(sec.Key("STRING").In("", []string{"str", "arr", "types"}), ShouldEqual, "str")
So(sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25) So(sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10) So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10)
@@ -194,7 +286,7 @@ func Test_Key(t *testing.T) {
}) })
Convey("Get values in range", func() { Convey("Get values in range", func() {
sec := cfg.Section("types") sec := f.Section("types")
So(sec.Key("FLOAT64").RangeFloat64(0, 1, 2), ShouldEqual, 1.25) So(sec.Key("FLOAT64").RangeFloat64(0, 1, 2), ShouldEqual, 1.25)
So(sec.Key("INT").RangeInt(0, 10, 20), ShouldEqual, 10) So(sec.Key("INT").RangeInt(0, 10, 20), ShouldEqual, 10)
So(sec.Key("INT").RangeInt64(0, 10, 20), ShouldEqual, 10) So(sec.Key("INT").RangeInt64(0, 10, 20), ShouldEqual, 10)
@@ -218,7 +310,7 @@ func Test_Key(t *testing.T) {
}) })
Convey("Get values into slice", func() { Convey("Get values into slice", func() {
sec := cfg.Section("array") sec := f.Section("array")
So(strings.Join(sec.Key("STRINGS").Strings(","), ","), ShouldEqual, "en,zh,de") So(strings.Join(sec.Key("STRINGS").Strings(","), ","), ShouldEqual, "en,zh,de")
So(len(sec.Key("STRINGS_404").Strings(",")), ShouldEqual, 0) So(len(sec.Key("STRINGS_404").Strings(",")), ShouldEqual, 0)
@@ -243,8 +335,18 @@ func Test_Key(t *testing.T) {
timesEqual(vals6, t, t, t) timesEqual(vals6, t, t, t)
}) })
Convey("Test string slice escapes", func() {
sec := f.Section("string escapes")
So(sec.Key("key1").Strings(","), ShouldResemble, []string{"value1", "value2", "value3"})
So(sec.Key("key2").Strings(","), ShouldResemble, []string{"value1, value2"})
So(sec.Key("key3").Strings(","), ShouldResemble, []string{`val\ue1`, "value2"})
So(sec.Key("key4").Strings(","), ShouldResemble, []string{`value1\`, `value\\2`})
So(sec.Key("key5").Strings(",,"), ShouldResemble, []string{"value1,, value2"})
So(sec.Key("key6").Strings(" "), ShouldResemble, []string{"aaa", "bbb and space", "ccc"})
})
Convey("Get valid values into slice", func() { Convey("Get valid values into slice", func() {
sec := cfg.Section("array") sec := f.Section("array")
vals1 := sec.Key("FLOAT64S").ValidFloat64s(",") vals1 := sec.Key("FLOAT64S").ValidFloat64s(",")
float64sEqual(vals1, 1.1, 2.2, 3.3) float64sEqual(vals1, 1.1, 2.2, 3.3)
@@ -267,7 +369,7 @@ func Test_Key(t *testing.T) {
}) })
Convey("Get values one type into slice of another type", func() { Convey("Get values one type into slice of another type", func() {
sec := cfg.Section("array") sec := f.Section("array")
vals1 := sec.Key("STRINGS").ValidFloat64s(",") vals1 := sec.Key("STRINGS").ValidFloat64s(",")
So(vals1, ShouldBeEmpty) So(vals1, ShouldBeEmpty)
@@ -288,7 +390,7 @@ func Test_Key(t *testing.T) {
}) })
Convey("Get valid values into slice without errors", func() { Convey("Get valid values into slice without errors", func() {
sec := cfg.Section("array") sec := f.Section("array")
vals1, err := sec.Key("FLOAT64S").StrictFloat64s(",") vals1, err := sec.Key("FLOAT64S").StrictFloat64s(",")
So(err, ShouldBeNil) So(err, ShouldBeNil)
float64sEqual(vals1, 1.1, 2.2, 3.3) float64sEqual(vals1, 1.1, 2.2, 3.3)
@@ -317,7 +419,7 @@ func Test_Key(t *testing.T) {
}) })
Convey("Get invalid values into slice", func() { Convey("Get invalid values into slice", func() {
sec := cfg.Section("array") sec := f.Section("array")
vals1, err := sec.Key("STRINGS").StrictFloat64s(",") vals1, err := sec.Key("STRINGS").StrictFloat64s(",")
So(vals1, ShouldBeEmpty) So(vals1, ShouldBeEmpty)
So(err, ShouldNotBeNil) So(err, ShouldNotBeNil)
@@ -342,232 +444,37 @@ func Test_Key(t *testing.T) {
So(vals6, ShouldBeEmpty) So(vals6, ShouldBeEmpty)
So(err, ShouldNotBeNil) So(err, ShouldNotBeNil)
}) })
Convey("Get key hash", func() {
cfg.Section("").KeysHash()
})
Convey("Set key value", func() {
k := cfg.Section("author").Key("NAME")
k.SetValue("无闻")
So(k.String(), ShouldEqual, "无闻")
})
Convey("Get key strings", func() {
So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,BOOL_FALSE,FLOAT64,INT,TIME,DURATION,UINT")
})
Convey("Delete a key", func() {
cfg.Section("package.sub").DeleteKey("UNUSED_KEY")
_, err := cfg.Section("package.sub").GetKey("UNUSED_KEY")
So(err, ShouldNotBeNil)
})
Convey("Has Key (backwards compatible)", func() {
sec := cfg.Section("package.sub")
haskey1 := sec.Haskey("UNUSED_KEY")
haskey2 := sec.Haskey("CLONE_URL")
haskey3 := sec.Haskey("CLONE_URL_NO")
So(haskey1, ShouldBeTrue)
So(haskey2, ShouldBeTrue)
So(haskey3, ShouldBeFalse)
})
Convey("Has Key", func() {
sec := cfg.Section("package.sub")
haskey1 := sec.HasKey("UNUSED_KEY")
haskey2 := sec.HasKey("CLONE_URL")
haskey3 := sec.HasKey("CLONE_URL_NO")
So(haskey1, ShouldBeTrue)
So(haskey2, ShouldBeTrue)
So(haskey3, ShouldBeFalse)
})
Convey("Has Value", func() {
sec := cfg.Section("author")
hasvalue1 := sec.HasValue("Unknwon")
hasvalue2 := sec.HasValue("doc")
So(hasvalue1, ShouldBeTrue)
So(hasvalue2, ShouldBeFalse)
})
}) })
}
Convey("Test getting and setting bad values", t, func() { func TestKey_StringsWithShadows(t *testing.T) {
cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") Convey("Get strings of shadows of a key", t, func() {
f, err := ini.ShadowLoad([]byte(""))
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil) So(f, ShouldNotBeNil)
Convey("Create new key with empty name", func() { k, err := f.Section("").NewKey("NUMS", "1,2")
k, err := cfg.Section("").NewKey("", "")
So(err, ShouldNotBeNil)
So(k, ShouldBeNil)
})
Convey("Create new section with empty name", func() {
s, err := cfg.NewSection("")
So(err, ShouldNotBeNil)
So(s, ShouldBeNil)
})
Convey("Create new sections with empty name", func() {
So(cfg.NewSections(""), ShouldNotBeNil)
})
Convey("Get section that not exists", func() {
s, err := cfg.GetSection("404")
So(err, ShouldNotBeNil)
So(s, ShouldBeNil)
s = cfg.Section("404")
So(s, ShouldNotBeNil)
})
})
Convey("Test key hash clone", t, func() {
cfg, err := Load([]byte(strings.Replace("network=tcp,addr=127.0.0.1:6379,db=4,pool_size=100,idle_timeout=180", ",", "\n", -1)))
So(err, ShouldBeNil) So(err, ShouldBeNil)
for _, v := range cfg.Section("").KeysHash() { So(k, ShouldNotBeNil)
So(len(v), ShouldBeGreaterThan, 0) k, err = f.Section("").NewKey("NUMS", "4,5,6")
}
})
Convey("Key has empty value", t, func() {
_conf := `key1=
key2= ; comment`
cfg, err := Load([]byte(_conf))
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cfg.Section("").Key("key1").Value(), ShouldBeEmpty) So(k, ShouldNotBeNil)
So(k.StringsWithShadows(","), ShouldResemble, []string{"1", "2", "4", "5", "6"})
}) })
} }
const _CONF_GIT_CONFIG = ` func TestKey_SetValue(t *testing.T) {
[remote "origin"] Convey("Set value of key", t, func() {
url = https://github.com/Antergone/test1.git f := ini.Empty()
url = https://github.com/Antergone/test2.git So(f, ShouldNotBeNil)
`
func Test_Key_Shadows(t *testing.T) { k, err := f.Section("").NewKey("NAME", "ini")
Convey("Shadows keys", t, func() { So(err, ShouldBeNil)
Convey("Disable shadows", func() { So(k, ShouldNotBeNil)
cfg, err := Load([]byte(_CONF_GIT_CONFIG)) So(k.Value(), ShouldEqual, "ini")
So(err, ShouldBeNil)
So(cfg.Section(`remote "origin"`).Key("url").String(), ShouldEqual, "https://github.com/Antergone/test2.git")
})
Convey("Enable shadows", func() { k.SetValue("ini.v1")
cfg, err := ShadowLoad([]byte(_CONF_GIT_CONFIG)) So(k.Value(), ShouldEqual, "ini.v1")
So(err, ShouldBeNil)
So(cfg.Section(`remote "origin"`).Key("url").String(), ShouldEqual, "https://github.com/Antergone/test1.git")
So(strings.Join(cfg.Section(`remote "origin"`).Key("url").ValueWithShadows(), " "), ShouldEqual,
"https://github.com/Antergone/test1.git https://github.com/Antergone/test2.git")
Convey("Save with shadows", func() {
var buf bytes.Buffer
_, err := cfg.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `[remote "origin"]
url = https://github.com/Antergone/test1.git
url = https://github.com/Antergone/test2.git
`)
})
})
}) })
} }
func newTestFile(block bool) *File {
c, _ := Load([]byte(_CONF_DATA))
c.BlockMode = block
return c
}
func Benchmark_Key_Value(b *testing.B) {
c := newTestFile(true)
for i := 0; i < b.N; i++ {
c.Section("").Key("NAME").Value()
}
}
func Benchmark_Key_Value_NonBlock(b *testing.B) {
c := newTestFile(false)
for i := 0; i < b.N; i++ {
c.Section("").Key("NAME").Value()
}
}
func Benchmark_Key_Value_ViaSection(b *testing.B) {
c := newTestFile(true)
sec := c.Section("")
for i := 0; i < b.N; i++ {
sec.Key("NAME").Value()
}
}
func Benchmark_Key_Value_ViaSection_NonBlock(b *testing.B) {
c := newTestFile(false)
sec := c.Section("")
for i := 0; i < b.N; i++ {
sec.Key("NAME").Value()
}
}
func Benchmark_Key_Value_Direct(b *testing.B) {
c := newTestFile(true)
key := c.Section("").Key("NAME")
for i := 0; i < b.N; i++ {
key.Value()
}
}
func Benchmark_Key_Value_Direct_NonBlock(b *testing.B) {
c := newTestFile(false)
key := c.Section("").Key("NAME")
for i := 0; i < b.N; i++ {
key.Value()
}
}
func Benchmark_Key_String(b *testing.B) {
c := newTestFile(true)
for i := 0; i < b.N; i++ {
_ = c.Section("").Key("NAME").String()
}
}
func Benchmark_Key_String_NonBlock(b *testing.B) {
c := newTestFile(false)
for i := 0; i < b.N; i++ {
_ = c.Section("").Key("NAME").String()
}
}
func Benchmark_Key_String_ViaSection(b *testing.B) {
c := newTestFile(true)
sec := c.Section("")
for i := 0; i < b.N; i++ {
_ = sec.Key("NAME").String()
}
}
func Benchmark_Key_String_ViaSection_NonBlock(b *testing.B) {
c := newTestFile(false)
sec := c.Section("")
for i := 0; i < b.N; i++ {
_ = sec.Key("NAME").String()
}
}
func Benchmark_Key_SetValue(b *testing.B) {
c := newTestFile(true)
for i := 0; i < b.N; i++ {
c.Section("").Key("NAME").SetValue("10")
}
}
func Benchmark_Key_SetValue_VisSection(b *testing.B) {
c := newTestFile(true)
sec := c.Section("")
for i := 0; i < b.N; i++ {
sec.Key("NAME").SetValue("10")
}
}

25
vendor/github.com/go-ini/ini/parser.go сгенерированный поставляемый
Просмотреть файл

@@ -193,7 +193,7 @@ func hasSurroundedQuote(in string, quote byte) bool {
strings.IndexByte(in[1:], quote) == len(in)-2 strings.IndexByte(in[1:], quote) == len(in)-2
} }
func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bool) (string, error) { func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes bool) (string, error) {
line := strings.TrimLeftFunc(string(in), unicode.IsSpace) line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
if len(line) == 0 { if len(line) == 0 {
return "", nil return "", nil
@@ -204,6 +204,8 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bo
valQuote = `"""` valQuote = `"""`
} else if line[0] == '`' { } else if line[0] == '`' {
valQuote = "`" valQuote = "`"
} else if unescapeValueDoubleQuotes && line[0] == '"' {
valQuote = `"`
} }
if len(valQuote) > 0 { if len(valQuote) > 0 {
@@ -214,6 +216,9 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bo
return p.readMultilines(line, line[startIdx:], valQuote) return p.readMultilines(line, line[startIdx:], valQuote)
} }
if unescapeValueDoubleQuotes && valQuote == `"` {
return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil
}
return line[startIdx : pos+startIdx], nil return line[startIdx : pos+startIdx], nil
} }
@@ -234,7 +239,7 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bo
} }
} }
// Trim single quotes // Trim single and double quotes
if hasSurroundedQuote(line, '\'') || if hasSurroundedQuote(line, '\'') ||
hasSurroundedQuote(line, '"') { hasSurroundedQuote(line, '"') {
line = line[1 : len(line)-1] line = line[1 : len(line)-1]
@@ -250,7 +255,11 @@ func (f *File) parse(reader io.Reader) (err error) {
} }
// Ignore error because default section name is never empty string. // Ignore error because default section name is never empty string.
section, _ := f.NewSection(DEFAULT_SECTION) name := DEFAULT_SECTION
if f.options.Insensitive {
name = strings.ToLower(DEFAULT_SECTION)
}
section, _ := f.NewSection(name)
var line []byte var line []byte
var inUnparseableSection bool var inUnparseableSection bool
@@ -321,7 +330,10 @@ func (f *File) parse(reader io.Reader) (err error) {
if err != nil { if err != nil {
// Treat as boolean key when desired, and whole line is key name. // Treat as boolean key when desired, and whole line is key name.
if IsErrDelimiterNotFound(err) && f.options.AllowBooleanKeys { if IsErrDelimiterNotFound(err) && f.options.AllowBooleanKeys {
kname, err := p.readValue(line, f.options.IgnoreContinuation, f.options.IgnoreInlineComment) kname, err := p.readValue(line,
f.options.IgnoreContinuation,
f.options.IgnoreInlineComment,
f.options.UnescapeValueDoubleQuotes)
if err != nil { if err != nil {
return err return err
} }
@@ -344,7 +356,10 @@ func (f *File) parse(reader io.Reader) (err error) {
p.count++ p.count++
} }
value, err := p.readValue(line[offset:], f.options.IgnoreContinuation, f.options.IgnoreInlineComment) value, err := p.readValue(line[offset:],
f.options.IgnoreContinuation,
f.options.IgnoreInlineComment,
f.options.UnescapeValueDoubleQuotes)
if err != nil { if err != nil {
return err return err
} }

49
vendor/github.com/go-ini/ini/parser_test.go сгенерированный поставляемый
Просмотреть файл

@@ -12,31 +12,66 @@
// License for the specific language governing permissions and limitations // License for the specific language governing permissions and limitations
// under the License. // under the License.
package ini package ini_test
import ( import (
"testing" "testing"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/ini.v1"
) )
func Test_BOM(t *testing.T) { func TestBOM(t *testing.T) {
Convey("Test handling BOM", t, func() { Convey("Test handling BOM", t, func() {
Convey("UTF-8-BOM", func() { Convey("UTF-8-BOM", func() {
cfg, err := Load("testdata/UTF-8-BOM.ini") f, err := ini.Load("testdata/UTF-8-BOM.ini")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil) So(f, ShouldNotBeNil)
So(cfg.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io") So(f.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
}) })
Convey("UTF-16-LE-BOM", func() { Convey("UTF-16-LE-BOM", func() {
cfg, err := Load("testdata/UTF-16-LE-BOM.ini") f, err := ini.Load("testdata/UTF-16-LE-BOM.ini")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil) So(f, ShouldNotBeNil)
}) })
Convey("UTF-16-BE-BOM", func() { Convey("UTF-16-BE-BOM", func() {
}) })
}) })
} }
func TestBadLoad(t *testing.T) {
Convey("Load with bad data", t, func() {
Convey("Bad section name", func() {
_, err := ini.Load([]byte("[]"))
So(err, ShouldNotBeNil)
_, err = ini.Load([]byte("["))
So(err, ShouldNotBeNil)
})
Convey("Bad keys", func() {
_, err := ini.Load([]byte(`"""name`))
So(err, ShouldNotBeNil)
_, err = ini.Load([]byte(`"""name"""`))
So(err, ShouldNotBeNil)
_, err = ini.Load([]byte(`""=1`))
So(err, ShouldNotBeNil)
_, err = ini.Load([]byte(`=`))
So(err, ShouldNotBeNil)
_, err = ini.Load([]byte(`name`))
So(err, ShouldNotBeNil)
})
Convey("Bad values", func() {
_, err := ini.Load([]byte(`name="""Unknwon`))
So(err, ShouldNotBeNil)
})
})
}

9
vendor/github.com/go-ini/ini/section.go сгенерированный поставляемый
Просмотреть файл

@@ -54,6 +54,14 @@ func (s *Section) Body() string {
return strings.TrimSpace(s.rawBody) return strings.TrimSpace(s.rawBody)
} }
// SetBody updates body content only if section is raw.
func (s *Section) SetBody(body string) {
if !s.isRawSection {
return
}
s.rawBody = body
}
// NewKey creates a new key to given section. // NewKey creates a new key to given section.
func (s *Section) NewKey(name, val string) (*Key, error) { func (s *Section) NewKey(name, val string) (*Key, error) {
if len(name) == 0 { if len(name) == 0 {
@@ -136,6 +144,7 @@ func (s *Section) HasKey(name string) bool {
} }
// Haskey is a backwards-compatible name for HasKey. // Haskey is a backwards-compatible name for HasKey.
// TODO: delete me in v2
func (s *Section) Haskey(name string) bool { func (s *Section) Haskey(name string) bool {
return s.HasKey(name) return s.HasKey(name)
} }

316
vendor/github.com/go-ini/ini/section_test.go сгенерированный поставляемый
Просмотреть файл

@@ -12,64 +12,302 @@
// License for the specific language governing permissions and limitations // License for the specific language governing permissions and limitations
// under the License. // under the License.
package ini package ini_test
import ( import (
"strings"
"testing" "testing"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/ini.v1"
) )
func Test_Section(t *testing.T) { func TestSection_SetBody(t *testing.T) {
Convey("Test CRD sections", t, func() { Convey("Set body of raw section", t, func() {
cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") f := ini.Empty()
So(f, ShouldNotBeNil)
sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000`)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil) So(sec, ShouldNotBeNil)
So(sec.Body(), ShouldEqual, `1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000`)
Convey("Get section strings", func() { sec.SetBody("1111111111111111111000000000000000001110000")
So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,comments,advance") So(sec.Body(), ShouldEqual, `1111111111111111111000000000000000001110000`)
})
Convey("Delete a section", func() { Convey("Set for non-raw section", func() {
cfg.DeleteSection("") sec, err := f.NewSection("author")
So(cfg.SectionStrings()[0], ShouldNotEqual, DEFAULT_SECTION)
})
Convey("Create new sections", func() {
cfg.NewSections("test", "test2")
_, err := cfg.GetSection("test")
So(err, ShouldBeNil)
_, err = cfg.GetSection("test2")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(sec.Body(), ShouldBeEmpty)
sec.SetBody("1111111111111111111000000000000000001110000")
So(sec.Body(), ShouldBeEmpty)
}) })
}) })
} }
func Test_SectionRaw(t *testing.T) { func TestSection_NewKey(t *testing.T) {
Convey("Test section raw string", t, func() { Convey("Create a new key", t, func() {
cfg, err := LoadSources( f := ini.Empty()
LoadOptions{ So(f, ShouldNotBeNil)
Insensitive: true,
UnparseableSections: []string{"core_lesson", "comments"}, k, err := f.Section("").NewKey("NAME", "ini")
},
"testdata/aicc.ini")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil) So(k, ShouldNotBeNil)
So(k.Name(), ShouldEqual, "NAME")
So(k.Value(), ShouldEqual, "ini")
Convey("Get section strings", func() { Convey("With duplicated name", func() {
So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,core,core_lesson,comments") k, err := f.Section("").NewKey("NAME", "ini.v1")
})
Convey("Validate non-raw section", func() {
val, err := cfg.Section("core").GetKey("lesson_status")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(val.String(), ShouldEqual, "C") So(k, ShouldNotBeNil)
// Overwrite previous existed key
So(k.Value(), ShouldEqual, "ini.v1")
}) })
Convey("Validate raw section", func() { Convey("With empty string", func() {
So(cfg.Section("core_lesson").Body(), ShouldEqual, `my lesson state data – 1111111111111111111000000000000000001110000 _, err := f.Section("").NewKey("", "")
111111111111111111100000000000111000000000 – end my lesson state data`) So(err, ShouldNotBeNil)
}) })
}) })
}
Convey("Create keys with same name and allow shadow", t, func() {
f, err := ini.ShadowLoad([]byte(""))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("").NewKey("NAME", "ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.ValueWithShadows(), ShouldResemble, []string{"ini", "ini.v1"})
})
}
func TestSection_NewBooleanKey(t *testing.T) {
Convey("Create a new boolean key", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("").NewBooleanKey("start-ssh-server")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.Name(), ShouldEqual, "start-ssh-server")
So(k.Value(), ShouldEqual, "true")
Convey("With empty string", func() {
_, err := f.Section("").NewBooleanKey("")
So(err, ShouldNotBeNil)
})
})
}
func TestSection_GetKey(t *testing.T) {
Convey("Get a key", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("").GetKey("NAME")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.Name(), ShouldEqual, "NAME")
So(k.Value(), ShouldEqual, "ini")
Convey("Key not exists", func() {
_, err := f.Section("").GetKey("404")
So(err, ShouldNotBeNil)
})
Convey("Key exists in parent section", func() {
k, err := f.Section("parent").NewKey("AGE", "18")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("parent.child.son").GetKey("AGE")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.Value(), ShouldEqual, "18")
})
})
}
func TestSection_HasKey(t *testing.T) {
Convey("Check if a key exists", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(f.Section("").HasKey("NAME"), ShouldBeTrue)
So(f.Section("").Haskey("NAME"), ShouldBeTrue)
So(f.Section("").HasKey("404"), ShouldBeFalse)
So(f.Section("").Haskey("404"), ShouldBeFalse)
})
}
func TestSection_HasValue(t *testing.T) {
Convey("Check if contains a value in any key", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(f.Section("").HasValue("ini"), ShouldBeTrue)
So(f.Section("").HasValue("404"), ShouldBeFalse)
})
}
func TestSection_Key(t *testing.T) {
Convey("Get a key", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k = f.Section("").Key("NAME")
So(k, ShouldNotBeNil)
So(k.Name(), ShouldEqual, "NAME")
So(k.Value(), ShouldEqual, "ini")
Convey("Key not exists", func() {
k := f.Section("").Key("404")
So(k, ShouldNotBeNil)
So(k.Name(), ShouldEqual, "404")
})
Convey("Key exists in parent section", func() {
k, err := f.Section("parent").NewKey("AGE", "18")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k = f.Section("parent.child.son").Key("AGE")
So(k, ShouldNotBeNil)
So(k.Value(), ShouldEqual, "18")
})
})
}
func TestSection_Keys(t *testing.T) {
Convey("Get all keys in a section", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("").NewKey("VERSION", "v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
keys := f.Section("").Keys()
names := []string{"NAME", "VERSION", "IMPORT_PATH"}
So(len(keys), ShouldEqual, len(names))
for i, name := range names {
So(keys[i].Name(), ShouldEqual, name)
}
})
}
func TestSection_ParentKeys(t *testing.T) {
Convey("Get all keys of parent sections", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("package").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("package").NewKey("VERSION", "v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("package").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
keys := f.Section("package.sub.sub2").ParentKeys()
names := []string{"NAME", "VERSION", "IMPORT_PATH"}
So(len(keys), ShouldEqual, len(names))
for i, name := range names {
So(keys[i].Name(), ShouldEqual, name)
}
})
}
func TestSection_KeyStrings(t *testing.T) {
Convey("Get all key names in a section", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("").NewKey("VERSION", "v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(f.Section("").KeyStrings(), ShouldResemble, []string{"NAME", "VERSION", "IMPORT_PATH"})
})
}
func TestSection_KeyHash(t *testing.T) {
Convey("Get clone of key hash", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("").NewKey("VERSION", "v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
hash := f.Section("").KeysHash()
relation := map[string]string{
"NAME": "ini",
"VERSION": "v1",
"IMPORT_PATH": "gopkg.in/ini.v1",
}
for k, v := range hash {
So(v, ShouldEqual, relation[k])
}
})
}
func TestSection_DeleteKey(t *testing.T) {
Convey("Delete a key", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(f.Section("").HasKey("NAME"), ShouldBeTrue)
f.Section("").DeleteKey("NAME")
So(f.Section("").HasKey("NAME"), ShouldBeFalse)
})
}

16
vendor/github.com/go-ini/ini/struct.go сгенерированный поставляемый
Просмотреть файл

@@ -113,7 +113,7 @@ func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowSh
default: default:
return fmt.Errorf("unsupported type '[]%s'", sliceOf) return fmt.Errorf("unsupported type '[]%s'", sliceOf)
} }
if isStrict { if err != nil && isStrict {
return err return err
} }
@@ -166,7 +166,7 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
durationVal, err := key.Duration() durationVal, err := key.Duration()
// Skip zero value // Skip zero value
if err == nil && int(durationVal) > 0 { if err == nil && int64(durationVal) > 0 {
field.Set(reflect.ValueOf(durationVal)) field.Set(reflect.ValueOf(durationVal))
return nil return nil
} }
@@ -450,6 +450,12 @@ func (s *Section) reflectFrom(val reflect.Value) error {
// Note: fieldName can never be empty here, ignore error. // Note: fieldName can never be empty here, ignore error.
sec, _ = s.f.NewSection(fieldName) sec, _ = s.f.NewSection(fieldName)
} }
// Add comment from comment tag
if len(sec.Comment) == 0 {
sec.Comment = tpField.Tag.Get("comment")
}
if err = sec.reflectFrom(field); err != nil { if err = sec.reflectFrom(field); err != nil {
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err) return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
} }
@@ -461,6 +467,12 @@ func (s *Section) reflectFrom(val reflect.Value) error {
if err != nil { if err != nil {
key, _ = s.NewKey(fieldName, "") key, _ = s.NewKey(fieldName, "")
} }
// Add comment from comment tag
if len(key.Comment) == 0 {
key.Comment = tpField.Tag.Get("comment")
}
if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil { if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err) return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
} }

99
vendor/github.com/go-ini/ini/struct_test.go сгенерированный поставляемый
Просмотреть файл

@@ -12,7 +12,7 @@
// License for the specific language governing permissions and limitations // License for the specific language governing permissions and limitations
// under the License. // under the License.
package ini package ini_test
import ( import (
"bytes" "bytes"
@@ -22,6 +22,7 @@ import (
"time" "time"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/ini.v1"
) )
type testNested struct { type testNested struct {
@@ -126,11 +127,11 @@ Born = nil
Cities = Cities =
` `
func Test_Struct(t *testing.T) { func Test_MapToStruct(t *testing.T) {
Convey("Map to struct", t, func() { Convey("Map to struct", t, func() {
Convey("Map file to struct", func() { Convey("Map file to struct", func() {
ts := new(testStruct) ts := new(testStruct)
So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil) So(ini.MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)
So(ts.Name, ShouldEqual, "Unknwon") So(ts.Name, ShouldEqual, "Unknwon")
So(ts.Age, ShouldEqual, 21) So(ts.Age, ShouldEqual, 21)
@@ -159,7 +160,7 @@ func Test_Struct(t *testing.T) {
Convey("Map section to struct", func() { Convey("Map section to struct", func() {
foobar := new(fooBar) foobar := new(fooBar)
f, err := Load([]byte(_CONF_DATA_STRUCT)) f, err := ini.Load([]byte(_CONF_DATA_STRUCT))
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(f.Section("foo.bar").MapTo(foobar), ShouldBeNil) So(f.Section("foo.bar").MapTo(foobar), ShouldBeNil)
@@ -168,58 +169,58 @@ func Test_Struct(t *testing.T) {
}) })
Convey("Map to non-pointer struct", func() { Convey("Map to non-pointer struct", func() {
cfg, err := Load([]byte(_CONF_DATA_STRUCT)) f, err := ini.Load([]byte(_CONF_DATA_STRUCT))
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil) So(f, ShouldNotBeNil)
So(cfg.MapTo(testStruct{}), ShouldNotBeNil) So(f.MapTo(testStruct{}), ShouldNotBeNil)
}) })
Convey("Map to unsupported type", func() { Convey("Map to unsupported type", func() {
cfg, err := Load([]byte(_CONF_DATA_STRUCT)) f, err := ini.Load([]byte(_CONF_DATA_STRUCT))
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil) So(f, ShouldNotBeNil)
cfg.NameMapper = func(raw string) string { f.NameMapper = func(raw string) string {
if raw == "Byte" { if raw == "Byte" {
return "NAME" return "NAME"
} }
return raw return raw
} }
So(cfg.MapTo(&unsupport{}), ShouldNotBeNil) So(f.MapTo(&unsupport{}), ShouldNotBeNil)
So(cfg.MapTo(&unsupport2{}), ShouldNotBeNil) So(f.MapTo(&unsupport2{}), ShouldNotBeNil)
So(cfg.MapTo(&unsupport4{}), ShouldNotBeNil) So(f.MapTo(&unsupport4{}), ShouldNotBeNil)
}) })
Convey("Map to omitempty field", func() { Convey("Map to omitempty field", func() {
ts := new(testStruct) ts := new(testStruct)
So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil) So(ini.MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)
So(ts.Omitted, ShouldEqual, true) So(ts.Omitted, ShouldEqual, true)
}) })
Convey("Map with shadows", func() { Convey("Map with shadows", func() {
cfg, err := LoadSources(LoadOptions{AllowShadows: true}, []byte(_CONF_DATA_STRUCT)) f, err := ini.LoadSources(ini.LoadOptions{AllowShadows: true}, []byte(_CONF_DATA_STRUCT))
So(err, ShouldBeNil) So(err, ShouldBeNil)
ts := new(testStruct) ts := new(testStruct)
So(cfg.MapTo(ts), ShouldBeNil) So(f.MapTo(ts), ShouldBeNil)
So(strings.Join(ts.Shadows, " "), ShouldEqual, "1 2 3 4") So(strings.Join(ts.Shadows, " "), ShouldEqual, "1 2 3 4")
So(fmt.Sprintf("%v", ts.ShadowInts), ShouldEqual, "[1 2 3 4]") So(fmt.Sprintf("%v", ts.ShadowInts), ShouldEqual, "[1 2 3 4]")
}) })
Convey("Map from invalid data source", func() { Convey("Map from invalid data source", func() {
So(MapTo(&testStruct{}, "hi"), ShouldNotBeNil) So(ini.MapTo(&testStruct{}, "hi"), ShouldNotBeNil)
}) })
Convey("Map to wrong types and gain default values", func() { Convey("Map to wrong types and gain default values", func() {
cfg, err := Load([]byte(_INVALID_DATA_CONF_STRUCT)) f, err := ini.Load([]byte(_INVALID_DATA_CONF_STRUCT))
So(err, ShouldBeNil) So(err, ShouldBeNil)
t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z") t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
So(err, ShouldBeNil) So(err, ShouldBeNil)
dv := &defaultValue{"Joe", 10, true, 1.25, t, []string{"HangZhou", "Boston"}} dv := &defaultValue{"Joe", 10, true, 1.25, t, []string{"HangZhou", "Boston"}}
So(cfg.MapTo(dv), ShouldBeNil) So(f.MapTo(dv), ShouldBeNil)
So(dv.Name, ShouldEqual, "Joe") So(dv.Name, ShouldEqual, "Joe")
So(dv.Age, ShouldEqual, 10) So(dv.Age, ShouldEqual, 10)
So(dv.Male, ShouldBeTrue) So(dv.Male, ShouldBeTrue)
@@ -230,7 +231,7 @@ func Test_Struct(t *testing.T) {
}) })
Convey("Map to struct in strict mode", t, func() { Convey("Map to struct in strict mode", t, func() {
cfg, err := Load([]byte(` f, err := ini.Load([]byte(`
name=bruce name=bruce
age=a30`)) age=a30`))
So(err, ShouldBeNil) So(err, ShouldBeNil)
@@ -241,12 +242,28 @@ age=a30`))
} }
s := new(Strict) s := new(Strict)
So(cfg.Section("").StrictMapTo(s), ShouldNotBeNil) So(f.Section("").StrictMapTo(s), ShouldNotBeNil)
}) })
Convey("Map slice in strict mode", t, func() {
f, err := ini.Load([]byte(`
names=alice, bruce`))
So(err, ShouldBeNil)
type Strict struct {
Names []string `ini:"names"`
}
s := new(Strict)
So(f.Section("").StrictMapTo(s), ShouldBeNil)
So(fmt.Sprint(s.Names), ShouldEqual, "[alice bruce]")
})
}
func Test_ReflectFromStruct(t *testing.T) {
Convey("Reflect from struct", t, func() { Convey("Reflect from struct", t, func() {
type Embeded struct { type Embeded struct {
Dates []time.Time `delim:"|"` Dates []time.Time `delim:"|" comment:"Time data"`
Places []string Places []string
Years []int Years []int
Numbers []int64 Numbers []int64
@@ -258,12 +275,12 @@ age=a30`))
type Author struct { type Author struct {
Name string `ini:"NAME"` Name string `ini:"NAME"`
Male bool Male bool
Age int Age int `comment:"Author's age"`
Height uint Height uint
GPA float64 GPA float64
Date time.Time Date time.Time
NeverMind string `ini:"-"` NeverMind string `ini:"-"`
*Embeded `ini:"infos"` *Embeded `ini:"infos" comment:"Embeded section"`
} }
t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z") t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
@@ -279,20 +296,23 @@ age=a30`))
[]float64{192.168, 10.11}, []float64{192.168, 10.11},
[]int{}, []int{},
}} }}
cfg := Empty() cfg := ini.Empty()
So(ReflectFrom(cfg, a), ShouldBeNil) So(ini.ReflectFrom(cfg, a), ShouldBeNil)
var buf bytes.Buffer var buf bytes.Buffer
_, err = cfg.WriteTo(&buf) _, err = cfg.WriteTo(&buf)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `NAME = Unknwon So(buf.String(), ShouldEqual, `NAME = Unknwon
Male = true Male = true
; Author's age
Age = 21 Age = 21
Height = 100 Height = 100
GPA = 2.8 GPA = 2.8
Date = 1993-10-07T20:17:05Z Date = 1993-10-07T20:17:05Z
; Embeded section
[infos] [infos]
; Time data
Dates = 1993-10-07T20:17:05Z|1993-10-07T20:17:05Z Dates = 1993-10-07T20:17:05Z|1993-10-07T20:17:05Z
Places = HangZhou,Boston Places = HangZhou,Boston
Years = 1993,1994 Years = 1993,1994
@@ -305,11 +325,11 @@ None =
`) `)
Convey("Reflect from non-point struct", func() { Convey("Reflect from non-point struct", func() {
So(ReflectFrom(cfg, Author{}), ShouldNotBeNil) So(ini.ReflectFrom(cfg, Author{}), ShouldNotBeNil)
}) })
Convey("Reflect from struct with omitempty", func() { Convey("Reflect from struct with omitempty", func() {
cfg := Empty() cfg := ini.Empty()
type SpecialStruct struct { type SpecialStruct struct {
FirstName string `ini:"first_name"` FirstName string `ini:"first_name"`
LastName string `ini:"last_name"` LastName string `ini:"last_name"`
@@ -319,7 +339,7 @@ None =
NotEmpty int `ini:"omitempty"` NotEmpty int `ini:"omitempty"`
} }
So(ReflectFrom(cfg, &SpecialStruct{FirstName: "John", LastName: "Doe", NotEmpty: 9}), ShouldBeNil) So(ini.ReflectFrom(cfg, &SpecialStruct{FirstName: "John", LastName: "Doe", NotEmpty: 9}), ShouldBeNil)
var buf bytes.Buffer var buf bytes.Buffer
_, err = cfg.WriteTo(&buf) _, err = cfg.WriteTo(&buf)
@@ -338,15 +358,30 @@ type testMapper struct {
func Test_NameGetter(t *testing.T) { func Test_NameGetter(t *testing.T) {
Convey("Test name mappers", t, func() { Convey("Test name mappers", t, func() {
So(MapToWithMapper(&testMapper{}, TitleUnderscore, []byte("packag_name=ini")), ShouldBeNil) So(ini.MapToWithMapper(&testMapper{}, ini.TitleUnderscore, []byte("packag_name=ini")), ShouldBeNil)
cfg, err := Load([]byte("PACKAGE_NAME=ini")) cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil) So(cfg, ShouldNotBeNil)
cfg.NameMapper = AllCapsUnderscore cfg.NameMapper = ini.AllCapsUnderscore
tg := new(testMapper) tg := new(testMapper)
So(cfg.MapTo(tg), ShouldBeNil) So(cfg.MapTo(tg), ShouldBeNil)
So(tg.PackageName, ShouldEqual, "ini") So(tg.PackageName, ShouldEqual, "ini")
}) })
} }
type testDurationStruct struct {
Duration time.Duration `ini:"Duration"`
}
func Test_Duration(t *testing.T) {
Convey("Duration less than 16m50s", t, func() {
ds := new(testDurationStruct)
So(ini.MapTo(ds, []byte("Duration=16m49s")), ShouldBeNil)
dur, err := time.ParseDuration("16m49s")
So(err, ShouldBeNil)
So(ds.Duration.Seconds(), ShouldEqual, dur.Seconds())
})
}

11
vendor/github.com/go-ini/ini/testdata/aicc.ini сгенерированный поставляемый
Просмотреть файл

@@ -1,11 +0,0 @@
[Core]
Lesson_Location = 87
Lesson_Status = C
Score = 3
Time = 00:02:30
[CORE_LESSON]
my lesson state data – 1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000 – end my lesson state data
[COMMENTS]
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>

83
vendor/github.com/go-ini/ini/testdata/full.ini сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,83 @@
; Package name
NAME = ini
; Package version
VERSION = v1
; Package import path
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
# Information about package author
# Bio can be written in multiple lines.
[author]
NAME = Unknwon
E-MAIL = u@gogs.io
GITHUB = https://github.com/%(NAME)s
BIO = """Gopher.
Coding addict.
Good man.
""" # Succeeding comment
[package]
CLONE_URL = https://%(IMPORT_PATH)s
[package.sub]
UNUSED_KEY = should be deleted
[features]
-: Support read/write comments of keys and sections
-: Support auto-increment of key names
-: Support load multiple files to overwrite key values
[types]
STRING = str
BOOL = true
BOOL_FALSE = false
FLOAT64 = 1.25
INT = 10
TIME = 2015-01-01T20:17:05Z
DURATION = 2h45m
UINT = 3
[array]
STRINGS = en, zh, de
FLOAT64S = 1.1, 2.2, 3.3
INTS = 1, 2, 3
UINTS = 1, 2, 3
TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
[note]
empty_lines = next line is empty\
; Comment before the section
[comments] ; This is a comment for the section too
; Comment before key
key = "value"
key2 = "value2" ; This is a comment for key2
key3 = "one", "two", "three"
[string escapes]
key1 = value1, value2, value3
key2 = value1\, value2
key3 = val\ue1, value2
key4 = value1\\, value\\\\2
key5 = value1\,, value2
key6 = aaa bbb\ and\ space ccc
[advance]
value with quotes = "some value"
value quote2 again = 'some value'
includes comment sign = `my#password`
includes comment sign2 = `my;password`
true = 2+3=5
"1+1=2" = true
"""6+1=7""" = true
"""`5+5`""" = 10
`"6+6"` = 12
`7-2=4` = false
ADDRESS = `404 road,
NotFound, State, 50000`
two_lines = how about \
continuation lines?
lots_of_lines = 1 \
2 \
3 \
4 \

Просмотреть файл

5
vendor/github.com/go-redis/redis/commands.go сгенерированный поставляемый
Просмотреть файл

@@ -214,6 +214,7 @@ type Cmdable interface {
ScriptKill() *StatusCmd ScriptKill() *StatusCmd
ScriptLoad(script string) *StringCmd ScriptLoad(script string) *StringCmd
DebugObject(key string) *StringCmd DebugObject(key string) *StringCmd
Publish(channel string, message interface{}) *IntCmd
PubSubChannels(pattern string) *StringSliceCmd PubSubChannels(pattern string) *StringSliceCmd
PubSubNumSub(channels ...string) *StringIntMapCmd PubSubNumSub(channels ...string) *StringIntMapCmd
PubSubNumPat() *IntCmd PubSubNumPat() *IntCmd
@@ -1880,8 +1881,8 @@ func (c *cmdable) DebugObject(key string) *StringCmd {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Publish posts the message to the channel. // Publish posts the message to the channel.
func (c *cmdable) Publish(channel, message string) *IntCmd { func (c *cmdable) Publish(channel string, message interface{}) *IntCmd {
cmd := NewIntCmd("PUBLISH", channel, message) cmd := NewIntCmd("publish", channel, message)
c.process(cmd) c.process(cmd)
return cmd return cmd
} }

19
vendor/github.com/go-redis/redis/internal/pool/pool.go сгенерированный поставляемый
Просмотреть файл

@@ -60,8 +60,10 @@ type Options struct {
type ConnPool struct { type ConnPool struct {
opt *Options opt *Options
dialErrorsNum uint32 // atomic dialErrorsNum uint32 // atomic
_lastDialError atomic.Value
lastDialError error
lastDialErrorMu sync.RWMutex
queue chan struct{} queue chan struct{}
@@ -98,7 +100,7 @@ func (p *ConnPool) NewConn() (*Conn, error) {
} }
if atomic.LoadUint32(&p.dialErrorsNum) >= uint32(p.opt.PoolSize) { if atomic.LoadUint32(&p.dialErrorsNum) >= uint32(p.opt.PoolSize) {
return nil, p.lastDialError() return nil, p.getLastDialError()
} }
netConn, err := p.opt.Dialer() netConn, err := p.opt.Dialer()
@@ -138,11 +140,16 @@ func (p *ConnPool) tryDial() {
} }
func (p *ConnPool) setLastDialError(err error) { func (p *ConnPool) setLastDialError(err error) {
p._lastDialError.Store(err) p.lastDialErrorMu.Lock()
p.lastDialError = err
p.lastDialErrorMu.Unlock()
} }
func (p *ConnPool) lastDialError() error { func (p *ConnPool) getLastDialError() error {
return p._lastDialError.Load().(error) p.lastDialErrorMu.RLock()
err := p.lastDialError
p.lastDialErrorMu.RUnlock()
return err
} }
// Get returns existed connection from the pool or creates a new one. // Get returns existed connection from the pool or creates a new one.

3
vendor/github.com/go-redis/redis/internal/proto/scan.go сгенерированный поставляемый
Просмотреть файл

@@ -120,8 +120,9 @@ func ScanSlice(data []string, slice interface{}) error {
return fmt.Errorf("redis: ScanSlice(non-slice %T)", slice) return fmt.Errorf("redis: ScanSlice(non-slice %T)", slice)
} }
next := internal.MakeSliceNextElemFunc(v)
for i, s := range data { for i, s := range data {
elem := internal.SliceNextElem(v) elem := next()
if err := Scan(internal.StringToBytes(s), elem.Addr().Interface()); err != nil { if err := Scan(internal.StringToBytes(s), elem.Addr().Interface()); err != nil {
return fmt.Errorf("redis: ScanSlice(index=%d value=%q) failed: %s", i, s, err) return fmt.Errorf("redis: ScanSlice(index=%d value=%q) failed: %s", i, s, err)
} }

37
vendor/github.com/go-redis/redis/internal/util.go сгенерированный поставляемый
Просмотреть файл

@@ -28,20 +28,35 @@ func isLower(s string) bool {
return true return true
} }
func SliceNextElem(v reflect.Value) reflect.Value { func MakeSliceNextElemFunc(v reflect.Value) func() reflect.Value {
if v.Len() < v.Cap() {
v.Set(v.Slice(0, v.Len()+1))
return v.Index(v.Len() - 1)
}
elemType := v.Type().Elem() elemType := v.Type().Elem()
if elemType.Kind() == reflect.Ptr { if elemType.Kind() == reflect.Ptr {
elem := reflect.New(elemType.Elem()) elemType = elemType.Elem()
v.Set(reflect.Append(v, elem)) return func() reflect.Value {
return elem.Elem() if v.Len() < v.Cap() {
v.Set(v.Slice(0, v.Len()+1))
elem := v.Index(v.Len() - 1)
if elem.IsNil() {
elem.Set(reflect.New(elemType))
}
return elem.Elem()
}
elem := reflect.New(elemType)
v.Set(reflect.Append(v, elem))
return elem.Elem()
}
} }
v.Set(reflect.Append(v, reflect.Zero(elemType))) zero := reflect.Zero(elemType)
return v.Index(v.Len() - 1) return func() reflect.Value {
if v.Len() < v.Cap() {
v.Set(v.Slice(0, v.Len()+1))
return v.Index(v.Len() - 1)
}
v.Set(reflect.Append(v, zero))
return v.Index(v.Len() - 1)
}
} }

36
vendor/github.com/go-redis/redis/pubsub.go сгенерированный поставляемый
Просмотреть файл

@@ -29,6 +29,9 @@ type PubSub struct {
closed bool closed bool
cmd *Cmd cmd *Cmd
chOnce sync.Once
ch chan *Message
} }
func (c *PubSub) conn() (*pool.Conn, error) { func (c *PubSub) conn() (*pool.Conn, error) {
@@ -346,24 +349,27 @@ func (c *PubSub) receiveMessage(timeout time.Duration) (*Message, error) {
} }
} }
// Channel returns a channel for concurrently receiving messages. // Channel returns a Go channel for concurrently receiving messages.
// The channel is closed with PubSub. // The channel is closed with PubSub. Receive or ReceiveMessage APIs
// can not be used after channel is created.
func (c *PubSub) Channel() <-chan *Message { func (c *PubSub) Channel() <-chan *Message {
ch := make(chan *Message, 100) c.chOnce.Do(func() {
go func() { c.ch = make(chan *Message, 100)
for { go func() {
msg, err := c.ReceiveMessage() for {
if err != nil { msg, err := c.ReceiveMessage()
if err == pool.ErrClosed { if err != nil {
break if err == pool.ErrClosed {
break
}
continue
} }
continue c.ch <- msg
} }
ch <- msg close(c.ch)
} }()
close(ch) })
}() return c.ch
return ch
} }
func appendIfNotExists(ss []string, es ...string) []string { func appendIfNotExists(ss []string, es ...string) []string {

16
vendor/github.com/go-redis/redis/pubsub_test.go сгенерированный поставляемый
Просмотреть файл

@@ -424,4 +424,20 @@ var _ = Describe("PubSub", func() {
wg.Wait() wg.Wait()
}) })
It("handles big message payload", func() {
pubsub := client.Subscribe("mychannel")
defer pubsub.Close()
ch := pubsub.Channel()
bigVal := bigVal()
err := client.Publish("mychannel", bigVal).Err()
Expect(err).NotTo(HaveOccurred())
var msg *redis.Message
Eventually(ch).Should(Receive(&msg))
Expect(msg.Channel).To(Equal("mychannel"))
Expect(msg.Payload).To(Equal(string(bigVal)))
})
}) })

9
vendor/github.com/go-redis/redis/race_test.go сгенерированный поставляемый
Просмотреть файл

@@ -105,7 +105,7 @@ var _ = Describe("races", func() {
It("should handle big vals in Get", func() { It("should handle big vals in Get", func() {
C, N = 4, 100 C, N = 4, 100
bigVal := bytes.Repeat([]byte{'*'}, 1<<17) // 128kb bigVal := bigVal()
err := client.Set("key", bigVal, 0).Err() err := client.Set("key", bigVal, 0).Err()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@@ -126,8 +126,7 @@ var _ = Describe("races", func() {
It("should handle big vals in Set", func() { It("should handle big vals in Set", func() {
C, N = 4, 100 C, N = 4, 100
bigVal := bytes.Repeat([]byte{'*'}, 1<<17) // 128kb bigVal := bigVal()
perform(C, func(id int) { perform(C, func(id int) {
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
err := client.Set("key", bigVal, 0).Err() err := client.Set("key", bigVal, 0).Err()
@@ -245,3 +244,7 @@ var _ = Describe("races", func() {
Expect(n).To(Equal(int64(N))) Expect(n).To(Equal(int64(N)))
}) })
}) })
func bigVal() []byte {
return bytes.Repeat([]byte{'*'}, 1<<17) // 128kb
}

1
vendor/github.com/golang/protobuf/README.md сгенерированный поставляемый
Просмотреть файл

@@ -1,6 +1,7 @@
# Go support for Protocol Buffers # Go support for Protocol Buffers
[![Build Status](https://travis-ci.org/golang/protobuf.svg?branch=master)](https://travis-ci.org/golang/protobuf) [![Build Status](https://travis-ci.org/golang/protobuf.svg?branch=master)](https://travis-ci.org/golang/protobuf)
[![GoDoc](https://godoc.org/github.com/golang/protobuf?status.svg)](https://godoc.org/github.com/golang/protobuf)
Google's data interchange format. Google's data interchange format.
Copyright 2010 The Go Authors. Copyright 2010 The Go Authors.

2
vendor/github.com/gorilla/handlers/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -7,6 +7,7 @@ matrix:
- go: 1.5 - go: 1.5
- go: 1.6 - go: 1.6
- go: 1.7 - go: 1.7
- go: 1.8
- go: tip - go: tip
allow_failures: allow_failures:
- go: tip - go: tip
@@ -16,3 +17,4 @@ script:
- diff -u <(echo -n) <(gofmt -d .) - diff -u <(echo -n) <(gofmt -d .)
- go vet $(go list ./... | grep -v /vendor/) - go vet $(go list ./... | grep -v /vendor/)
- go test -v -race ./... - go test -v -race ./...

12
vendor/github.com/gorilla/handlers/cors.go сгенерированный поставляемый
Просмотреть файл

@@ -110,7 +110,17 @@ func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set(corsVaryHeader, corsOriginHeader) w.Header().Set(corsVaryHeader, corsOriginHeader)
} }
w.Header().Set(corsAllowOriginHeader, origin) returnOrigin := origin
for _, o := range ch.allowedOrigins {
// A configuration of * is different than explicitly setting an allowed
// origin. Returning arbitrary origin headers an an access control allow
// origin header is unsafe and is not required by any use case.
if o == corsOriginMatchAll {
returnOrigin = "*"
break
}
}
w.Header().Set(corsAllowOriginHeader, returnOrigin)
if r.Method == corsOptionMethod { if r.Method == corsOptionMethod {
return return

37
vendor/github.com/gorilla/handlers/cors_test.go сгенерированный поставляемый
Просмотреть файл

@@ -327,10 +327,45 @@ func TestCORSHandlerWithCustomValidator(t *testing.T) {
return false return false
} }
CORS(AllowedOriginValidator(originValidator))(testHandler).ServeHTTP(rr, r) // Specially craft a CORS object.
handleFunc := func(h http.Handler) http.Handler {
c := &cors{
allowedMethods: defaultCorsMethods,
allowedHeaders: defaultCorsHeaders,
allowedOrigins: []string{"http://a.example.com"},
h: h,
}
AllowedOriginValidator(originValidator)(c)
return c
}
handleFunc(testHandler).ServeHTTP(rr, r)
header := rr.HeaderMap.Get(corsAllowOriginHeader) header := rr.HeaderMap.Get(corsAllowOriginHeader)
if header != r.URL.String() { if header != r.URL.String() {
t.Fatalf("bad header: expected %s to be %s, got %s.", corsAllowOriginHeader, r.URL.String(), header) t.Fatalf("bad header: expected %s to be %s, got %s.", corsAllowOriginHeader, r.URL.String(), header)
} }
} }
func TestCORSAllowStar(t *testing.T) {
r := newRequest("GET", "http://a.example.com")
r.Header.Set("Origin", r.URL.String())
rr := httptest.NewRecorder()
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
originValidator := func(origin string) bool {
if strings.HasSuffix(origin, ".example.com") {
return true
}
return false
}
CORS(AllowedOriginValidator(originValidator))(testHandler).ServeHTTP(rr, r)
header := rr.HeaderMap.Get(corsAllowOriginHeader)
// Because * is the default CORS policy (which is safe), we should be
// expect a * returned here as the Access Control Allow Origin header
if header != "*" {
t.Fatalf("bad header: expected %s to be %s, got %s.", corsAllowOriginHeader, r.URL.String(), header)
}
}

6
vendor/github.com/gorilla/mux/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -3,13 +3,13 @@ sudo: false
matrix: matrix:
include: include:
- go: 1.2
- go: 1.3
- go: 1.4
- go: 1.5 - go: 1.5
- go: 1.6 - go: 1.6
- go: 1.7 - go: 1.7
- go: 1.8 - go: 1.8
- go: 1.9
- go: tip
allow_failures:
- go: tip - go: tip
install: install:

36
vendor/github.com/gorilla/mux/README.md сгенерированный поставляемый
Просмотреть файл

@@ -135,6 +135,14 @@ r.HandleFunc("/products", ProductsHandler).
Schemes("http") Schemes("http")
``` ```
Routes are tested in the order they were added to the router. If two routes match, the first one wins:
```go
r := mux.NewRouter()
r.HandleFunc("/specific", specificHandler)
r.PathPrefix("/").Handler(catchAllHandler)
```
Setting the same matching conditions again and again can be boring, so we have a way to group several routes that share the same requirements. We call it "subrouting". Setting the same matching conditions again and again can be boring, so we have a way to group several routes that share the same requirements. We call it "subrouting".
For example, let's say we have several URLs that should only match when the host is `www.example.com`. Create a route for that host and get a "subrouter" from it: For example, let's say we have several URLs that should only match when the host is `www.example.com`. Create a route for that host and get a "subrouter" from it:
@@ -193,22 +201,34 @@ func main() {
r.HandleFunc("/products", handler).Methods("POST") r.HandleFunc("/products", handler).Methods("POST")
r.HandleFunc("/articles", handler).Methods("GET") r.HandleFunc("/articles", handler).Methods("GET")
r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT") r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
t, err := route.GetPathTemplate() t, err := route.GetPathTemplate()
if err != nil { if err != nil {
return err return err
} }
qt, err := route.GetQueriesTemplates()
if err != nil {
return err
}
// p will contain regular expression is compatible with regular expression in Perl, Python, and other languages. // p will contain regular expression is compatible with regular expression in Perl, Python, and other languages.
// for instance the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$' // for instance the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$'
p, err := route.GetPathRegexp() p, err := route.GetPathRegexp()
if err != nil { if err != nil {
return err return err
} }
// qr will contain a list of regular expressions with the same semantics as GetPathRegexp,
// just applied to the Queries pairs instead, e.g., 'Queries("surname", "{surname}") will return
// {"^surname=(?P<v0>.*)$}. Where each combined query pair will have an entry in the list.
qr, err := route.GetQueriesRegexp()
if err != nil {
return err
}
m, err := route.GetMethods() m, err := route.GetMethods()
if err != nil { if err != nil {
return err return err
} }
fmt.Println(strings.Join(m, ","), t, p) fmt.Println(strings.Join(m, ","), strings.Join(qt, ","), strings.Join(qr, ","), t, p)
return nil return nil
}) })
http.Handle("/", r) http.Handle("/", r)
@@ -331,22 +351,34 @@ r.HandleFunc("/", handler)
r.HandleFunc("/products", handler).Methods("POST") r.HandleFunc("/products", handler).Methods("POST")
r.HandleFunc("/articles", handler).Methods("GET") r.HandleFunc("/articles", handler).Methods("GET")
r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT") r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
t, err := route.GetPathTemplate() t, err := route.GetPathTemplate()
if err != nil { if err != nil {
return err return err
} }
qt, err := route.GetQueriesTemplates()
if err != nil {
return err
}
// p will contain a regular expression that is compatible with regular expressions in Perl, Python, and other languages. // p will contain a regular expression that is compatible with regular expressions in Perl, Python, and other languages.
// For example, the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$'. // For example, the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$'.
p, err := route.GetPathRegexp() p, err := route.GetPathRegexp()
if err != nil { if err != nil {
return err return err
} }
// qr will contain a list of regular expressions with the same semantics as GetPathRegexp,
// just applied to the Queries pairs instead, e.g., 'Queries("surname", "{surname}") will return
// {"^surname=(?P<v0>.*)$}. Where each combined query pair will have an entry in the list.
qr, err := route.GetQueriesRegexp()
if err != nil {
return err
}
m, err := route.GetMethods() m, err := route.GetMethods()
if err != nil { if err != nil {
return err return err
} }
fmt.Println(strings.Join(m, ","), t, p) fmt.Println(strings.Join(m, ","), strings.Join(qt, ","), strings.Join(qr, ","), t, p)
return nil return nil
}) })
``` ```

51
vendor/github.com/gorilla/mux/mux.go сгенерированный поставляемый
Просмотреть файл

@@ -10,11 +10,11 @@ import (
"net/http" "net/http"
"path" "path"
"regexp" "regexp"
"strings"
) )
var ( var (
ErrMethodMismatch = errors.New("method is not allowed") ErrMethodMismatch = errors.New("method is not allowed")
ErrNotFound = errors.New("no matching route was found")
) )
// NewRouter returns a new router instance. // NewRouter returns a new router instance.
@@ -65,7 +65,17 @@ type Router struct {
useEncodedPath bool useEncodedPath bool
} }
// Match matches registered routes against the request. // Match attempts to match the given request against the router's registered routes.
//
// If the request matches a route of this router or one of its subrouters the Route,
// Handler, and Vars fields of the the match argument are filled and this function
// returns true.
//
// If the request does not match any of this router's or its subrouters' routes
// then this function returns false. If available, a reason for the match failure
// will be filled in the match argument's MatchErr field. If the match failure type
// (eg: not found) has a registered handler, the handler is assigned to the Handler
// field of the match argument.
func (r *Router) Match(req *http.Request, match *RouteMatch) bool { func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
for _, route := range r.routes { for _, route := range r.routes {
if route.Match(req, match) { if route.Match(req, match) {
@@ -73,16 +83,23 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
} }
} }
if match.MatchErr == ErrMethodMismatch && r.MethodNotAllowedHandler != nil { if match.MatchErr == ErrMethodMismatch {
match.Handler = r.MethodNotAllowedHandler if r.MethodNotAllowedHandler != nil {
return true match.Handler = r.MethodNotAllowedHandler
return true
} else {
return false
}
} }
// Closest match for a router (includes sub-routers) // Closest match for a router (includes sub-routers)
if r.NotFoundHandler != nil { if r.NotFoundHandler != nil {
match.Handler = r.NotFoundHandler match.Handler = r.NotFoundHandler
match.MatchErr = ErrNotFound
return true return true
} }
match.MatchErr = ErrNotFound
return false return false
} }
@@ -94,7 +111,7 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if !r.skipClean { if !r.skipClean {
path := req.URL.Path path := req.URL.Path
if r.useEncodedPath { if r.useEncodedPath {
path = getPath(req) path = req.URL.EscapedPath()
} }
// Clean path to canonical form and redirect. // Clean path to canonical form and redirect.
if p := cleanPath(path); p != path { if p := cleanPath(path); p != path {
@@ -409,28 +426,6 @@ func setCurrentRoute(r *http.Request, val interface{}) *http.Request {
// Helpers // Helpers
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// getPath returns the escaped path if possible; doing what URL.EscapedPath()
// which was added in go1.5 does
func getPath(req *http.Request) string {
if req.RequestURI != "" {
// Extract the path from RequestURI (which is escaped unlike URL.Path)
// as detailed here as detailed in https://golang.org/pkg/net/url/#URL
// for < 1.5 server side workaround
// http://localhost/path/here?v=1 -> /path/here
path := req.RequestURI
path = strings.TrimPrefix(path, req.URL.Scheme+`://`)
path = strings.TrimPrefix(path, req.URL.Host)
if i := strings.LastIndex(path, "?"); i > -1 {
path = path[:i]
}
if i := strings.LastIndex(path, "#"); i > -1 {
path = path[:i]
}
return path
}
return req.URL.Path
}
// cleanPath returns the canonical path for p, eliminating . and .. elements. // cleanPath returns the canonical path for p, eliminating . and .. elements.
// Borrowed from the net/http package. // Borrowed from the net/http package.
func cleanPath(p string) string { func cleanPath(p string) string {

627
vendor/github.com/gorilla/mux/mux_test.go сгенерированный поставляемый
Просмотреть файл

@@ -29,20 +29,22 @@ func (r *routeRegexp) GoString() string {
} }
type routeTest struct { type routeTest struct {
title string // title of the test title string // title of the test
route *Route // the route being tested route *Route // the route being tested
request *http.Request // a request to test the route request *http.Request // a request to test the route
vars map[string]string // the expected vars of the match vars map[string]string // the expected vars of the match
scheme string // the expected scheme of the built URL scheme string // the expected scheme of the built URL
host string // the expected host of the built URL host string // the expected host of the built URL
path string // the expected path of the built URL path string // the expected path of the built URL
query string // the expected query string of the built URL query string // the expected query string of the built URL
pathTemplate string // the expected path template of the route pathTemplate string // the expected path template of the route
hostTemplate string // the expected host template of the route hostTemplate string // the expected host template of the route
methods []string // the expected route methods queriesTemplate string // the expected query template of the route
pathRegexp string // the expected path regexp methods []string // the expected route methods
shouldMatch bool // whether the request is expected to match the route at all pathRegexp string // the expected path regexp
shouldRedirect bool // whether the request should result in a redirect queriesRegexp string // the expected query regexp
shouldMatch bool // whether the request is expected to match the route at all
shouldRedirect bool // whether the request should result in a redirect
} }
func TestHost(t *testing.T) { func TestHost(t *testing.T) {
@@ -739,257 +741,309 @@ func TestMethods(t *testing.T) {
func TestQueries(t *testing.T) { func TestQueries(t *testing.T) {
tests := []routeTest{ tests := []routeTest{
{ {
title: "Queries route, match", title: "Queries route, match",
route: new(Route).Queries("foo", "bar", "baz", "ding"), route: new(Route).Queries("foo", "bar", "baz", "ding"),
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
query: "foo=bar&baz=ding", query: "foo=bar&baz=ding",
shouldMatch: true, queriesTemplate: "foo=bar,baz=ding",
queriesRegexp: "^foo=bar$,^baz=ding$",
shouldMatch: true,
}, },
{ {
title: "Queries route, match with a query string", title: "Queries route, match with a query string",
route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"),
request: newRequest("GET", "http://www.example.com/api?foo=bar&baz=ding"), request: newRequest("GET", "http://www.example.com/api?foo=bar&baz=ding"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
query: "foo=bar&baz=ding", query: "foo=bar&baz=ding",
pathTemplate: `/api`, pathTemplate: `/api`,
hostTemplate: `www.example.com`, hostTemplate: `www.example.com`,
shouldMatch: true, queriesTemplate: "foo=bar,baz=ding",
queriesRegexp: "^foo=bar$,^baz=ding$",
shouldMatch: true,
}, },
{ {
title: "Queries route, match with a query string out of order", title: "Queries route, match with a query string out of order",
route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"),
request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"), request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
query: "foo=bar&baz=ding", query: "foo=bar&baz=ding",
pathTemplate: `/api`, pathTemplate: `/api`,
hostTemplate: `www.example.com`, hostTemplate: `www.example.com`,
shouldMatch: true, queriesTemplate: "foo=bar,baz=ding",
queriesRegexp: "^foo=bar$,^baz=ding$",
shouldMatch: true,
}, },
{ {
title: "Queries route, bad query", title: "Queries route, bad query",
route: new(Route).Queries("foo", "bar", "baz", "ding"), route: new(Route).Queries("foo", "bar", "baz", "ding"),
request: newRequest("GET", "http://localhost?foo=bar&baz=dong"), request: newRequest("GET", "http://localhost?foo=bar&baz=dong"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
shouldMatch: false, queriesTemplate: "foo=bar,baz=ding",
queriesRegexp: "^foo=bar$,^baz=ding$",
shouldMatch: false,
}, },
{ {
title: "Queries route with pattern, match", title: "Queries route with pattern, match",
route: new(Route).Queries("foo", "{v1}"), route: new(Route).Queries("foo", "{v1}"),
request: newRequest("GET", "http://localhost?foo=bar"), request: newRequest("GET", "http://localhost?foo=bar"),
vars: map[string]string{"v1": "bar"}, vars: map[string]string{"v1": "bar"},
host: "", host: "",
path: "", path: "",
query: "foo=bar", query: "foo=bar",
shouldMatch: true, queriesTemplate: "foo={v1}",
queriesRegexp: "^foo=(?P<v0>.*)$",
shouldMatch: true,
}, },
{ {
title: "Queries route with multiple patterns, match", title: "Queries route with multiple patterns, match",
route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"), route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"),
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
vars: map[string]string{"v1": "bar", "v2": "ding"}, vars: map[string]string{"v1": "bar", "v2": "ding"},
host: "", host: "",
path: "", path: "",
query: "foo=bar&baz=ding", query: "foo=bar&baz=ding",
shouldMatch: true, queriesTemplate: "foo={v1},baz={v2}",
queriesRegexp: "^foo=(?P<v0>.*)$,^baz=(?P<v0>.*)$",
shouldMatch: true,
}, },
{ {
title: "Queries route with regexp pattern, match", title: "Queries route with regexp pattern, match",
route: new(Route).Queries("foo", "{v1:[0-9]+}"), route: new(Route).Queries("foo", "{v1:[0-9]+}"),
request: newRequest("GET", "http://localhost?foo=10"), request: newRequest("GET", "http://localhost?foo=10"),
vars: map[string]string{"v1": "10"}, vars: map[string]string{"v1": "10"},
host: "", host: "",
path: "", path: "",
query: "foo=10", query: "foo=10",
shouldMatch: true, queriesTemplate: "foo={v1:[0-9]+}",
queriesRegexp: "^foo=(?P<v0>[0-9]+)$",
shouldMatch: true,
}, },
{ {
title: "Queries route with regexp pattern, regexp does not match", title: "Queries route with regexp pattern, regexp does not match",
route: new(Route).Queries("foo", "{v1:[0-9]+}"), route: new(Route).Queries("foo", "{v1:[0-9]+}"),
request: newRequest("GET", "http://localhost?foo=a"), request: newRequest("GET", "http://localhost?foo=a"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
shouldMatch: false, queriesTemplate: "foo={v1:[0-9]+}",
queriesRegexp: "^foo=(?P<v0>[0-9]+)$",
shouldMatch: false,
}, },
{ {
title: "Queries route with regexp pattern with quantifier, match", title: "Queries route with regexp pattern with quantifier, match",
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
request: newRequest("GET", "http://localhost?foo=1"), request: newRequest("GET", "http://localhost?foo=1"),
vars: map[string]string{"v1": "1"}, vars: map[string]string{"v1": "1"},
host: "", host: "",
path: "", path: "",
query: "foo=1", query: "foo=1",
shouldMatch: true, queriesTemplate: "foo={v1:[0-9]{1}}",
queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
shouldMatch: true,
}, },
{ {
title: "Queries route with regexp pattern with quantifier, additional variable in query string, match", title: "Queries route with regexp pattern with quantifier, additional variable in query string, match",
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
request: newRequest("GET", "http://localhost?bar=2&foo=1"), request: newRequest("GET", "http://localhost?bar=2&foo=1"),
vars: map[string]string{"v1": "1"}, vars: map[string]string{"v1": "1"},
host: "", host: "",
path: "", path: "",
query: "foo=1", query: "foo=1",
shouldMatch: true, queriesTemplate: "foo={v1:[0-9]{1}}",
queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
shouldMatch: true,
}, },
{ {
title: "Queries route with regexp pattern with quantifier, regexp does not match", title: "Queries route with regexp pattern with quantifier, regexp does not match",
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
request: newRequest("GET", "http://localhost?foo=12"), request: newRequest("GET", "http://localhost?foo=12"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
shouldMatch: false, queriesTemplate: "foo={v1:[0-9]{1}}",
queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
shouldMatch: false,
}, },
{ {
title: "Queries route with regexp pattern with quantifier, additional capturing group", title: "Queries route with regexp pattern with quantifier, additional capturing group",
route: new(Route).Queries("foo", "{v1:[0-9]{1}(?:a|b)}"), route: new(Route).Queries("foo", "{v1:[0-9]{1}(?:a|b)}"),
request: newRequest("GET", "http://localhost?foo=1a"), request: newRequest("GET", "http://localhost?foo=1a"),
vars: map[string]string{"v1": "1a"}, vars: map[string]string{"v1": "1a"},
host: "", host: "",
path: "", path: "",
query: "foo=1a", query: "foo=1a",
shouldMatch: true, queriesTemplate: "foo={v1:[0-9]{1}(?:a|b)}",
queriesRegexp: "^foo=(?P<v0>[0-9]{1}(?:a|b))$",
shouldMatch: true,
}, },
{ {
title: "Queries route with regexp pattern with quantifier, additional variable in query string, regexp does not match", title: "Queries route with regexp pattern with quantifier, additional variable in query string, regexp does not match",
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
request: newRequest("GET", "http://localhost?foo=12"), request: newRequest("GET", "http://localhost?foo=12"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
shouldMatch: false, queriesTemplate: "foo={v1:[0-9]{1}}",
queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
shouldMatch: false,
}, },
{ {
title: "Queries route with hyphenated name, match", title: "Queries route with hyphenated name, match",
route: new(Route).Queries("foo", "{v-1}"), route: new(Route).Queries("foo", "{v-1}"),
request: newRequest("GET", "http://localhost?foo=bar"), request: newRequest("GET", "http://localhost?foo=bar"),
vars: map[string]string{"v-1": "bar"}, vars: map[string]string{"v-1": "bar"},
host: "", host: "",
path: "", path: "",
query: "foo=bar", query: "foo=bar",
shouldMatch: true, queriesTemplate: "foo={v-1}",
queriesRegexp: "^foo=(?P<v0>.*)$",
shouldMatch: true,
}, },
{ {
title: "Queries route with multiple hyphenated names, match", title: "Queries route with multiple hyphenated names, match",
route: new(Route).Queries("foo", "{v-1}", "baz", "{v-2}"), route: new(Route).Queries("foo", "{v-1}", "baz", "{v-2}"),
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
vars: map[string]string{"v-1": "bar", "v-2": "ding"}, vars: map[string]string{"v-1": "bar", "v-2": "ding"},
host: "", host: "",
path: "", path: "",
query: "foo=bar&baz=ding", query: "foo=bar&baz=ding",
shouldMatch: true, queriesTemplate: "foo={v-1},baz={v-2}",
queriesRegexp: "^foo=(?P<v0>.*)$,^baz=(?P<v0>.*)$",
shouldMatch: true,
}, },
{ {
title: "Queries route with hyphenate name and pattern, match", title: "Queries route with hyphenate name and pattern, match",
route: new(Route).Queries("foo", "{v-1:[0-9]+}"), route: new(Route).Queries("foo", "{v-1:[0-9]+}"),
request: newRequest("GET", "http://localhost?foo=10"), request: newRequest("GET", "http://localhost?foo=10"),
vars: map[string]string{"v-1": "10"}, vars: map[string]string{"v-1": "10"},
host: "", host: "",
path: "", path: "",
query: "foo=10", query: "foo=10",
shouldMatch: true, queriesTemplate: "foo={v-1:[0-9]+}",
queriesRegexp: "^foo=(?P<v0>[0-9]+)$",
shouldMatch: true,
}, },
{ {
title: "Queries route with hyphenated name and pattern with quantifier, additional capturing group", title: "Queries route with hyphenated name and pattern with quantifier, additional capturing group",
route: new(Route).Queries("foo", "{v-1:[0-9]{1}(?:a|b)}"), route: new(Route).Queries("foo", "{v-1:[0-9]{1}(?:a|b)}"),
request: newRequest("GET", "http://localhost?foo=1a"), request: newRequest("GET", "http://localhost?foo=1a"),
vars: map[string]string{"v-1": "1a"}, vars: map[string]string{"v-1": "1a"},
host: "", host: "",
path: "", path: "",
query: "foo=1a", query: "foo=1a",
shouldMatch: true, queriesTemplate: "foo={v-1:[0-9]{1}(?:a|b)}",
queriesRegexp: "^foo=(?P<v0>[0-9]{1}(?:a|b))$",
shouldMatch: true,
}, },
{ {
title: "Queries route with empty value, should match", title: "Queries route with empty value, should match",
route: new(Route).Queries("foo", ""), route: new(Route).Queries("foo", ""),
request: newRequest("GET", "http://localhost?foo=bar"), request: newRequest("GET", "http://localhost?foo=bar"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
query: "foo=", query: "foo=",
shouldMatch: true, queriesTemplate: "foo=",
queriesRegexp: "^foo=.*$",
shouldMatch: true,
}, },
{ {
title: "Queries route with empty value and no parameter in request, should not match", title: "Queries route with empty value and no parameter in request, should not match",
route: new(Route).Queries("foo", ""), route: new(Route).Queries("foo", ""),
request: newRequest("GET", "http://localhost"), request: newRequest("GET", "http://localhost"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
shouldMatch: false, queriesTemplate: "foo=",
queriesRegexp: "^foo=.*$",
shouldMatch: false,
}, },
{ {
title: "Queries route with empty value and empty parameter in request, should match", title: "Queries route with empty value and empty parameter in request, should match",
route: new(Route).Queries("foo", ""), route: new(Route).Queries("foo", ""),
request: newRequest("GET", "http://localhost?foo="), request: newRequest("GET", "http://localhost?foo="),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
query: "foo=", query: "foo=",
shouldMatch: true, queriesTemplate: "foo=",
queriesRegexp: "^foo=.*$",
shouldMatch: true,
}, },
{ {
title: "Queries route with overlapping value, should not match", title: "Queries route with overlapping value, should not match",
route: new(Route).Queries("foo", "bar"), route: new(Route).Queries("foo", "bar"),
request: newRequest("GET", "http://localhost?foo=barfoo"), request: newRequest("GET", "http://localhost?foo=barfoo"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
shouldMatch: false, queriesTemplate: "foo=bar",
queriesRegexp: "^foo=bar$",
shouldMatch: false,
}, },
{ {
title: "Queries route with no parameter in request, should not match", title: "Queries route with no parameter in request, should not match",
route: new(Route).Queries("foo", "{bar}"), route: new(Route).Queries("foo", "{bar}"),
request: newRequest("GET", "http://localhost"), request: newRequest("GET", "http://localhost"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
shouldMatch: false, queriesTemplate: "foo={bar}",
queriesRegexp: "^foo=(?P<v0>.*)$",
shouldMatch: false,
}, },
{ {
title: "Queries route with empty parameter in request, should match", title: "Queries route with empty parameter in request, should match",
route: new(Route).Queries("foo", "{bar}"), route: new(Route).Queries("foo", "{bar}"),
request: newRequest("GET", "http://localhost?foo="), request: newRequest("GET", "http://localhost?foo="),
vars: map[string]string{"foo": ""}, vars: map[string]string{"foo": ""},
host: "", host: "",
path: "", path: "",
query: "foo=", query: "foo=",
shouldMatch: true, queriesTemplate: "foo={bar}",
queriesRegexp: "^foo=(?P<v0>.*)$",
shouldMatch: true,
}, },
{ {
title: "Queries route, bad submatch", title: "Queries route, bad submatch",
route: new(Route).Queries("foo", "bar", "baz", "ding"), route: new(Route).Queries("foo", "bar", "baz", "ding"),
request: newRequest("GET", "http://localhost?fffoo=bar&baz=dingggg"), request: newRequest("GET", "http://localhost?fffoo=bar&baz=dingggg"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
shouldMatch: false, queriesTemplate: "foo=bar,baz=ding",
queriesRegexp: "^foo=bar$,^baz=ding$",
shouldMatch: false,
}, },
{ {
title: "Queries route with pattern, match, escaped value", title: "Queries route with pattern, match, escaped value",
route: new(Route).Queries("foo", "{v1}"), route: new(Route).Queries("foo", "{v1}"),
request: newRequest("GET", "http://localhost?foo=%25bar%26%20%2F%3D%3F"), request: newRequest("GET", "http://localhost?foo=%25bar%26%20%2F%3D%3F"),
vars: map[string]string{"v1": "%bar& /=?"}, vars: map[string]string{"v1": "%bar& /=?"},
host: "", host: "",
path: "", path: "",
query: "foo=%25bar%26+%2F%3D%3F", query: "foo=%25bar%26+%2F%3D%3F",
shouldMatch: true, queriesTemplate: "foo={v1}",
queriesRegexp: "^foo=(?P<v0>.*)$",
shouldMatch: true,
}, },
} }
for _, test := range tests { for _, test := range tests {
testRoute(t, test) testRoute(t, test)
testTemplate(t, test) testTemplate(t, test)
testQueriesTemplates(t, test)
testUseEscapedRoute(t, test) testUseEscapedRoute(t, test)
testQueriesRegexp(t, test)
} }
} }
@@ -1717,20 +1771,38 @@ func testRegexp(t *testing.T, test routeTest) {
} }
} }
func testQueriesRegexp(t *testing.T, test routeTest) {
route := test.route
queries, queriesErr := route.GetQueriesRegexp()
gotQueries := strings.Join(queries, ",")
if test.queriesRegexp != "" && queriesErr == nil && gotQueries != test.queriesRegexp {
t.Errorf("(%v) GetQueriesRegexp not equal: expected %v, got %v", test.title, test.queriesRegexp, gotQueries)
}
}
func testQueriesTemplates(t *testing.T, test routeTest) {
route := test.route
queries, queriesErr := route.GetQueriesTemplates()
gotQueries := strings.Join(queries, ",")
if test.queriesTemplate != "" && queriesErr == nil && gotQueries != test.queriesTemplate {
t.Errorf("(%v) GetQueriesTemplates not equal: expected %v, got %v", test.title, test.queriesTemplate, gotQueries)
}
}
type TestA301ResponseWriter struct { type TestA301ResponseWriter struct {
hh http.Header hh http.Header
status int status int
} }
func (ho TestA301ResponseWriter) Header() http.Header { func (ho *TestA301ResponseWriter) Header() http.Header {
return http.Header(ho.hh) return http.Header(ho.hh)
} }
func (ho TestA301ResponseWriter) Write(b []byte) (int, error) { func (ho *TestA301ResponseWriter) Write(b []byte) (int, error) {
return 0, nil return 0, nil
} }
func (ho TestA301ResponseWriter) WriteHeader(code int) { func (ho *TestA301ResponseWriter) WriteHeader(code int) {
ho.status = code ho.status = code
} }
@@ -1805,6 +1877,96 @@ func TestSubrouterHeader(t *testing.T) {
} }
} }
func TestNoMatchMethodErrorHandler(t *testing.T) {
func1 := func(w http.ResponseWriter, r *http.Request) {}
r := NewRouter()
r.HandleFunc("/", func1).Methods("GET", "POST")
req, _ := http.NewRequest("PUT", "http://localhost/", nil)
match := new(RouteMatch)
matched := r.Match(req, match)
if matched {
t.Error("Should not have matched route for methods")
}
if match.MatchErr != ErrMethodMismatch {
t.Error("Should get ErrMethodMismatch error")
}
resp := NewRecorder()
r.ServeHTTP(resp, req)
if resp.Code != 405 {
t.Errorf("Expecting code %v", 405)
}
// Add matching route
r.HandleFunc("/", func1).Methods("PUT")
match = new(RouteMatch)
matched = r.Match(req, match)
if !matched {
t.Error("Should have matched route for methods")
}
if match.MatchErr != nil {
t.Error("Should not have any matching error. Found:", match.MatchErr)
}
}
func TestErrMatchNotFound(t *testing.T) {
emptyHandler := func(w http.ResponseWriter, r *http.Request) {}
r := NewRouter()
r.HandleFunc("/", emptyHandler)
s := r.PathPrefix("/sub/").Subrouter()
s.HandleFunc("/", emptyHandler)
// Regular 404 not found
req, _ := http.NewRequest("GET", "/sub/whatever", nil)
match := new(RouteMatch)
matched := r.Match(req, match)
if matched {
t.Errorf("Subrouter should not have matched that, got %v", match.Route)
}
// Even without a custom handler, MatchErr is set to ErrNotFound
if match.MatchErr != ErrNotFound {
t.Errorf("Expected ErrNotFound MatchErr, but was %v", match.MatchErr)
}
// Now lets add a 404 handler to subrouter
s.NotFoundHandler = http.NotFoundHandler()
req, _ = http.NewRequest("GET", "/sub/whatever", nil)
// Test the subrouter first
match = new(RouteMatch)
matched = s.Match(req, match)
// Now we should get a match
if !matched {
t.Errorf("Subrouter should have matched %s", req.RequestURI)
}
// But MatchErr should be set to ErrNotFound anyway
if match.MatchErr != ErrNotFound {
t.Errorf("Expected ErrNotFound MatchErr, but was %v", match.MatchErr)
}
// Now test the parent (MatchErr should propagate)
match = new(RouteMatch)
matched = r.Match(req, match)
// Now we should get a match
if !matched {
t.Errorf("Router should have matched %s via subrouter", req.RequestURI)
}
// But MatchErr should be set to ErrNotFound anyway
if match.MatchErr != ErrNotFound {
t.Errorf("Expected ErrNotFound MatchErr, but was %v", match.MatchErr)
}
}
// mapToPairs converts a string map to a slice of string pairs // mapToPairs converts a string map to a slice of string pairs
func mapToPairs(m map[string]string) []string { func mapToPairs(m map[string]string) []string {
var i int var i int
@@ -1871,42 +2033,3 @@ func newRequest(method, url string) *http.Request {
} }
return req return req
} }
func TestNoMatchMethodErrorHandler(t *testing.T) {
func1 := func(w http.ResponseWriter, r *http.Request) {}
r := NewRouter()
r.HandleFunc("/", func1).Methods("GET", "POST")
req, _ := http.NewRequest("PUT", "http://localhost/", nil)
match := new(RouteMatch)
matched := r.Match(req, match)
if matched {
t.Error("Should not have matched route for methods")
}
if match.MatchErr != ErrMethodMismatch {
t.Error("Should get ErrMethodMismatch error")
}
resp := NewRecorder()
r.ServeHTTP(resp, req)
if resp.Code != 405 {
t.Errorf("Expecting code %v", 405)
}
// Add matching route
r.HandleFunc("/", func1).Methods("PUT")
match = new(RouteMatch)
matched = r.Match(req, match)
if !matched {
t.Error("Should have matched route for methods")
}
if match.MatchErr != nil {
t.Error("Should not have any matching error. Found:", match.MatchErr)
}
}

6
vendor/github.com/gorilla/mux/regexp.go сгенерированный поставляемый
Просмотреть файл

@@ -141,7 +141,7 @@ type routeRegexp struct {
matchQuery bool matchQuery bool
// The strictSlash value defined on the route, but disabled if PathPrefix was used. // The strictSlash value defined on the route, but disabled if PathPrefix was used.
strictSlash bool strictSlash bool
// Determines whether to use encoded path from getPath function or unencoded // Determines whether to use encoded req.URL.EnscapedPath() or unencoded
// req.URL.Path for path matching // req.URL.Path for path matching
useEncodedPath bool useEncodedPath bool
// Expanded regexp. // Expanded regexp.
@@ -162,7 +162,7 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
} }
path := req.URL.Path path := req.URL.Path
if r.useEncodedPath { if r.useEncodedPath {
path = getPath(req) path = req.URL.EscapedPath()
} }
return r.regexp.MatchString(path) return r.regexp.MatchString(path)
} }
@@ -272,7 +272,7 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route)
} }
path := req.URL.Path path := req.URL.Path
if r.useEncodedPath { if r.useEncodedPath {
path = getPath(req) path = req.URL.EscapedPath()
} }
// Store path variables. // Store path variables.
if v.path != nil { if v.path != nil {

44
vendor/github.com/gorilla/mux/route.go сгенерированный поставляемый
Просмотреть файл

@@ -72,7 +72,11 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
return false return false
} }
match.MatchErr = nil if match.MatchErr == ErrMethodMismatch {
// We found a route which matches request method, clear MatchErr
match.MatchErr = nil
}
// Yay, we have a match. Let's collect some info about it. // Yay, we have a match. Let's collect some info about it.
if match.Route == nil { if match.Route == nil {
match.Route = r match.Route = r
@@ -608,6 +612,44 @@ func (r *Route) GetPathRegexp() (string, error) {
return r.regexp.path.regexp.String(), nil return r.regexp.path.regexp.String(), nil
} }
// GetQueriesRegexp returns the expanded regular expressions used to match the
// route queries.
// This is useful for building simple REST API documentation and for instrumentation
// against third-party services.
// An empty list will be returned if the route does not have queries.
func (r *Route) GetQueriesRegexp() ([]string, error) {
if r.err != nil {
return nil, r.err
}
if r.regexp == nil || r.regexp.queries == nil {
return nil, errors.New("mux: route doesn't have queries")
}
var queries []string
for _, query := range r.regexp.queries {
queries = append(queries, query.regexp.String())
}
return queries, nil
}
// GetQueriesTemplates returns the templates used to build the
// query matching.
// This is useful for building simple REST API documentation and for instrumentation
// against third-party services.
// An empty list will be returned if the route does not define queries.
func (r *Route) GetQueriesTemplates() ([]string, error) {
if r.err != nil {
return nil, r.err
}
if r.regexp == nil || r.regexp.queries == nil {
return nil, errors.New("mux: route doesn't have queries")
}
var queries []string
for _, query := range r.regexp.queries {
queries = append(queries, query.template)
}
return queries, nil
}
// GetMethods returns the methods the route matches against // GetMethods returns the methods the route matches against
// This is useful for building simple REST API documentation and for instrumentation // This is useful for building simple REST API documentation and for instrumentation
// against third-party services. // against third-party services.

117
vendor/github.com/hashicorp/go-sockaddr/ifaddr_test.go сгенерированный поставляемый
Просмотреть файл

@@ -410,6 +410,114 @@ func TestIfAddrMath(t *testing.T) {
value: "+xyz", value: "+xyz",
wantFail: true, wantFail: true,
}, },
{
name: "ipv4 mask operand equals input ipv4 subnet mask",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv4Addr("10.20.30.40/8"),
},
operation: "mask",
value: "8",
expected: "10.0.0.0/8",
},
{
name: "ipv4 mask operand larger than input ipv4 subnet mask",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv4Addr("192.168.10.20/24"),
},
operation: "mask",
value: "16",
expected: "192.168.0.0/16",
},
{
name: "ipv4 host upper bound mask operand larger than input ipv4 subnet mask",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv4Addr("192.168.255.255/24"),
},
operation: "mask",
value: "16",
expected: "192.168.0.0/16",
},
{
name: "ipv4 mask operand smaller than ipv4 subnet mask",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv4Addr("10.20.30.40/8"),
},
operation: "mask",
value: "16",
expected: "10.20.0.0/8",
},
{
name: "ipv4 host upper bound mask operand smaller than input ipv4 subnet mask",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv4Addr("10.20.255.255/8"),
},
operation: "mask",
value: "16",
expected: "10.20.0.0/8",
},
{
name: "ipv4 mask bad value upper bound",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"),
},
operation: "mask",
value: "33",
wantFail: true,
},
{
name: "ipv4 mask bad value lower bound",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"),
},
operation: "mask",
value: "-1",
wantFail: true,
},
{
name: "ipv6 mask operand equals input ipv6 subnet mask",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv6Addr("2001:0db8:85a3::8a2e:0370:7334/64"),
},
operation: "mask",
value: "64",
expected: "2001:db8:85a3::/64",
},
{
name: "ipv6 mask operand larger than input ipv6 subnet mask",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv6Addr("2001:0db8:85a3::8a2e:0370:7334/64"),
},
operation: "mask",
value: "32",
expected: "2001:db8::/32",
},
{
name: "ipv6 mask operand smaller than input ipv6 subnet mask",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv6Addr("2001:0db8:85a3::8a2e:0370:7334/64"),
},
operation: "mask",
value: "96",
expected: "2001:db8:85a3::8a2e:0:0/64",
},
{
name: "ipv6 mask bad value upper bound",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv6Addr("::1/128"),
},
operation: "mask",
value: "129",
wantFail: true,
},
{
name: "ipv6 mask bad value lower bound",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustIPv6Addr("::1/128"),
},
operation: "mask",
value: "-1",
wantFail: true,
},
{ {
name: "unix unsupported operation", name: "unix unsupported operation",
ifAddr: sockaddr.IfAddr{ ifAddr: sockaddr.IfAddr{
@@ -428,6 +536,15 @@ func TestIfAddrMath(t *testing.T) {
value: "+123", value: "+123",
wantFail: true, wantFail: true,
}, },
{
name: "unix unsupported operation",
ifAddr: sockaddr.IfAddr{
SockAddr: sockaddr.MustUnixSock("/tmp/foo"),
},
operation: "mask",
value: "8",
wantFail: true,
},
} }
for i, test := range tests { for i, test := range tests {

75
vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go сгенерированный поставляемый
Просмотреть файл

@@ -1,6 +1,7 @@
package sockaddr package sockaddr
import ( import (
"encoding/binary"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
@@ -866,6 +867,80 @@ func IfAddrMath(operation, value string, inputIfAddr IfAddr) (IfAddr, error) {
default: default:
return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType) return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
} }
case "mask":
// "mask" operates on the IP address and returns the IP address on
// which the given integer mask has been applied. If the applied mask
// corresponds to a larger network than the mask of the IP address,
// the latter will be replaced by the former.
switch sockType := inputIfAddr.SockAddr.Type(); sockType {
case TypeIPv4:
i, err := strconv.ParseUint(value, 10, 32)
if err != nil {
return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
}
if i > 32 {
return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv4 addresses must be between 0 and 32", operation)
}
ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
ipv4Mask := net.CIDRMask(int(i), 32)
ipv4MaskUint32 := binary.BigEndian.Uint32(ipv4Mask)
maskedIpv4 := ipv4.NetIP().Mask(ipv4Mask)
maskedIpv4Uint32 := binary.BigEndian.Uint32(maskedIpv4)
maskedIpv4MaskUint32 := uint32(ipv4.Mask)
if ipv4MaskUint32 < maskedIpv4MaskUint32 {
maskedIpv4MaskUint32 = ipv4MaskUint32
}
return IfAddr{
SockAddr: IPv4Addr{
Address: IPv4Address(maskedIpv4Uint32),
Mask: IPv4Mask(maskedIpv4MaskUint32),
},
Interface: inputIfAddr.Interface,
}, nil
case TypeIPv6:
i, err := strconv.ParseUint(value, 10, 32)
if err != nil {
return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
}
if i > 128 {
return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv6 addresses must be between 0 and 64", operation)
}
ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
ipv6Mask := net.CIDRMask(int(i), 128)
ipv6MaskBigInt := new(big.Int)
ipv6MaskBigInt.SetBytes(ipv6Mask)
maskedIpv6 := ipv6.NetIP().Mask(ipv6Mask)
maskedIpv6BigInt := new(big.Int)
maskedIpv6BigInt.SetBytes(maskedIpv6)
maskedIpv6MaskBigInt := new(big.Int)
maskedIpv6MaskBigInt.Set(ipv6.Mask)
if ipv6MaskBigInt.Cmp(maskedIpv6MaskBigInt) == -1 {
maskedIpv6MaskBigInt = ipv6MaskBigInt
}
return IfAddr{
SockAddr: IPv6Addr{
Address: IPv6Address(maskedIpv6BigInt),
Mask: IPv6Mask(maskedIpv6MaskBigInt),
},
Interface: inputIfAddr.Interface,
}, nil
default:
return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
}
default: default:
return IfAddr{}, fmt.Errorf("unsupported math operation: %q", operation) return IfAddr{}, fmt.Errorf("unsupported math operation: %q", operation)
} }

8
vendor/github.com/hashicorp/go-sockaddr/template/doc.go сгенерированный поставляемый
Просмотреть файл

@@ -212,6 +212,13 @@ Supported operations include:
from the network's broadcast address (e.g. 127.0.0.1 `"network" "-1"` will from the network's broadcast address (e.g. 127.0.0.1 `"network" "-1"` will
return "127.255.255.255"). Values that overflow the network size will return "127.255.255.255"). Values that overflow the network size will
safely wrap. safely wrap.
- `mask`: Applies the given network mask to the address. The network mask is
expressed as a decimal value (e.g. network mask "24" corresponds to
`255.255.255.0`). After applying the network mask, the network mask of the
resulting address will be either the applied network mask or the network mask
of the input address depending on which network is larger
(e.g. 192.168.10.20/24 `"mask" "16"` will return "192.168.0.0/16" but
192.168.10.20/24 `"mask" "28"` will return "192.168.10.16/24").
Example: Example:
@@ -219,6 +226,7 @@ Example:
{{ GetPrivateInterfaces | include "type" "IP" | math "address" "-256" | attr "address" }} {{ GetPrivateInterfaces | include "type" "IP" | math "address" "-256" | attr "address" }}
{{ GetPrivateInterfaces | include "type" "IP" | math "network" "+2" | attr "address" }} {{ GetPrivateInterfaces | include "type" "IP" | math "network" "+2" | attr "address" }}
{{ GetPrivateInterfaces | include "type" "IP" | math "network" "-2" | attr "address" }} {{ GetPrivateInterfaces | include "type" "IP" | math "network" "-2" | attr "address" }}
{{ GetPrivateInterfaces | include "type" "IP" | math "mask" "24" | attr "address" }}
{{ GetPrivateInterfaces | include "flags" "forwardable|up" | include "type" "IPv4" | math "network" "+2" | attr "address" }} {{ GetPrivateInterfaces | include "flags" "forwardable|up" | include "type" "IPv4" | math "network" "+2" | attr "address" }}

3
vendor/github.com/hashicorp/hcl/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -3,7 +3,8 @@ sudo: false
language: go language: go
go: go:
- 1.8 - 1.x
- tip
branches: branches:
only: only:

31
vendor/github.com/hashicorp/hcl/decoder.go сгенерированный поставляемый
Просмотреть файл

@@ -573,7 +573,11 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
// Compile the list of all the fields that we're going to be decoding // Compile the list of all the fields that we're going to be decoding
// from all the structs. // from all the structs.
fields := make(map[*reflect.StructField]reflect.Value) type field struct {
field reflect.StructField
val reflect.Value
}
fields := []field{}
for len(structs) > 0 { for len(structs) > 0 {
structVal := structs[0] structVal := structs[0]
structs = structs[1:] structs = structs[1:]
@@ -616,7 +620,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
} }
// Normal struct field, store it away // Normal struct field, store it away
fields[&fieldType] = structVal.Field(i) fields = append(fields, field{fieldType, structVal.Field(i)})
} }
} }
@@ -624,26 +628,27 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
decodedFields := make([]string, 0, len(fields)) decodedFields := make([]string, 0, len(fields))
decodedFieldsVal := make([]reflect.Value, 0) decodedFieldsVal := make([]reflect.Value, 0)
unusedKeysVal := make([]reflect.Value, 0) unusedKeysVal := make([]reflect.Value, 0)
for fieldType, field := range fields { for _, f := range fields {
if !field.IsValid() { field, fieldValue := f.field, f.val
if !fieldValue.IsValid() {
// This should never happen // This should never happen
panic("field is not valid") panic("field is not valid")
} }
// If we can't set the field, then it is unexported or something, // If we can't set the field, then it is unexported or something,
// and we just continue onwards. // and we just continue onwards.
if !field.CanSet() { if !fieldValue.CanSet() {
continue continue
} }
fieldName := fieldType.Name fieldName := field.Name
tagValue := fieldType.Tag.Get(tagName) tagValue := field.Tag.Get(tagName)
tagParts := strings.SplitN(tagValue, ",", 2) tagParts := strings.SplitN(tagValue, ",", 2)
if len(tagParts) >= 2 { if len(tagParts) >= 2 {
switch tagParts[1] { switch tagParts[1] {
case "decodedFields": case "decodedFields":
decodedFieldsVal = append(decodedFieldsVal, field) decodedFieldsVal = append(decodedFieldsVal, fieldValue)
continue continue
case "key": case "key":
if item == nil { if item == nil {
@@ -654,10 +659,10 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
} }
} }
field.SetString(item.Keys[0].Token.Value().(string)) fieldValue.SetString(item.Keys[0].Token.Value().(string))
continue continue
case "unusedKeys": case "unusedKeys":
unusedKeysVal = append(unusedKeysVal, field) unusedKeysVal = append(unusedKeysVal, fieldValue)
continue continue
} }
} }
@@ -684,7 +689,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
// because we actually want the value. // because we actually want the value.
fieldName = fmt.Sprintf("%s.%s", name, fieldName) fieldName = fmt.Sprintf("%s.%s", name, fieldName)
if len(prefixMatches.Items) > 0 { if len(prefixMatches.Items) > 0 {
if err := d.decode(fieldName, prefixMatches, field); err != nil { if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil {
return err return err
} }
} }
@@ -694,12 +699,12 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
decodeNode = &ast.ObjectList{Items: ot.List.Items} decodeNode = &ast.ObjectList{Items: ot.List.Items}
} }
if err := d.decode(fieldName, decodeNode, field); err != nil { if err := d.decode(fieldName, decodeNode, fieldValue); err != nil {
return err return err
} }
} }
decodedFields = append(decodedFields, fieldType.Name) decodedFields = append(decodedFields, field.Name)
} }
if len(decodedFieldsVal) > 0 { if len(decodedFieldsVal) > 0 {

2
vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go сгенерированный поставляемый
Просмотреть файл

@@ -351,7 +351,7 @@ func (s *Scanner) scanNumber(ch rune) token.Type {
return token.NUMBER return token.NUMBER
} }
// scanMantissa scans the mantissa begining from the rune. It returns the next // scanMantissa scans the mantissa beginning from the rune. It returns the next
// non decimal rune. It's used to determine wheter it's a fraction or exponent. // non decimal rune. It's used to determine wheter it's a fraction or exponent.
func (s *Scanner) scanMantissa(ch rune) rune { func (s *Scanner) scanMantissa(ch rune) rune {
scanned := false scanned := false

2
vendor/github.com/hashicorp/hcl/json/scanner/scanner.go сгенерированный поставляемый
Просмотреть файл

@@ -246,7 +246,7 @@ func (s *Scanner) scanNumber(ch rune) token.Type {
return token.NUMBER return token.NUMBER
} }
// scanMantissa scans the mantissa begining from the rune. It returns the next // scanMantissa scans the mantissa beginning from the rune. It returns the next
// non decimal rune. It's used to determine wheter it's a fraction or exponent. // non decimal rune. It's used to determine wheter it's a fraction or exponent.
func (s *Scanner) scanMantissa(ch rune) rune { func (s *Scanner) scanMantissa(ch rune) rune {
scanned := false scanned := false

12
vendor/github.com/hashicorp/memberlist/memberlist.go сгенерированный поставляемый
Просмотреть файл

@@ -308,23 +308,17 @@ func (m *Memberlist) tcpLookupIP(host string, defaultPort uint16) ([]ipPort, err
// resolveAddr is used to resolve the address into an address, // resolveAddr is used to resolve the address into an address,
// port, and error. If no port is given, use the default // port, and error. If no port is given, use the default
func (m *Memberlist) resolveAddr(hostStr string) ([]ipPort, error) { func (m *Memberlist) resolveAddr(hostStr string) ([]ipPort, error) {
// Normalize the incoming string to host:port so we can apply Go's // This captures the supplied port, or the default one.
// parser to it. hostStr = ensurePort(hostStr, m.config.BindPort)
port := uint16(0)
if !hasPort(hostStr) {
hostStr += ":" + strconv.Itoa(m.config.BindPort)
}
host, sport, err := net.SplitHostPort(hostStr) host, sport, err := net.SplitHostPort(hostStr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// This will capture the supplied port, or the default one added above.
lport, err := strconv.ParseUint(sport, 10, 16) lport, err := strconv.ParseUint(sport, 10, 16)
if err != nil { if err != nil {
return nil, err return nil, err
} }
port = uint16(lport) port := uint16(lport)
// If it looks like an IP address we are done. The SplitHostPort() above // If it looks like an IP address we are done. The SplitHostPort() above
// will make sure the host part is in good shape for parsing, even for // will make sure the host part is in good shape for parsing, even for

2
vendor/github.com/hashicorp/memberlist/memberlist_test.go сгенерированный поставляемый
Просмотреть файл

@@ -424,7 +424,7 @@ func TestMemberList_ResolveAddr_TCP_First(t *testing.T) {
} }
port := uint16(m.config.BindPort) port := uint16(m.config.BindPort)
expected := []ipPort{ expected := []ipPort{
ipPort{net.ParseIP("127.0.0.1").To4(), port}, ipPort{net.ParseIP("127.0.0.1"), port},
ipPort{net.ParseIP("2001:db8:a0b:12f0::1"), port}, ipPort{net.ParseIP("2001:db8:a0b:12f0::1"), port},
} }
if !reflect.DeepEqual(ips, expected) { if !reflect.DeepEqual(ips, expected) {

2
vendor/github.com/hashicorp/memberlist/suspicion.go сгенерированный поставляемый
Просмотреть файл

@@ -117,7 +117,7 @@ func (s *suspicion) Confirm(from string) bool {
// stop the timer then we will call the timeout function directly from // stop the timer then we will call the timeout function directly from
// here. // here.
n := atomic.AddInt32(&s.n, 1) n := atomic.AddInt32(&s.n, 1)
elapsed := time.Now().Sub(s.start) elapsed := time.Since(s.start)
remaining := remainingSuspicionTime(n, s.k, elapsed, s.min, s.max) remaining := remainingSuspicionTime(n, s.k, elapsed, s.min, s.max)
if s.timer.Stop() { if s.timer.Stop() {
if remaining > 0 { if remaining > 0 {

42
vendor/github.com/hashicorp/memberlist/util.go сгенерированный поставляемый
Просмотреть файл

@@ -217,20 +217,6 @@ func decodeCompoundMessage(buf []byte) (trunc int, parts [][]byte, err error) {
return return
} }
// Given a string of the form "host", "host:port",
// "ipv6::addr" or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool {
last := strings.LastIndex(s, ":")
if last == -1 {
return false
}
if s[0] == '[' {
return s[last-1] == ']'
}
return strings.Index(s, ":") == last
}
// compressPayload takes an opaque input buffer, compresses it // compressPayload takes an opaque input buffer, compresses it
// and wraps it in a compress{} message that is encoded. // and wraps it in a compress{} message that is encoded.
func compressPayload(inp []byte) (*bytes.Buffer, error) { func compressPayload(inp []byte) (*bytes.Buffer, error) {
@@ -294,3 +280,31 @@ func decompressBuffer(c *compress) ([]byte, error) {
func joinHostPort(host string, port uint16) string { func joinHostPort(host string, port uint16) string {
return net.JoinHostPort(host, strconv.Itoa(int(port))) return net.JoinHostPort(host, strconv.Itoa(int(port)))
} }
// hasPort is given a string of the form "host", "host:port", "ipv6::address",
// or "[ipv6::address]:port", and returns true if the string includes a port.
func hasPort(s string) bool {
// IPv6 address in brackets.
if strings.LastIndex(s, "[") == 0 {
return strings.LastIndex(s, ":") > strings.LastIndex(s, "]")
}
// Otherwise the presence of a single colon determines if there's a port
// since IPv6 addresses outside of brackets (count > 1) can't have a
// port.
return strings.Count(s, ":") == 1
}
// ensurePort makes sure the given string has a port number on it, otherwise it
// appends the given port as a default.
func ensurePort(s string, port int) string {
if hasPort(s) {
return s
}
// If this is an IPv6 address, the join call will add another set of
// brackets, so we have to trim before we add the default port.
s = strings.Trim(s, "[]")
s = net.JoinHostPort(s, strconv.Itoa(port))
return s
}

39
vendor/github.com/hashicorp/memberlist/util_test.go сгенерированный поставляемый
Просмотреть файл

@@ -7,24 +7,31 @@ import (
"time" "time"
) )
func Test_hasPort(t *testing.T) { func TestUtil_PortFunctions(t *testing.T) {
cases := []struct { tests := []struct {
s string addr string
expected bool hasPort bool
ensurePort string
}{ }{
{"", false}, {"1.2.3.4", false, "1.2.3.4:8301"},
{":80", true}, {"1.2.3.4:1234", true, "1.2.3.4:1234"},
{"127.0.0.1", false}, {"2600:1f14:e22:1501:f9a:2e0c:a167:67e8", false, "[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:8301"},
{"127.0.0.1:80", true}, {"[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]", false, "[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:8301"},
{"::1", false}, {"[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:1234", true, "[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:1234"},
{"2001:db8:a0b:12f0::1", false}, {"localhost", false, "localhost:8301"},
{"[2001:db8:a0b:12f0::1]", false}, {"localhost:1234", true, "localhost:1234"},
{"[2001:db8:a0b:12f0::1]:80", true}, {"hashicorp.com", false, "hashicorp.com:8301"},
{"hashicorp.com:1234", true, "hashicorp.com:1234"},
} }
for _, c := range cases { for _, tt := range tests {
if hasPort(c.s) != c.expected { t.Run(tt.addr, func(t *testing.T) {
t.Fatalf("bad: '%s' hasPort was not %v", c.s, c.expected) if got, want := hasPort(tt.addr), tt.hasPort; got != want {
} t.Fatalf("got %v want %v", got, want)
}
if got, want := ensurePort(tt.addr, 8301), tt.ensurePort; got != want {
t.Fatalf("got %v want %v", got, want)
}
})
} }
} }

25
vendor/github.com/lib/pq/.travis.sh сгенерированный поставляемый
Просмотреть файл

@@ -70,4 +70,29 @@ postgresql_uninstall() {
sudo rm -rf /var/lib/postgresql sudo rm -rf /var/lib/postgresql
} }
megacheck_install() {
# Megacheck is Go 1.6+, so skip if Go 1.5.
if [[ "$(go version)" =~ "go1.5" ]]
then
echo "megacheck not supported, skipping installation"
return 0
fi
# Lock megacheck version at $MEGACHECK_VERSION to prevent spontaneous
# new error messages in old code.
go get -d honnef.co/go/tools/...
git -C $GOPATH/src/honnef.co/go/tools/ checkout $MEGACHECK_VERSION
go install honnef.co/go/tools/cmd/megacheck
megacheck --version
}
golint_install() {
# Golint is Go 1.6+, so skip if Go 1.5.
if [[ "$(go version)" =~ "go1.5" ]]
then
echo "golint not supported, skipping installation"
return 0
fi
go get github.com/golang/lint/golint
}
$1 $1

14
vendor/github.com/lib/pq/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -16,7 +16,9 @@ env:
- PQGOSSLTESTS=1 - PQGOSSLTESTS=1
- PQSSLCERTTEST_PATH=$PWD/certs - PQSSLCERTTEST_PATH=$PWD/certs
- PGHOST=127.0.0.1 - PGHOST=127.0.0.1
- MEGACHECK_VERSION=2017.1
matrix: matrix:
- PGVERSION=10
- PGVERSION=9.6 - PGVERSION=9.6
- PGVERSION=9.5 - PGVERSION=9.5
- PGVERSION=9.4 - PGVERSION=9.4
@@ -31,6 +33,8 @@ before_install:
- ./.travis.sh postgresql_install - ./.travis.sh postgresql_install
- ./.travis.sh postgresql_configure - ./.travis.sh postgresql_configure
- ./.travis.sh client_configure - ./.travis.sh client_configure
- ./.travis.sh megacheck_install
- ./.travis.sh golint_install
- go get golang.org/x/tools/cmd/goimports - go get golang.org/x/tools/cmd/goimports
before_script: before_script:
@@ -42,5 +46,15 @@ script:
- > - >
goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }' goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }'
- go vet ./... - go vet ./...
# For compatibility with Go 1.5, launch only if megacheck is present,
# ignore SA1019 (deprecation warnings) in conn_test.go (we have to use the
# deprecated driver.Execer and driver.Queryer interfaces) and S1024
# (time.Until) everywhere.
- >
which megacheck > /dev/null
&& megacheck -ignore 'github.com/lib/pq/conn_test.go:SA1019 github.com/lib/pq/*.go:S1024' ./...
|| echo 'megacheck is not supported, skipping check'
# For compatibility with Go 1.5, launch only if golint is present.
- which golint > /dev/null && golint ./... || echo 'golint is not supported, skipping check'
- PQTEST_BINARY_PARAMETERS=no go test -race -v ./... - PQTEST_BINARY_PARAMETERS=no go test -race -v ./...
- PQTEST_BINARY_PARAMETERS=yes go test -race -v ./... - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./...

1
vendor/github.com/lib/pq/README.md сгенерированный поставляемый
Просмотреть файл

@@ -1,5 +1,6 @@
# pq - A pure Go postgres driver for Go's database/sql package # pq - A pure Go postgres driver for Go's database/sql package
[![GoDoc](https://godoc.org/github.com/lib/pq?status.svg)](https://godoc.org/github.com/lib/pq)
[![Build Status](https://travis-ci.org/lib/pq.svg?branch=master)](https://travis-ci.org/lib/pq) [![Build Status](https://travis-ci.org/lib/pq.svg?branch=master)](https://travis-ci.org/lib/pq)
## Install ## Install

12
vendor/github.com/lib/pq/array_test.go сгенерированный поставляемый
Просмотреть файл

@@ -89,9 +89,7 @@ func TestParseArrayError(t *testing.T) {
} }
func TestArrayScanner(t *testing.T) { func TestArrayScanner(t *testing.T) {
var s sql.Scanner var s sql.Scanner = Array(&[]bool{})
s = Array(&[]bool{})
if _, ok := s.(*BoolArray); !ok { if _, ok := s.(*BoolArray); !ok {
t.Errorf("Expected *BoolArray, got %T", s) t.Errorf("Expected *BoolArray, got %T", s)
} }
@@ -126,9 +124,7 @@ func TestArrayScanner(t *testing.T) {
} }
func TestArrayValuer(t *testing.T) { func TestArrayValuer(t *testing.T) {
var v driver.Valuer var v driver.Valuer = Array([]bool{})
v = Array([]bool{})
if _, ok := v.(*BoolArray); !ok { if _, ok := v.(*BoolArray); !ok {
t.Errorf("Expected *BoolArray, got %T", v) t.Errorf("Expected *BoolArray, got %T", v)
} }
@@ -1193,9 +1189,7 @@ func TestGenericArrayValue(t *testing.T) {
} }
func TestGenericArrayValueErrors(t *testing.T) { func TestGenericArrayValueErrors(t *testing.T) {
var v []interface{} v := []interface{}{func() {}}
v = []interface{}{func() {}}
if _, err := (GenericArray{v}).Value(); err == nil { if _, err := (GenericArray{v}).Value(); err == nil {
t.Errorf("Expected error for %q, got nil", v) t.Errorf("Expected error for %q, got nil", v)
} }

32
vendor/github.com/lib/pq/conn.go сгенерированный поставляемый
Просмотреть файл

@@ -35,8 +35,12 @@ var (
errNoLastInsertID = errors.New("no LastInsertId available after the empty statement") errNoLastInsertID = errors.New("no LastInsertId available after the empty statement")
) )
// Driver is the Postgres database driver.
type Driver struct{} type Driver struct{}
// Open opens a new connection to the database. name is a connection string.
// Most users should only use it through database/sql package from the standard
// library.
func (d *Driver) Open(name string) (driver.Conn, error) { func (d *Driver) Open(name string) (driver.Conn, error) {
return Open(name) return Open(name)
} }
@@ -78,6 +82,8 @@ func (s transactionStatus) String() string {
panic("not reached") panic("not reached")
} }
// Dialer is the dialer interface. It can be used to obtain more control over
// how pq creates network connections.
type Dialer interface { type Dialer interface {
Dial(network, address string) (net.Conn, error) Dial(network, address string) (net.Conn, error)
DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error)
@@ -149,11 +155,7 @@ func (cn *conn) handleDriverSettings(o values) (err error) {
if err != nil { if err != nil {
return err return err
} }
err = boolSetting("binary_parameters", &cn.binaryParameters) return boolSetting("binary_parameters", &cn.binaryParameters)
if err != nil {
return err
}
return nil
} }
func (cn *conn) handlePgpass(o values) { func (cn *conn) handlePgpass(o values) {
@@ -165,11 +167,16 @@ func (cn *conn) handlePgpass(o values) {
if filename == "" { if filename == "" {
// XXX this code doesn't work on Windows where the default filename is // XXX this code doesn't work on Windows where the default filename is
// XXX %APPDATA%\postgresql\pgpass.conf // XXX %APPDATA%\postgresql\pgpass.conf
user, err := user.Current() // Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470
if err != nil { userHome := os.Getenv("HOME")
return if userHome == "" {
user, err := user.Current()
if err != nil {
return
}
userHome = user.HomeDir
} }
filename = filepath.Join(user.HomeDir, ".pgpass") filename = filepath.Join(userHome, ".pgpass")
} }
fileinfo, err := os.Stat(filename) fileinfo, err := os.Stat(filename)
if err != nil { if err != nil {
@@ -237,10 +244,14 @@ func (cn *conn) writeBuf(b byte) *writeBuf {
} }
} }
// Open opens a new connection to the database. name is a connection string.
// Most users should only use it through database/sql package from the standard
// library.
func Open(name string) (_ driver.Conn, err error) { func Open(name string) (_ driver.Conn, err error) {
return DialOpen(defaultDialer{}, name) return DialOpen(defaultDialer{}, name)
} }
// DialOpen opens a new connection to the database using a dialer.
func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
// Handle any panics during connection initialization. Note that we // Handle any panics during connection initialization. Note that we
// specifically do *not* want to use errRecover(), as that would turn any // specifically do *not* want to use errRecover(), as that would turn any
@@ -1431,7 +1442,8 @@ func (rs *rows) NextResultSet() error {
// //
// tblname := "my_table" // tblname := "my_table"
// data := "my_data" // data := "my_data"
// err = db.Exec(fmt.Sprintf("INSERT INTO %s VALUES ($1)", pq.QuoteIdentifier(tblname)), data) // quoted := pq.QuoteIdentifier(tblname)
// err := db.Exec(fmt.Sprintf("INSERT INTO %s VALUES ($1)", quoted), data)
// //
// Any double quotes in name will be escaped. The quoted identifier will be // Any double quotes in name will be escaped. The quoted identifier will be
// case sensitive when used in a query. If the input string contains a zero // case sensitive when used in a query. If the input string contains a zero

74
vendor/github.com/lib/pq/conn_test.go сгенерированный поставляемый
Просмотреть файл

@@ -935,12 +935,14 @@ func TestParseErrorInExtendedQuery(t *testing.T) {
db := openTestConn(t) db := openTestConn(t)
defer db.Close() defer db.Close()
rows, err := db.Query("PARSE_ERROR $1", 1) _, err := db.Query("PARSE_ERROR $1", 1)
if err == nil { pqErr, _ := err.(*Error)
t.Fatal("expected error") // Expecting a syntax error.
if err == nil || pqErr == nil || pqErr.Code != "42601" {
t.Fatalf("expected syntax error, got %s", err)
} }
rows, err = db.Query("SELECT 1") rows, err := db.Query("SELECT 1")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -1205,16 +1207,11 @@ func TestParseComplete(t *testing.T) {
tpc("SELECT foo", "", 0, true) // invalid row count tpc("SELECT foo", "", 0, true) // invalid row count
} }
func TestExecerInterface(t *testing.T) { // Test interface conformance.
// Gin up a straw man private struct just for the type check var (
cn := &conn{c: nil} _ driver.Execer = (*conn)(nil)
var cni interface{} = cn _ driver.Queryer = (*conn)(nil)
)
_, ok := cni.(driver.Execer)
if !ok {
t.Fatal("Driver doesn't implement Execer")
}
}
func TestNullAfterNonNull(t *testing.T) { func TestNullAfterNonNull(t *testing.T) {
db := openTestConn(t) db := openTestConn(t)
@@ -1392,36 +1389,29 @@ func TestParseOpts(t *testing.T) {
} }
func TestRuntimeParameters(t *testing.T) { func TestRuntimeParameters(t *testing.T) {
type RuntimeTestResult int
const (
ResultUnknown RuntimeTestResult = iota
ResultSuccess
ResultError // other error
)
tests := []struct { tests := []struct {
conninfo string conninfo string
param string param string
expected string expected string
expectedOutcome RuntimeTestResult success bool
}{ }{
// invalid parameter // invalid parameter
{"DOESNOTEXIST=foo", "", "", ResultError}, {"DOESNOTEXIST=foo", "", "", false},
// we can only work with a specific value for these two // we can only work with a specific value for these two
{"client_encoding=SQL_ASCII", "", "", ResultError}, {"client_encoding=SQL_ASCII", "", "", false},
{"datestyle='ISO, YDM'", "", "", ResultError}, {"datestyle='ISO, YDM'", "", "", false},
// "options" should work exactly as it does in libpq // "options" should work exactly as it does in libpq
{"options='-c search_path=pqgotest'", "search_path", "pqgotest", ResultSuccess}, {"options='-c search_path=pqgotest'", "search_path", "pqgotest", true},
// pq should override client_encoding in this case // pq should override client_encoding in this case
{"options='-c client_encoding=SQL_ASCII'", "client_encoding", "UTF8", ResultSuccess}, {"options='-c client_encoding=SQL_ASCII'", "client_encoding", "UTF8", true},
// allow client_encoding to be set explicitly // allow client_encoding to be set explicitly
{"client_encoding=UTF8", "client_encoding", "UTF8", ResultSuccess}, {"client_encoding=UTF8", "client_encoding", "UTF8", true},
// test a runtime parameter not supported by libpq // test a runtime parameter not supported by libpq
{"work_mem='139kB'", "work_mem", "139kB", ResultSuccess}, {"work_mem='139kB'", "work_mem", "139kB", true},
// test fallback_application_name // test fallback_application_name
{"application_name=foo fallback_application_name=bar", "application_name", "foo", ResultSuccess}, {"application_name=foo fallback_application_name=bar", "application_name", "foo", true},
{"application_name='' fallback_application_name=bar", "application_name", "", ResultSuccess}, {"application_name='' fallback_application_name=bar", "application_name", "", true},
{"fallback_application_name=bar", "application_name", "bar", ResultSuccess}, {"fallback_application_name=bar", "application_name", "bar", true},
} }
for _, test := range tests { for _, test := range tests {
@@ -1436,23 +1426,23 @@ func TestRuntimeParameters(t *testing.T) {
continue continue
} }
tryGetParameterValue := func() (value string, outcome RuntimeTestResult) { tryGetParameterValue := func() (value string, success bool) {
defer db.Close() defer db.Close()
row := db.QueryRow("SELECT current_setting($1)", test.param) row := db.QueryRow("SELECT current_setting($1)", test.param)
err = row.Scan(&value) err = row.Scan(&value)
if err != nil { if err != nil {
return "", ResultError return "", false
} }
return value, ResultSuccess return value, true
} }
value, outcome := tryGetParameterValue() value, success := tryGetParameterValue()
if outcome != test.expectedOutcome && outcome == ResultError { if success != test.success && !test.success {
t.Fatalf("%v: unexpected error: %v", test.conninfo, err) t.Fatalf("%v: unexpected error: %v", test.conninfo, err)
} }
if outcome != test.expectedOutcome { if success != test.success {
t.Fatalf("unexpected outcome %v (was expecting %v) for conninfo \"%s\"", t.Fatalf("unexpected outcome %v (was expecting %v) for conninfo \"%s\"",
outcome, test.expectedOutcome, test.conninfo) success, test.success, test.conninfo)
} }
if value != test.expected { if value != test.expected {
t.Fatalf("bad value for %s: got %s, want %s with conninfo \"%s\"", t.Fatalf("bad value for %s: got %s, want %s with conninfo \"%s\"",

8
vendor/github.com/lib/pq/copy_test.go сгенерированный поставляемый
Просмотреть файл

@@ -9,8 +9,7 @@ import (
) )
func TestCopyInStmt(t *testing.T) { func TestCopyInStmt(t *testing.T) {
var stmt string stmt := CopyIn("table name")
stmt = CopyIn("table name")
if stmt != `COPY "table name" () FROM STDIN` { if stmt != `COPY "table name" () FROM STDIN` {
t.Fatal(stmt) t.Fatal(stmt)
} }
@@ -27,8 +26,7 @@ func TestCopyInStmt(t *testing.T) {
} }
func TestCopyInSchemaStmt(t *testing.T) { func TestCopyInSchemaStmt(t *testing.T) {
var stmt string stmt := CopyInSchema("schema name", "table name")
stmt = CopyInSchema("schema name", "table name")
if stmt != `COPY "schema name"."table name" () FROM STDIN` { if stmt != `COPY "schema name"."table name" () FROM STDIN` {
t.Fatal(stmt) t.Fatal(stmt)
} }
@@ -226,7 +224,7 @@ func TestCopyInTypes(t *testing.T) {
if text != "Héllö\n ☃!\r\t\\" { if text != "Héllö\n ☃!\r\t\\" {
t.Fatal("unexpected result", text) t.Fatal("unexpected result", text)
} }
if bytes.Compare(blob, []byte{0, 255, 9, 10, 13}) != 0 { if !bytes.Equal(blob, []byte{0, 255, 9, 10, 13}) {
t.Fatal("unexpected result", blob) t.Fatal("unexpected result", blob)
} }
if nothing.Valid { if nothing.Valid {

32
vendor/github.com/lib/pq/doc.go сгенерированный поставляемый
Просмотреть файл

@@ -11,7 +11,8 @@ using this package directly. For example:
) )
func main() { func main() {
db, err := sql.Open("postgres", "user=pqgotest dbname=pqgotest sslmode=verify-full") connStr := "user=pqgotest dbname=pqgotest sslmode=verify-full"
db, err := sql.Open("postgres", connStr)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@@ -23,7 +24,8 @@ using this package directly. For example:
You can also connect to a database using a URL. For example: You can also connect to a database using a URL. For example:
db, err := sql.Open("postgres", "postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full") connStr := "postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full"
db, err := sql.Open("postgres", connStr)
Connection String Parameters Connection String Parameters
@@ -43,21 +45,28 @@ supported:
* dbname - The name of the database to connect to * dbname - The name of the database to connect to
* user - The user to sign in as * user - The user to sign in as
* password - The user's password * password - The user's password
* host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) * host - The host to connect to. Values that start with / are for unix
domain sockets. (default is localhost)
* port - The port to bind to. (default is 5432) * port - The port to bind to. (default is 5432)
* sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) * sslmode - Whether or not to use SSL (default is require, this is not
the default for libpq)
* fallback_application_name - An application_name to fall back to if one isn't provided. * fallback_application_name - An application_name to fall back to if one isn't provided.
* connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. * connect_timeout - Maximum wait for connection, in seconds. Zero or
not specified means wait indefinitely.
* sslcert - Cert file location. The file must contain PEM encoded data. * sslcert - Cert file location. The file must contain PEM encoded data.
* sslkey - Key file location. The file must contain PEM encoded data. * sslkey - Key file location. The file must contain PEM encoded data.
* sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. * sslrootcert - The location of the root certificate file. The file
must contain PEM encoded data.
Valid values for sslmode are: Valid values for sslmode are:
* disable - No SSL * disable - No SSL
* require - Always SSL (skip verification) * require - Always SSL (skip verification)
* verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) * verify-ca - Always SSL (verify that the certificate presented by the
* verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) server was signed by a trusted CA)
* verify-full - Always SSL (verify that the certification presented by
the server was signed by a trusted CA and the server host name
matches the one in the certificate)
See http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING See http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
for more information about connection string parameters. for more information about connection string parameters.
@@ -68,7 +77,7 @@ Use single quotes for values that contain whitespace:
A backslash will escape the next character in values: A backslash will escape the next character in values:
"user=space\ man password='it\'s valid' "user=space\ man password='it\'s valid'"
Note that the connection parameter client_encoding (which sets the Note that the connection parameter client_encoding (which sets the
text encoding for the connection) may be set but must be "UTF8", text encoding for the connection) may be set but must be "UTF8",
@@ -129,7 +138,8 @@ This package returns the following types for values from the PostgreSQL backend:
- integer types smallint, integer, and bigint are returned as int64 - integer types smallint, integer, and bigint are returned as int64
- floating-point types real and double precision are returned as float64 - floating-point types real and double precision are returned as float64
- character types char, varchar, and text are returned as string - character types char, varchar, and text are returned as string
- temporal types date, time, timetz, timestamp, and timestamptz are returned as time.Time - temporal types date, time, timetz, timestamp, and timestamptz are
returned as time.Time
- the boolean type is returned as bool - the boolean type is returned as bool
- the bytea type is returned as []byte - the bytea type is returned as []byte
@@ -229,7 +239,7 @@ for more information). Note that the channel name will be truncated to 63
bytes by the PostgreSQL server. bytes by the PostgreSQL server.
You can find a complete, working example of Listener usage at You can find a complete, working example of Listener usage at
http://godoc.org/github.com/lib/pq/listen_example. http://godoc.org/github.com/lib/pq/examples/listen.
*/ */
package pq package pq

10
vendor/github.com/lib/pq/encode_test.go сгенерированный поставляемый
Просмотреть файл

@@ -267,9 +267,7 @@ func TestTimestampWithOutTimezone(t *testing.T) {
t.Fatalf("Could not run query: %v", err) t.Fatalf("Could not run query: %v", err)
} }
n := r.Next() if !r.Next() {
if n != true {
t.Fatal("Expected at least one row") t.Fatal("Expected at least one row")
} }
@@ -289,8 +287,7 @@ func TestTimestampWithOutTimezone(t *testing.T) {
expected, result) expected, result)
} }
n = r.Next() if r.Next() {
if n != false {
t.Fatal("Expected only one row") t.Fatal("Expected only one row")
} }
} }
@@ -731,8 +728,7 @@ func TestAppendEscapedText(t *testing.T) {
} }
func TestAppendEscapedTextExistingBuffer(t *testing.T) { func TestAppendEscapedTextExistingBuffer(t *testing.T) {
var buf []byte buf := []byte("123\t")
buf = []byte("123\t")
if esc := appendEscapedText(buf, "hallo\tescape"); string(esc) != "123\thallo\\tescape" { if esc := appendEscapedText(buf, "hallo\tescape"); string(esc) != "123\thallo\\tescape" {
t.Fatal(string(esc)) t.Fatal(string(esc))
} }

Просмотреть файл

@@ -1,6 +1,6 @@
/* /*
Below you will find a self-contained Go program which uses the LISTEN / NOTIFY Package listen is a self-contained Go program which uses the LISTEN / NOTIFY
mechanism to avoid polling the database while waiting for more work to arrive. mechanism to avoid polling the database while waiting for more work to arrive.
// //
@@ -77,7 +77,9 @@ mechanism to avoid polling the database while waiting for more work to arrive.
} }
} }
listener := pq.NewListener(conninfo, 10 * time.Second, time.Minute, reportProblem) minReconn := 10 * time.Second
maxReconn := time.Minute
listener := pq.NewListener(conninfo, minReconn, maxReconn, reportProblem)
err = listener.Listen("getwork") err = listener.Listen("getwork")
if err != nil { if err != nil {
panic(err) panic(err)
@@ -93,4 +95,4 @@ mechanism to avoid polling the database while waiting for more work to arrive.
*/ */
package listen_example package listen

2
vendor/github.com/lib/pq/hstore/hstore.go сгенерированный поставляемый
Просмотреть файл

@@ -6,7 +6,7 @@ import (
"strings" "strings"
) )
// A wrapper for transferring Hstore values back and forth easily. // Hstore is a wrapper for transferring Hstore values back and forth easily.
type Hstore struct { type Hstore struct {
Map map[string]sql.NullString Map map[string]sql.NullString
} }

56
vendor/github.com/lib/pq/notify.go сгенерированный поставляемый
Просмотреть файл

@@ -60,7 +60,7 @@ type ListenerConn struct {
replyChan chan message replyChan chan message
} }
// Creates a new ListenerConn. Use NewListener instead. // NewListenerConn creates a new ListenerConn. Use NewListener instead.
func NewListenerConn(name string, notificationChan chan<- *Notification) (*ListenerConn, error) { func NewListenerConn(name string, notificationChan chan<- *Notification) (*ListenerConn, error) {
return newDialListenerConn(defaultDialer{}, name, notificationChan) return newDialListenerConn(defaultDialer{}, name, notificationChan)
} }
@@ -214,17 +214,17 @@ func (l *ListenerConn) listenerConnMain() {
// this ListenerConn is done // this ListenerConn is done
} }
// Send a LISTEN query to the server. See ExecSimpleQuery. // Listen sends a LISTEN query to the server. See ExecSimpleQuery.
func (l *ListenerConn) Listen(channel string) (bool, error) { func (l *ListenerConn) Listen(channel string) (bool, error) {
return l.ExecSimpleQuery("LISTEN " + QuoteIdentifier(channel)) return l.ExecSimpleQuery("LISTEN " + QuoteIdentifier(channel))
} }
// Send an UNLISTEN query to the server. See ExecSimpleQuery. // Unlisten sends an UNLISTEN query to the server. See ExecSimpleQuery.
func (l *ListenerConn) Unlisten(channel string) (bool, error) { func (l *ListenerConn) Unlisten(channel string) (bool, error) {
return l.ExecSimpleQuery("UNLISTEN " + QuoteIdentifier(channel)) return l.ExecSimpleQuery("UNLISTEN " + QuoteIdentifier(channel))
} }
// Send `UNLISTEN *` to the server. See ExecSimpleQuery. // UnlistenAll sends an `UNLISTEN *` query to the server. See ExecSimpleQuery.
func (l *ListenerConn) UnlistenAll() (bool, error) { func (l *ListenerConn) UnlistenAll() (bool, error) {
return l.ExecSimpleQuery("UNLISTEN *") return l.ExecSimpleQuery("UNLISTEN *")
} }
@@ -267,8 +267,8 @@ func (l *ListenerConn) sendSimpleQuery(q string) (err error) {
return nil return nil
} }
// Execute a "simple query" (i.e. one with no bindable parameters) on the // ExecSimpleQuery executes a "simple query" (i.e. one with no bindable
// connection. The possible return values are: // parameters) on the connection. The possible return values are:
// 1) "executed" is true; the query was executed to completion on the // 1) "executed" is true; the query was executed to completion on the
// database server. If the query failed, err will be set to the error // database server. If the query failed, err will be set to the error
// returned by the database, otherwise err will be nil. // returned by the database, otherwise err will be nil.
@@ -333,6 +333,7 @@ func (l *ListenerConn) ExecSimpleQuery(q string) (executed bool, err error) {
} }
} }
// Close closes the connection.
func (l *ListenerConn) Close() error { func (l *ListenerConn) Close() error {
l.connectionLock.Lock() l.connectionLock.Lock()
if l.err != nil { if l.err != nil {
@@ -346,7 +347,7 @@ func (l *ListenerConn) Close() error {
return l.cn.c.Close() return l.cn.c.Close()
} }
// Err() returns the reason the connection was closed. It is not safe to call // Err returns the reason the connection was closed. It is not safe to call
// this function until l.Notify has been closed. // this function until l.Notify has been closed.
func (l *ListenerConn) Err() error { func (l *ListenerConn) Err() error {
return l.err return l.err
@@ -354,32 +355,43 @@ func (l *ListenerConn) Err() error {
var errListenerClosed = errors.New("pq: Listener has been closed") var errListenerClosed = errors.New("pq: Listener has been closed")
// ErrChannelAlreadyOpen is returned from Listen when a channel is already
// open.
var ErrChannelAlreadyOpen = errors.New("pq: channel is already open") var ErrChannelAlreadyOpen = errors.New("pq: channel is already open")
// ErrChannelNotOpen is returned from Unlisten when a channel is not open.
var ErrChannelNotOpen = errors.New("pq: channel is not open") var ErrChannelNotOpen = errors.New("pq: channel is not open")
// ListenerEventType is an enumeration of listener event types.
type ListenerEventType int type ListenerEventType int
const ( const (
// Emitted only when the database connection has been initially // ListenerEventConnected is emitted only when the database connection
// initialized. err will always be nil. // has been initially initialized. The err argument of the callback
// will always be nil.
ListenerEventConnected ListenerEventType = iota ListenerEventConnected ListenerEventType = iota
// Emitted after a database connection has been lost, either because of an // ListenerEventDisconnected is emitted after a database connection has
// error or because Close has been called. err will be set to the reason // been lost, either because of an error or because Close has been
// the database connection was lost. // called. The err argument will be set to the reason the database
// connection was lost.
ListenerEventDisconnected ListenerEventDisconnected
// Emitted after a database connection has been re-established after // ListenerEventReconnected is emitted after a database connection has
// connection loss. err will always be nil. After this event has been // been re-established after connection loss. The err argument of the
// emitted, a nil pq.Notification is sent on the Listener.Notify channel. // callback will always be nil. After this event has been emitted, a
// nil pq.Notification is sent on the Listener.Notify channel.
ListenerEventReconnected ListenerEventReconnected
// Emitted after a connection to the database was attempted, but failed. // ListenerEventConnectionAttemptFailed is emitted after a connection
// err will be set to an error describing why the connection attempt did // to the database was attempted, but failed. The err argument will be
// not succeed. // set to an error describing why the connection attempt did not
// succeed.
ListenerEventConnectionAttemptFailed ListenerEventConnectionAttemptFailed
) )
// EventCallbackType is the event callback type. See also ListenerEventType
// constants' documentation.
type EventCallbackType func(event ListenerEventType, err error) type EventCallbackType func(event ListenerEventType, err error)
// Listener provides an interface for listening to notifications from a // Listener provides an interface for listening to notifications from a
@@ -454,9 +466,9 @@ func NewDialListener(d Dialer,
return l return l
} }
// Returns the notification channel for this listener. This is the same // NotificationChannel returns the notification channel for this listener.
// channel as Notify, and will not be recreated during the life time of the // This is the same channel as Notify, and will not be recreated during the
// Listener. // life time of the Listener.
func (l *Listener) NotificationChannel() <-chan *Notification { func (l *Listener) NotificationChannel() <-chan *Notification {
return l.Notify return l.Notify
} }
@@ -639,7 +651,7 @@ func (l *Listener) resync(cn *ListenerConn, notificationChan <-chan *Notificatio
// close and then return the error message from the connection, as // close and then return the error message from the connection, as
// per ListenerConn's interface. // per ListenerConn's interface.
if err != nil { if err != nil {
for _ = range notificationChan { for range notificationChan {
} }
doneChan <- cn.Err() doneChan <- cn.Err()
return return

6
vendor/github.com/lib/pq/notify_test.go сгенерированный поставляемый
Просмотреть файл

@@ -123,6 +123,9 @@ func TestConnUnlisten(t *testing.T) {
} }
_, err = db.Exec("NOTIFY notify_test") _, err = db.Exec("NOTIFY notify_test")
if err != nil {
t.Fatal(err)
}
err = expectNotification(t, channel, "notify_test", "") err = expectNotification(t, channel, "notify_test", "")
if err != nil { if err != nil {
@@ -159,6 +162,9 @@ func TestConnUnlistenAll(t *testing.T) {
} }
_, err = db.Exec("NOTIFY notify_test") _, err = db.Exec("NOTIFY notify_test")
if err != nil {
t.Fatal(err)
}
err = expectNotification(t, channel, "notify_test", "") err = expectNotification(t, channel, "notify_test", "")
if err != nil { if err != nil {

45
vendor/github.com/magiconair/properties/CHANGELOG.md сгенерированный поставляемый
Просмотреть файл

@@ -1,62 +1,65 @@
## Changelog ## Changelog
### Unreleased ### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017
* [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces
* [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled * [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled
Thanks to @mgurov for the fix. Thanks to @mgurov for the fix.
### [1.7.3](https://github.com/magiconair/properties/tags/v1.7.3) - 10 Jul 2017 ### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017
* [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically * [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically
* [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map * [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map
### [1.7.2](https://github.com/magiconair/properties/tags/v1.7.2) - 20 Mar 2017 ### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017
* [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency * [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency
* [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc) * [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc)
### [1.7.1](https://github.com/magiconair/properties/tags/v1.7.1) - 13 Jan 2017 ### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017
* [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER`
* [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs
* [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy * [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy
* [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function * [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function
### [1.7.0](https://github.com/magiconair/properties/tags/v1.7.0) - 20 Mar 2016 ### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016
* [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL. * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL.
* [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string. * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string.
* [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe) * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe)
### [1.6.0](https://github.com/magiconair/properties/tags/v1.6.0) - 11 Dec 2015 ### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015
* Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags. * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags.
### [1.5.6](https://github.com/magiconair/properties/tags/v1.5.6) - 18 Oct 2015 ### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015
* Vendored in gopkg.in/check.v1 * Vendored in gopkg.in/check.v1
### [1.5.5](https://github.com/magiconair/properties/tags/v1.5.5) - 31 Jul 2015 ### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015
* [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs) * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs)
### [1.5.4](https://github.com/magiconair/properties/tags/v1.5.4) - 23 Jun 2015 ### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015
* [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references. * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references.
### [1.5.3](https://github.com/magiconair/properties/tags/v1.5.3) - 02 Jun 2015 ### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015
* [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp)
### [1.5.2](https://github.com/magiconair/properties/tags/v1.5.2) - 10 Apr 2015 ### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015
* [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty
* Add clickable links to README * Add clickable links to README
### [1.5.1](https://github.com/magiconair/properties/tags/v1.5.1) - 08 Dec 2014 ### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014
* Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with
[time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration). [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration).
### [1.5.0](https://github.com/magiconair/properties/tags/v1.5.0) - 18 Nov 2014 ### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014
* Added support for single and multi-line comments (reading, writing and updating) * Added support for single and multi-line comments (reading, writing and updating)
* The order of keys is now preserved * The order of keys is now preserved
@@ -64,31 +67,31 @@
* Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method
* Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1) * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1)
### [1.4.2](https://github.com/magiconair/properties/tags/v1.4.2) - 15 Nov 2014 ### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014
* [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one
### [1.4.1](https://github.com/magiconair/properties/tags/v1.4.1) - 13 Nov 2014 ### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014
* [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string
### [1.4.0](https://github.com/magiconair/properties/tags/v1.4.0) - 23 Sep 2014 ### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014
* Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys
* Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties
### [1.3.0](https://github.com/magiconair/properties/tags/v1.3.0) - 18 Mar 2014 ### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014
* Added support for time.Duration * Added support for time.Duration
* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tags/vior configurable (log.Fatal, panic) - custom) * Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom)
* Changed default of MustXXX() failure from panic to log.Fatal * Changed default of MustXXX() failure from panic to log.Fatal
### [1.2.0](https://github.com/magiconair/properties/tags/v1.2.0) - 05 Mar 2014 ### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014
* Added MustGet... functions * Added MustGet... functions
* Added support for int and uint with range checks on 32 bit platforms * Added support for int and uint with range checks on 32 bit platforms
### [1.1.0](https://github.com/magiconair/properties/tags/v1.1.0) - 20 Jan 2014 ### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014
* Renamed from goproperties to properties * Renamed from goproperties to properties
* Added support for expansion of environment vars in * Added support for expansion of environment vars in
@@ -96,6 +99,6 @@
* Fixed bug where value expressions were not at the * Fixed bug where value expressions were not at the
start of the string start of the string
### [1.0.0](https://github.com/magiconair/properties/tags/v1.0.0) - 7 Jan 2014 ### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014
* Initial release * Initial release

2
vendor/github.com/magiconair/properties/README.md сгенерированный поставляемый
Просмотреть файл

@@ -1,7 +1,7 @@
Overview [![Build Status](https://travis-ci.org/magiconair/properties.svg?branch=master)](https://travis-ci.org/magiconair/properties) Overview [![Build Status](https://travis-ci.org/magiconair/properties.svg?branch=master)](https://travis-ci.org/magiconair/properties)
======== ========
#### Current version: 1.7.3 #### Current version: 1.7.4
properties is a Go library for reading and writing properties files. properties is a Go library for reading and writing properties files.

3
vendor/github.com/magiconair/properties/lex.go сгенерированный поставляемый
Просмотреть файл

@@ -196,9 +196,8 @@ func lexBeforeKey(l *lexer) stateFn {
return lexComment return lexComment
case isWhitespace(r): case isWhitespace(r):
l.acceptRun(whitespace)
l.ignore() l.ignore()
return lexKey return lexBeforeKey
default: default:
l.backup() l.backup()

2
vendor/github.com/magiconair/properties/properties_test.go сгенерированный поставляемый
Просмотреть файл

@@ -44,6 +44,8 @@ var complexTests = [][]string{
{"\nkey=value\n", "key", "value"}, {"\nkey=value\n", "key", "value"},
{"\rkey=value\r", "key", "value"}, {"\rkey=value\r", "key", "value"},
{"\r\nkey=value\r\n", "key", "value"}, {"\r\nkey=value\r\n", "key", "value"},
{"\nkey=value\n \nkey2=value2", "key", "value", "key2", "value2"},
{"\nkey=value\n\t\nkey2=value2", "key", "value", "key2", "value2"},
// escaped chars in key // escaped chars in key
{"k\\ ey = value", "k ey", "value"}, {"k\\ ey = value", "k ey", "value"},

12
vendor/github.com/miekg/dns/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -1,14 +1,20 @@
language: go language: go
sudo: false sudo: false
go: go:
- 1.7.x - 1.9.x
- 1.8.x
- tip - tip
env:
- TESTS="-race -v -bench=. -coverprofile=coverage.txt -covermode=atomic"
- TESTS="-race -v ./..."
before_install: before_install:
# don't use the miekg/dns when testing forks # don't use the miekg/dns when testing forks
- mkdir -p $GOPATH/src/github.com/miekg - mkdir -p $GOPATH/src/github.com/miekg
- ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true - ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true
script: script:
- go test -race -v -bench=. - go test $TESTS
after_success:
- bash <(curl -s https://codecov.io/bash)

27
vendor/github.com/miekg/dns/README.md сгенерированный поставляемый
Просмотреть файл

@@ -1,19 +1,19 @@
[![Build Status](https://travis-ci.org/miekg/dns.svg?branch=master)](https://travis-ci.org/miekg/dns) [![Build Status](https://travis-ci.org/miekg/dns.svg?branch=master)](https://travis-ci.org/miekg/dns)
[![Code Coverage](https://img.shields.io/codecov/c/github/miekg/dns/master.svg)](https://codecov.io/github/miekg/dns?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/miekg/dns)](https://goreportcard.com/report/miekg/dns)
[![](https://godoc.org/github.com/miekg/dns?status.svg)](https://godoc.org/github.com/miekg/dns) [![](https://godoc.org/github.com/miekg/dns?status.svg)](https://godoc.org/github.com/miekg/dns)
# Alternative (more granular) approach to a DNS library # Alternative (more granular) approach to a DNS library
> Less is more. > Less is more.
Complete and usable DNS library. All widely used Resource Records are Complete and usable DNS library. All widely used Resource Records are supported, including the
supported, including the DNSSEC types. It follows a lean and mean philosophy. DNSSEC types. It follows a lean and mean philosophy. If there is stuff you should know as a DNS
If there is stuff you should know as a DNS programmer there isn't a convenience programmer there isn't a convenience function for it. Server side and client side programming is
function for it. Server side and client side programming is supported, i.e. you supported, i.e. you can build servers and resolvers with it.
can build servers and resolvers with it.
We try to keep the "master" branch as sane as possible and at the bleeding edge We try to keep the "master" branch as sane as possible and at the bleeding edge of standards,
of standards, avoiding breaking changes wherever reasonable. We support the last avoiding breaking changes wherever reasonable. We support the last two versions of Go.
two versions of Go, currently: 1.7 and 1.8.
# Goals # Goals
@@ -55,11 +55,13 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/mehrdadrad/mylg * https://github.com/mehrdadrad/mylg
* https://github.com/bamarni/dockness * https://github.com/bamarni/dockness
* https://github.com/fffaraz/microdns * https://github.com/fffaraz/microdns
* http://quilt.io * http://kelda.io
* https://github.com/ipdcode/hades (JD.COM) * https://github.com/ipdcode/hades (JD.COM)
* https://github.com/StackExchange/dnscontrol/ * https://github.com/StackExchange/dnscontrol/
* https://www.dnsperf.com/ * https://www.dnsperf.com/
* https://dnssectest.net/ * https://dnssectest.net/
* https://dns.apebits.com
* https://github.com/oif/apex
Send pull request if you want to be listed here. Send pull request if you want to be listed here.
@@ -86,8 +88,8 @@ Miek Gieben - 2010-2012 - <miek@miek.nl>
# Building # Building
Building is done with the `go` tool. If you have setup your GOPATH Building is done with the `go` tool. If you have setup your GOPATH correctly, the following should
correctly, the following should work: work:
go get github.com/miekg/dns go get github.com/miekg/dns
go build github.com/miekg/dns go build github.com/miekg/dns
@@ -150,9 +152,8 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 7314 - DNS (EDNS) EXPIRE Option * 7314 - DNS (EDNS) EXPIRE Option
* 7828 - edns-tcp-keepalive EDNS0 Option * 7828 - edns-tcp-keepalive EDNS0 Option
* 7553 - URI record * 7553 - URI record
* 7858 - DNS over TLS: Initiation and Performance Considerations (draft) * 7858 - DNS over TLS: Initiation and Performance Considerations
* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies) * 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
* xxxx - EDNS0 DNS Update Lease (draft)
## Loosely based upon ## Loosely based upon

4
vendor/github.com/miekg/dns/client.go сгенерированный поставляемый
Просмотреть файл

@@ -78,6 +78,7 @@ func (c *Client) writeTimeout() time.Duration {
return dnsTimeout return dnsTimeout
} }
// Dial connects to the address on the named network.
func (c *Client) Dial(address string) (conn *Conn, err error) { func (c *Client) Dial(address string) (conn *Conn, err error) {
// create a new dialer with the appropriate timeout // create a new dialer with the appropriate timeout
var d net.Dialer var d net.Dialer
@@ -454,8 +455,7 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
// DialTimeout acts like Dial but takes a timeout. // DialTimeout acts like Dial but takes a timeout.
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) { func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}}
client := Client{Net: "udp", Dialer: &net.Dialer{Timeout: timeout}}
conn, err = client.Dial(address) conn, err = client.Dial(address)
if err != nil { if err != nil {
return nil, err return nil, err

122
vendor/github.com/miekg/dns/client_test.go сгенерированный поставляемый
Просмотреть файл

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"net" "net"
"strconv" "strconv"
"strings"
"sync" "sync"
"testing" "testing"
"time" "time"
@@ -15,7 +16,7 @@ func TestDialUDP(t *testing.T) {
HandleFunc("miek.nl.", HelloServer) HandleFunc("miek.nl.", HelloServer)
defer HandleRemove("miek.nl.") defer HandleRemove("miek.nl.")
s, addrstr, err := RunLocalUDPServer("[::1]:0") s, addrstr, err := RunLocalUDPServer(":0")
if err != nil { if err != nil {
t.Fatalf("unable to run test server: %v", err) t.Fatalf("unable to run test server: %v", err)
} }
@@ -38,7 +39,7 @@ func TestClientSync(t *testing.T) {
HandleFunc("miek.nl.", HelloServer) HandleFunc("miek.nl.", HelloServer)
defer HandleRemove("miek.nl.") defer HandleRemove("miek.nl.")
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0") s, addrstr, err := RunLocalUDPServer(":0")
if err != nil { if err != nil {
t.Fatalf("unable to run test server: %v", err) t.Fatalf("unable to run test server: %v", err)
} }
@@ -72,7 +73,7 @@ func TestClientLocalAddress(t *testing.T) {
HandleFunc("miek.nl.", HelloServerEchoAddrPort) HandleFunc("miek.nl.", HelloServerEchoAddrPort)
defer HandleRemove("miek.nl.") defer HandleRemove("miek.nl.")
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0") s, addrstr, err := RunLocalUDPServer(":0")
if err != nil { if err != nil {
t.Fatalf("unable to run test server: %v", err) t.Fatalf("unable to run test server: %v", err)
} }
@@ -82,11 +83,11 @@ func TestClientLocalAddress(t *testing.T) {
m.SetQuestion("miek.nl.", TypeSOA) m.SetQuestion("miek.nl.", TypeSOA)
c := new(Client) c := new(Client)
laddr := net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 12345, Zone: ""} laddr := net.UDPAddr{IP: net.ParseIP("0.0.0.0"), Port: 12345, Zone: ""}
c.Dialer = &net.Dialer{LocalAddr: &laddr} c.Dialer = &net.Dialer{LocalAddr: &laddr}
r, _, err := c.Exchange(m, addrstr) r, _, err := c.Exchange(m, addrstr)
if err != nil { if err != nil {
t.Errorf("failed to exchange: %v", err) t.Fatalf("failed to exchange: %v", err)
} }
if r != nil && r.Rcode != RcodeSuccess { if r != nil && r.Rcode != RcodeSuccess {
t.Errorf("failed to get an valid answer\n%v", r) t.Errorf("failed to get an valid answer\n%v", r)
@@ -98,7 +99,7 @@ func TestClientLocalAddress(t *testing.T) {
if txt == nil { if txt == nil {
t.Errorf("invalid TXT response\n%v", txt) t.Errorf("invalid TXT response\n%v", txt)
} }
if len(txt.Txt) != 1 || txt.Txt[0] != "127.0.0.1:12345" { if len(txt.Txt) != 1 || !strings.Contains(txt.Txt[0], ":12345") {
t.Errorf("invalid TXT response\n%v", txt.Txt) t.Errorf("invalid TXT response\n%v", txt.Txt)
} }
} }
@@ -116,7 +117,7 @@ func TestClientTLSSyncV4(t *testing.T) {
Certificates: []tls.Certificate{cert}, Certificates: []tls.Certificate{cert},
} }
s, addrstr, err := RunLocalTLSServer("127.0.0.1:0", &config) s, addrstr, err := RunLocalTLSServer(":0", &config)
if err != nil { if err != nil {
t.Fatalf("unable to run test server: %v", err) t.Fatalf("unable to run test server: %v", err)
} }
@@ -162,70 +163,11 @@ func TestClientTLSSyncV4(t *testing.T) {
} }
} }
func TestClientTLSSyncV6(t *testing.T) {
HandleFunc("miek.nl.", HelloServer)
defer HandleRemove("miek.nl.")
cert, err := tls.X509KeyPair(CertPEMBlock, KeyPEMBlock)
if err != nil {
t.Fatalf("unable to build certificate: %v", err)
}
config := tls.Config{
Certificates: []tls.Certificate{cert},
}
s, addrstr, err := RunLocalTLSServer("[::1]:0", &config)
if err != nil {
t.Fatalf("unable to run test server: %v", err)
}
defer s.Shutdown()
m := new(Msg)
m.SetQuestion("miek.nl.", TypeSOA)
c := new(Client)
// test tcp-tls
c.Net = "tcp-tls"
c.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
}
r, _, err := c.Exchange(m, addrstr)
if err != nil {
t.Fatalf("failed to exchange: %v", err)
}
if r == nil {
t.Fatal("response is nil")
}
if r.Rcode != RcodeSuccess {
t.Errorf("failed to get an valid answer\n%v", r)
}
// test tcp6-tls
c.Net = "tcp6-tls"
c.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
}
r, _, err = c.Exchange(m, addrstr)
if err != nil {
t.Fatalf("failed to exchange: %v", err)
}
if r == nil {
t.Fatal("response is nil")
}
if r.Rcode != RcodeSuccess {
t.Errorf("failed to get an valid answer\n%v", r)
}
}
func TestClientSyncBadID(t *testing.T) { func TestClientSyncBadID(t *testing.T) {
HandleFunc("miek.nl.", HelloServerBadID) HandleFunc("miek.nl.", HelloServerBadID)
defer HandleRemove("miek.nl.") defer HandleRemove("miek.nl.")
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0") s, addrstr, err := RunLocalUDPServer(":0")
if err != nil { if err != nil {
t.Fatalf("unable to run test server: %v", err) t.Fatalf("unable to run test server: %v", err)
} }
@@ -248,7 +190,7 @@ func TestClientEDNS0(t *testing.T) {
HandleFunc("miek.nl.", HelloServer) HandleFunc("miek.nl.", HelloServer)
defer HandleRemove("miek.nl.") defer HandleRemove("miek.nl.")
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0") s, addrstr, err := RunLocalUDPServer(":0")
if err != nil { if err != nil {
t.Fatalf("unable to run test server: %v", err) t.Fatalf("unable to run test server: %v", err)
} }
@@ -295,7 +237,7 @@ func TestClientEDNS0Local(t *testing.T) {
HandleFunc("miek.nl.", handler) HandleFunc("miek.nl.", handler)
defer HandleRemove("miek.nl.") defer HandleRemove("miek.nl.")
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0") s, addrstr, err := RunLocalUDPServer(":0")
if err != nil { if err != nil {
t.Fatalf("unable to run test server: %s", err) t.Fatalf("unable to run test server: %s", err)
} }
@@ -321,7 +263,6 @@ func TestClientEDNS0Local(t *testing.T) {
} }
if r.Rcode != RcodeSuccess { if r.Rcode != RcodeSuccess {
t.Fatal("failed to get a valid answer") t.Fatal("failed to get a valid answer")
t.Logf("%v\n", r)
} }
txt := r.Extra[0].(*TXT).Txt[0] txt := r.Extra[0].(*TXT).Txt[0]
@@ -333,41 +274,11 @@ func TestClientEDNS0Local(t *testing.T) {
got := r.Extra[1].(*OPT).Option[0].(*EDNS0_LOCAL).String() got := r.Extra[1].(*OPT).Option[0].(*EDNS0_LOCAL).String()
if got != optStr1 { if got != optStr1 {
t.Errorf("failed to get local edns0 answer; got %s, expected %s", got, optStr1) t.Errorf("failed to get local edns0 answer; got %s, expected %s", got, optStr1)
t.Logf("%v\n", r)
} }
got = r.Extra[1].(*OPT).Option[1].(*EDNS0_LOCAL).String() got = r.Extra[1].(*OPT).Option[1].(*EDNS0_LOCAL).String()
if got != optStr2 { if got != optStr2 {
t.Errorf("failed to get local edns0 answer; got %s, expected %s", got, optStr2) t.Errorf("failed to get local edns0 answer; got %s, expected %s", got, optStr2)
t.Logf("%v\n", r)
}
}
// ExampleTsigSecret_updateLeaseTSIG shows how to update a lease signed with TSIG
func ExampleTsigSecret_updateLeaseTSIG() {
m := new(Msg)
m.SetUpdate("t.local.ip6.io.")
rr, _ := NewRR("t.local.ip6.io. 30 A 127.0.0.1")
rrs := make([]RR, 1)
rrs[0] = rr
m.Insert(rrs)
leaseRr := new(OPT)
leaseRr.Hdr.Name = "."
leaseRr.Hdr.Rrtype = TypeOPT
e := new(EDNS0_UL)
e.Code = EDNS0UL
e.Lease = 120
leaseRr.Option = append(leaseRr.Option, e)
m.Extra = append(m.Extra, leaseRr)
c := new(Client)
m.SetTsig("polvi.", HmacMD5, 300, time.Now().Unix())
c.TsigSecret = map[string]string{"polvi.": "pRZgBrBvI4NAHZYhxmhs/Q=="}
_, _, err := c.Exchange(m, "127.0.0.1:53")
if err != nil {
panic(err)
} }
} }
@@ -376,7 +287,7 @@ func TestClientConn(t *testing.T) {
defer HandleRemove("miek.nl.") defer HandleRemove("miek.nl.")
// This uses TCP just to make it slightly different than TestClientSync // This uses TCP just to make it slightly different than TestClientSync
s, addrstr, err := RunLocalTCPServer("127.0.0.1:0") s, addrstr, err := RunLocalTCPServer(":0")
if err != nil { if err != nil {
t.Fatalf("unable to run test server: %v", err) t.Fatalf("unable to run test server: %v", err)
} }
@@ -558,7 +469,7 @@ func TestTruncatedMsg(t *testing.T) {
func TestTimeout(t *testing.T) { func TestTimeout(t *testing.T) {
// Set up a dummy UDP server that won't respond // Set up a dummy UDP server that won't respond
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") addr, err := net.ResolveUDPAddr("udp", ":0")
if err != nil { if err != nil {
t.Fatalf("unable to resolve local udp address: %v", err) t.Fatalf("unable to resolve local udp address: %v", err)
} }
@@ -614,7 +525,7 @@ func TestTimeout(t *testing.T) {
length := time.Since(start) length := time.Since(start)
if length > allowable { if length > allowable {
t.Errorf("exchange took longer (%v) than specified Timeout (%v)", length, timeout) t.Errorf("exchange took longer %v than specified Timeout %v", length, allowable)
} }
} }
@@ -640,7 +551,7 @@ func TestConcurrentExchanges(t *testing.T) {
HandleFunc("miek.nl.", handler) HandleFunc("miek.nl.", handler)
defer HandleRemove("miek.nl.") defer HandleRemove("miek.nl.")
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0") s, addrstr, err := RunLocalUDPServer(":0")
if err != nil { if err != nil {
t.Fatalf("unable to run test server: %s", err) t.Fatalf("unable to run test server: %s", err)
} }
@@ -673,8 +584,7 @@ func TestConcurrentExchanges(t *testing.T) {
wg.Wait() wg.Wait()
if r[0] == r[1] { if r[0] == r[1] {
t.Log("Got same response object, expected non-shared responses") t.Errorf("got same response, expected non-shared responses")
t.Fail()
} }
} }
} }

8
vendor/github.com/miekg/dns/clientconfig.go сгенерированный поставляемый
Просмотреть файл

@@ -2,6 +2,7 @@ package dns
import ( import (
"bufio" "bufio"
"io"
"os" "os"
"strconv" "strconv"
"strings" "strings"
@@ -25,8 +26,13 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
return nil, err return nil, err
} }
defer file.Close() defer file.Close()
return ClientConfigFromReader(file)
}
// ClientConfigFromReader works like ClientConfigFromFile but takes an io.Reader as argument
func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
c := new(ClientConfig) c := new(ClientConfig)
scanner := bufio.NewScanner(file) scanner := bufio.NewScanner(resolvconf)
c.Servers = make([]string, 0) c.Servers = make([]string, 0)
c.Search = make([]string, 0) c.Search = make([]string, 0)
c.Port = "53" c.Port = "53"

40
vendor/github.com/miekg/dns/clientconfig_test.go сгенерированный поставляемый
Просмотреть файл

@@ -4,6 +4,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"testing" "testing"
) )
@@ -20,17 +21,7 @@ nameserver 10.28.10.2
nameserver 11.28.10.1` // <- NOTE: NO newline. nameserver 11.28.10.1` // <- NOTE: NO newline.
func testConfig(t *testing.T, data string) { func testConfig(t *testing.T, data string) {
tempDir, err := ioutil.TempDir("", "") cc, err := ClientConfigFromReader(strings.NewReader(data))
if err != nil {
t.Fatalf("tempDir: %v", err)
}
defer os.RemoveAll(tempDir)
path := filepath.Join(tempDir, "resolv.conf")
if err := ioutil.WriteFile(path, []byte(data), 0644); err != nil {
t.Fatalf("writeFile: %v", err)
}
cc, err := ClientConfigFromFile(path)
if err != nil { if err != nil {
t.Errorf("error parsing resolv.conf: %v", err) t.Errorf("error parsing resolv.conf: %v", err)
} }
@@ -49,6 +40,33 @@ func testConfig(t *testing.T, data string) {
func TestNameserver(t *testing.T) { testConfig(t, normal) } func TestNameserver(t *testing.T) { testConfig(t, normal) }
func TestMissingFinalNewLine(t *testing.T) { testConfig(t, missingNewline) } func TestMissingFinalNewLine(t *testing.T) { testConfig(t, missingNewline) }
func TestReadFromFile(t *testing.T) {
tempDir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("tempDir: %v", err)
}
defer os.RemoveAll(tempDir)
path := filepath.Join(tempDir, "resolv.conf")
if err := ioutil.WriteFile(path, []byte(normal), 0644); err != nil {
t.Fatalf("writeFile: %v", err)
}
cc, err := ClientConfigFromFile(path)
if err != nil {
t.Errorf("error parsing resolv.conf: %v", err)
}
if l := len(cc.Servers); l != 2 {
t.Errorf("incorrect number of nameservers detected: %d", l)
}
if l := len(cc.Search); l != 1 {
t.Errorf("domain directive not parsed correctly: %v", cc.Search)
} else {
if cc.Search[0] != "somedomain.com" {
t.Errorf("domain is unexpected: %v", cc.Search[0])
}
}
}
func TestNameList(t *testing.T) { func TestNameList(t *testing.T) {
cfg := ClientConfig{ cfg := ClientConfig{
Ndots: 1, Ndots: 1,

25
vendor/github.com/miekg/dns/compress_generate.go сгенерированный поставляемый
Просмотреть файл

@@ -51,8 +51,9 @@ func main() {
fatalIfErr(err) fatalIfErr(err)
scope := pkg.Scope() scope := pkg.Scope()
domainTypes := map[string]bool{} // Types that have a domain name in them (either comressible or not). var domainTypes []string // Types that have a domain name in them (either compressible or not).
cdomainTypes := map[string]bool{} // Types that have a compressible domain name in them (subset of domainType) var cdomainTypes []string // Types that have a compressible domain name in them (subset of domainType)
Names:
for _, name := range scope.Names() { for _, name := range scope.Names() {
o := scope.Lookup(name) o := scope.Lookup(name)
if o == nil || !o.Exported() { if o == nil || !o.Exported() {
@@ -73,21 +74,25 @@ func main() {
for i := 1; i < st.NumFields(); i++ { for i := 1; i < st.NumFields(); i++ {
if _, ok := st.Field(i).Type().(*types.Slice); ok { if _, ok := st.Field(i).Type().(*types.Slice); ok {
if st.Tag(i) == `dns:"domain-name"` { if st.Tag(i) == `dns:"domain-name"` {
domainTypes[o.Name()] = true domainTypes = append(domainTypes, o.Name())
continue Names
} }
if st.Tag(i) == `dns:"cdomain-name"` { if st.Tag(i) == `dns:"cdomain-name"` {
cdomainTypes[o.Name()] = true cdomainTypes = append(cdomainTypes, o.Name())
domainTypes[o.Name()] = true domainTypes = append(domainTypes, o.Name())
continue Names
} }
continue continue
} }
switch { switch {
case st.Tag(i) == `dns:"domain-name"`: case st.Tag(i) == `dns:"domain-name"`:
domainTypes[o.Name()] = true domainTypes = append(domainTypes, o.Name())
continue Names
case st.Tag(i) == `dns:"cdomain-name"`: case st.Tag(i) == `dns:"cdomain-name"`:
cdomainTypes[o.Name()] = true cdomainTypes = append(cdomainTypes, o.Name())
domainTypes[o.Name()] = true domainTypes = append(domainTypes, o.Name())
continue Names
} }
} }
} }
@@ -99,7 +104,7 @@ func main() {
fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR) {\n") fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR) {\n")
fmt.Fprint(b, "switch x := r.(type) {\n") fmt.Fprint(b, "switch x := r.(type) {\n")
for name, _ := range domainTypes { for _, name := range domainTypes {
o := scope.Lookup(name) o := scope.Lookup(name)
st, _ := getTypeStruct(o.Type(), scope) st, _ := getTypeStruct(o.Type(), scope)
@@ -135,7 +140,7 @@ func main() {
fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool) {\n") fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool) {\n")
fmt.Fprint(b, "switch x := r.(type) {\n") fmt.Fprint(b, "switch x := r.(type) {\n")
for name, _ := range cdomainTypes { for _, name := range cdomainTypes {
o := scope.Lookup(name) o := scope.Lookup(name)
st, _ := getTypeStruct(o.Type(), scope) st, _ := getTypeStruct(o.Type(), scope)

9
vendor/github.com/miekg/dns/dns.go сгенерированный поставляемый
Просмотреть файл

@@ -6,9 +6,12 @@ const (
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits. year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
defaultTtl = 3600 // Default internal TTL. defaultTtl = 3600 // Default internal TTL.
DefaultMsgSize = 4096 // DefaultMsgSize is the standard default for messages larger than 512 bytes. // DefaultMsgSize is the standard default for messages larger than 512 bytes.
MinMsgSize = 512 // MinMsgSize is the minimal size of a DNS packet. DefaultMsgSize = 4096
MaxMsgSize = 65535 // MaxMsgSize is the largest possible DNS packet. // MinMsgSize is the minimal size of a DNS packet.
MinMsgSize = 512
// MaxMsgSize is the largest possible DNS packet.
MaxMsgSize = 65535
) )
// Error represents a DNS error. // Error represents a DNS error.

37
vendor/github.com/miekg/dns/dns_bench_test.go сгенерированный поставляемый
Просмотреть файл

@@ -17,7 +17,26 @@ func BenchmarkMsgLength(b *testing.B) {
return msg return msg
} }
name1 := "12345678901234567890123456789012345.12345678.123." name1 := "12345678901234567890123456789012345.12345678.123."
rrMx, _ := NewRR(name1 + " 3600 IN MX 10 " + name1) rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
b.StartTimer()
for i := 0; i < b.N; i++ {
msg.Len()
}
}
func BenchmarkMsgLengthNoCompression(b *testing.B) {
b.StopTimer()
makeMsg := func(question string, ans, ns, e []RR) *Msg {
msg := new(Msg)
msg.SetQuestion(Fqdn(question), TypeANY)
msg.Answer = append(msg.Answer, ans...)
msg.Ns = append(msg.Ns, ns...)
msg.Extra = append(msg.Extra, e...)
return msg
}
name1 := "12345678901234567890123456789012345.12345678.123."
rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil) msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
b.StartTimer() b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
@@ -36,7 +55,7 @@ func BenchmarkMsgLengthPack(b *testing.B) {
return msg return msg
} }
name1 := "12345678901234567890123456789012345.12345678.123." name1 := "12345678901234567890123456789012345.12345678.123."
rrMx, _ := NewRR(name1 + " 3600 IN MX 10 " + name1) rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil) msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
@@ -77,11 +96,11 @@ func BenchmarkCopy(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
m := new(Msg) m := new(Msg)
m.SetQuestion("miek.nl.", TypeA) m.SetQuestion("miek.nl.", TypeA)
rr, _ := NewRR("miek.nl. 2311 IN A 127.0.0.1") rr := testRR("miek.nl. 2311 IN A 127.0.0.1")
m.Answer = []RR{rr} m.Answer = []RR{rr}
rr, _ = NewRR("miek.nl. 2311 IN NS 127.0.0.1") rr = testRR("miek.nl. 2311 IN NS 127.0.0.1")
m.Ns = []RR{rr} m.Ns = []RR{rr}
rr, _ = NewRR("miek.nl. 2311 IN A 127.0.0.1") rr = testRR("miek.nl. 2311 IN A 127.0.0.1")
m.Extra = []RR{rr} m.Extra = []RR{rr}
b.ResetTimer() b.ResetTimer()
@@ -139,7 +158,7 @@ func BenchmarkUnpackMX(b *testing.B) {
} }
func BenchmarkPackAAAAA(b *testing.B) { func BenchmarkPackAAAAA(b *testing.B) {
aaaa, _ := NewRR(". IN A ::1") aaaa := testRR(". IN A ::1")
buf := make([]byte, aaaa.len()) buf := make([]byte, aaaa.len())
b.ReportAllocs() b.ReportAllocs()
@@ -150,7 +169,7 @@ func BenchmarkPackAAAAA(b *testing.B) {
} }
func BenchmarkUnpackAAAA(b *testing.B) { func BenchmarkUnpackAAAA(b *testing.B) {
aaaa, _ := NewRR(". IN A ::1") aaaa := testRR(". IN A ::1")
buf := make([]byte, aaaa.len()) buf := make([]byte, aaaa.len())
PackRR(aaaa, buf, 0, nil, false) PackRR(aaaa, buf, 0, nil, false)
@@ -173,7 +192,7 @@ func BenchmarkPackMsg(b *testing.B) {
return msg return msg
} }
name1 := "12345678901234567890123456789012345.12345678.123." name1 := "12345678901234567890123456789012345.12345678.123."
rrMx, _ := NewRR(name1 + " 3600 IN MX 10 " + name1) rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil) msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
buf := make([]byte, 512) buf := make([]byte, 512)
b.ReportAllocs() b.ReportAllocs()
@@ -194,7 +213,7 @@ func BenchmarkUnpackMsg(b *testing.B) {
return msg return msg
} }
name1 := "12345678901234567890123456789012345.12345678.123." name1 := "12345678901234567890123456789012345.12345678.123."
rrMx, _ := NewRR(name1 + " 3600 IN MX 10 " + name1) rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil) msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
msgBuf, _ := msg.Pack() msgBuf, _ := msg.Pack()
b.ReportAllocs() b.ReportAllocs()

72
vendor/github.com/miekg/dns/dns_test.go сгенерированный поставляемый
Просмотреть файл

@@ -126,60 +126,17 @@ func TestBailiwick(t *testing.T) {
} }
} }
func TestPack(t *testing.T) {
rr := []string{"US. 86400 IN NSEC 0-.us. NS SOA RRSIG NSEC DNSKEY TYPE65534"}
m := new(Msg)
var err error
m.Answer = make([]RR, 1)
for _, r := range rr {
m.Answer[0], err = NewRR(r)
if err != nil {
t.Errorf("failed to create RR: %v", err)
continue
}
if _, err := m.Pack(); err != nil {
t.Errorf("packing failed: %v", err)
}
}
x := new(Msg)
ns, _ := NewRR("pool.ntp.org. 390 IN NS a.ntpns.org")
ns.(*NS).Ns = "a.ntpns.org"
x.Ns = append(m.Ns, ns)
x.Ns = append(m.Ns, ns)
x.Ns = append(m.Ns, ns)
// This crashes due to the fact the a.ntpns.org isn't a FQDN
// How to recover() from a remove panic()?
if _, err := x.Pack(); err == nil {
t.Error("packing should fail")
}
x.Answer = make([]RR, 1)
x.Answer[0], err = NewRR(rr[0])
if err != nil {
t.Fatal(err)
}
if _, err := x.Pack(); err == nil {
t.Error("packing should fail")
}
x.Question = make([]Question, 1)
x.Question[0] = Question{";sd#edddds鍛↙赏‘℅∥↙xzztsestxssweewwsssstx@s@Z嵌e@cn.pool.ntp.org.", TypeA, ClassINET}
if _, err := x.Pack(); err == nil {
t.Error("packing should fail")
}
}
func TestPackNAPTR(t *testing.T) { func TestPackNAPTR(t *testing.T) {
for _, n := range []string{ for _, n := range []string{
`apple.com. IN NAPTR 100 50 "se" "SIP+D2U" "" _sip._udp.apple.com.`, `apple.com. IN NAPTR 100 50 "se" "SIP+D2U" "" _sip._udp.apple.com.`,
`apple.com. IN NAPTR 90 50 "se" "SIP+D2T" "" _sip._tcp.apple.com.`, `apple.com. IN NAPTR 90 50 "se" "SIP+D2T" "" _sip._tcp.apple.com.`,
`apple.com. IN NAPTR 50 50 "se" "SIPS+D2T" "" _sips._tcp.apple.com.`, `apple.com. IN NAPTR 50 50 "se" "SIPS+D2T" "" _sips._tcp.apple.com.`,
} { } {
rr, _ := NewRR(n) rr := testRR(n)
msg := make([]byte, rr.len()) msg := make([]byte, rr.len())
if off, err := PackRR(rr, msg, 0, nil, false); err != nil { if off, err := PackRR(rr, msg, 0, nil, false); err != nil {
t.Errorf("packing failed: %v", err) t.Errorf("packing failed: %v", err)
t.Errorf("length %d, need more than %d", rr.len(), off) t.Errorf("length %d, need more than %d", rr.len(), off)
} else {
t.Logf("buf size needed: %d", off)
} }
} }
} }
@@ -207,8 +164,8 @@ func TestMsgCompressLength(t *testing.T) {
} }
name1 := "12345678901234567890123456789012345.12345678.123." name1 := "12345678901234567890123456789012345.12345678.123."
rrA, _ := NewRR(name1 + " 3600 IN A 192.0.2.1") rrA := testRR(name1 + " 3600 IN A 192.0.2.1")
rrMx, _ := NewRR(name1 + " 3600 IN MX 10 " + name1) rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
tests := []*Msg{ tests := []*Msg{
makeMsg(name1, []RR{rrA}, nil, nil), makeMsg(name1, []RR{rrA}, nil, nil),
makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)} makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)}
@@ -237,8 +194,8 @@ func TestMsgLength(t *testing.T) {
} }
name1 := "12345678901234567890123456789012345.12345678.123." name1 := "12345678901234567890123456789012345.12345678.123."
rrA, _ := NewRR(name1 + " 3600 IN A 192.0.2.1") rrA := testRR(name1 + " 3600 IN A 192.0.2.1")
rrMx, _ := NewRR(name1 + " 3600 IN MX 10 " + name1) rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
tests := []*Msg{ tests := []*Msg{
makeMsg(name1, []RR{rrA}, nil, nil), makeMsg(name1, []RR{rrA}, nil, nil),
makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)} makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)}
@@ -331,14 +288,14 @@ func TestMsgCompressLength2(t *testing.T) {
} }
func TestToRFC3597(t *testing.T) { func TestToRFC3597(t *testing.T) {
a, _ := NewRR("miek.nl. IN A 10.0.1.1") a := testRR("miek.nl. IN A 10.0.1.1")
x := new(RFC3597) x := new(RFC3597)
x.ToRFC3597(a) x.ToRFC3597(a)
if x.String() != `miek.nl. 3600 CLASS1 TYPE1 \# 4 0a000101` { if x.String() != `miek.nl. 3600 CLASS1 TYPE1 \# 4 0a000101` {
t.Errorf("string mismatch, got: %s", x) t.Errorf("string mismatch, got: %s", x)
} }
b, _ := NewRR("miek.nl. IN MX 10 mx.miek.nl.") b := testRR("miek.nl. IN MX 10 mx.miek.nl.")
x.ToRFC3597(b) x.ToRFC3597(b)
if x.String() != `miek.nl. 3600 CLASS1 TYPE15 \# 14 000a026d78046d69656b026e6c00` { if x.String() != `miek.nl. 3600 CLASS1 TYPE15 \# 14 000a026d78046d69656b026e6c00` {
t.Errorf("string mismatch, got: %s", x) t.Errorf("string mismatch, got: %s", x)
@@ -372,11 +329,9 @@ func TestNoRdataUnpack(t *testing.T) {
t.Errorf("failed to pack RR: %v", err) t.Errorf("failed to pack RR: %v", err)
continue continue
} }
rr, _, err := UnpackRR(data[:off], 0) if _, _, err := UnpackRR(data[:off], 0); err != nil {
if err != nil {
t.Errorf("failed to unpack RR with zero rdata: %s: %v", TypeToString[typ], err) t.Errorf("failed to unpack RR with zero rdata: %s: %v", TypeToString[typ], err)
} }
t.Log(rr)
} }
} }
@@ -397,7 +352,7 @@ func TestRdataOverflow(t *testing.T) {
} }
func TestCopy(t *testing.T) { func TestCopy(t *testing.T) {
rr, _ := NewRR("miek.nl. 2311 IN A 127.0.0.1") // Weird TTL to avoid catching TTL rr := testRR("miek.nl. 2311 IN A 127.0.0.1") // Weird TTL to avoid catching TTL
rr1 := Copy(rr) rr1 := Copy(rr)
if rr.String() != rr1.String() { if rr.String() != rr1.String() {
t.Fatalf("Copy() failed %s != %s", rr.String(), rr1.String()) t.Fatalf("Copy() failed %s != %s", rr.String(), rr1.String())
@@ -407,9 +362,9 @@ func TestCopy(t *testing.T) {
func TestMsgCopy(t *testing.T) { func TestMsgCopy(t *testing.T) {
m := new(Msg) m := new(Msg)
m.SetQuestion("miek.nl.", TypeA) m.SetQuestion("miek.nl.", TypeA)
rr, _ := NewRR("miek.nl. 2311 IN A 127.0.0.1") rr := testRR("miek.nl. 2311 IN A 127.0.0.1")
m.Answer = []RR{rr} m.Answer = []RR{rr}
rr, _ = NewRR("miek.nl. 2311 IN NS 127.0.0.1") rr = testRR("miek.nl. 2311 IN NS 127.0.0.1")
m.Ns = []RR{rr} m.Ns = []RR{rr}
m1 := m.Copy() m1 := m.Copy()
@@ -417,12 +372,12 @@ func TestMsgCopy(t *testing.T) {
t.Fatalf("Msg.Copy() failed %s != %s", m.String(), m1.String()) t.Fatalf("Msg.Copy() failed %s != %s", m.String(), m1.String())
} }
m1.Answer[0], _ = NewRR("somethingelse.nl. 2311 IN A 127.0.0.1") m1.Answer[0] = testRR("somethingelse.nl. 2311 IN A 127.0.0.1")
if m.String() == m1.String() { if m.String() == m1.String() {
t.Fatalf("Msg.Copy() failed; change to copy changed template %s", m.String()) t.Fatalf("Msg.Copy() failed; change to copy changed template %s", m.String())
} }
rr, _ = NewRR("miek.nl. 2311 IN A 127.0.0.2") rr = testRR("miek.nl. 2311 IN A 127.0.0.2")
m1.Answer = append(m1.Answer, rr) m1.Answer = append(m1.Answer, rr)
if m1.Ns[0].String() == m1.Answer[1].String() { if m1.Ns[0].String() == m1.Answer[1].String() {
t.Fatalf("Msg.Copy() failed; append changed underlying array %s", m1.Ns[0].String()) t.Fatalf("Msg.Copy() failed; append changed underlying array %s", m1.Ns[0].String())
@@ -448,6 +403,5 @@ func TestMsgPackBuffer(t *testing.T) {
t.Errorf("packet %d failed to unpack", i) t.Errorf("packet %d failed to unpack", i)
continue continue
} }
t.Logf("packet %d %s", i, m.String())
} }
} }

113
vendor/github.com/miekg/dns/dnssec_test.go сгенерированный поставляемый
Просмотреть файл

@@ -35,57 +35,6 @@ func getSoa() *SOA {
return soa return soa
} }
func TestGenerateEC(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
key := new(DNSKEY)
key.Hdr.Rrtype = TypeDNSKEY
key.Hdr.Name = "miek.nl."
key.Hdr.Class = ClassINET
key.Hdr.Ttl = 14400
key.Flags = 256
key.Protocol = 3
key.Algorithm = ECDSAP256SHA256
privkey, _ := key.Generate(256)
t.Log(key.String())
t.Log(key.PrivateKeyString(privkey))
}
func TestGenerateDSA(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
key := new(DNSKEY)
key.Hdr.Rrtype = TypeDNSKEY
key.Hdr.Name = "miek.nl."
key.Hdr.Class = ClassINET
key.Hdr.Ttl = 14400
key.Flags = 256
key.Protocol = 3
key.Algorithm = DSA
privkey, _ := key.Generate(1024)
t.Log(key.String())
t.Log(key.PrivateKeyString(privkey))
}
func TestGenerateRSA(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
key := new(DNSKEY)
key.Hdr.Rrtype = TypeDNSKEY
key.Hdr.Name = "miek.nl."
key.Hdr.Class = ClassINET
key.Hdr.Ttl = 14400
key.Flags = 256
key.Protocol = 3
key.Algorithm = RSASHA256
privkey, _ := key.Generate(1024)
t.Log(key.String())
t.Log(key.PrivateKeyString(privkey))
}
func TestSecure(t *testing.T) { func TestSecure(t *testing.T) {
soa := getSoa() soa := getSoa()
@@ -211,10 +160,9 @@ func TestSignVerify(t *testing.T) {
continue continue
} }
if err := sig.Verify(key, []RR{r}); err != nil { if err := sig.Verify(key, []RR{r}); err != nil {
t.Error("failure to validate") t.Errorf("failure to validate: %s", r.Header().Name)
continue continue
} }
t.Logf("validated: %s", r.Header().Name)
} }
} }
@@ -248,9 +196,7 @@ func Test65534(t *testing.T) {
} }
if err := sig.Verify(key, []RR{t6}); err != nil { if err := sig.Verify(key, []RR{t6}); err != nil {
t.Error(err) t.Error(err)
t.Error("failure to validate") t.Errorf("failure to validate %s", t6.Header().Name)
} else {
t.Logf("validated: %s", t6.Header().Name)
} }
} }
@@ -381,7 +327,7 @@ Created: 20110302104537
Publish: 20110302104537 Publish: 20110302104537
Activate: 20110302104537` Activate: 20110302104537`
xk, _ := NewRR(pub) xk := testRR(pub)
k := xk.(*DNSKEY) k := xk.(*DNSKEY)
p, err := k.NewPrivateKey(priv) p, err := k.NewPrivateKey(priv)
if err != nil { if err != nil {
@@ -432,10 +378,7 @@ func TestSignVerifyECDSA(t *testing.T) {
Algorithm: 14 (ECDSAP384SHA384) Algorithm: 14 (ECDSAP384SHA384)
PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR` PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
eckey, err := NewRR(pub) eckey := testRR(pub)
if err != nil {
t.Fatal(err)
}
privkey, err := eckey.(*DNSKEY).NewPrivateKey(priv) privkey, err := eckey.(*DNSKEY).NewPrivateKey(priv)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -448,7 +391,7 @@ PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
if ds.Digest != "72d7b62976ce06438e9c0bf319013cf801f09ecc84b8d7e9495f27e305c6a9b0563a9b5f4d288405c3008a946df983d6" { if ds.Digest != "72d7b62976ce06438e9c0bf319013cf801f09ecc84b8d7e9495f27e305c6a9b0563a9b5f4d288405c3008a946df983d6" {
t.Fatal("wrong DS Digest") t.Fatal("wrong DS Digest")
} }
a, _ := NewRR("www.example.net. 3600 IN A 192.0.2.1") a := testRR("www.example.net. 3600 IN A 192.0.2.1")
sig := new(RRSIG) sig := new(RRSIG)
sig.Hdr = RR_Header{"example.net.", TypeRRSIG, ClassINET, 14400, 0} sig.Hdr = RR_Header{"example.net.", TypeRRSIG, ClassINET, 14400, 0}
sig.Expiration, _ = StringToTime("20100909102025") sig.Expiration, _ = StringToTime("20100909102025")
@@ -473,10 +416,7 @@ PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
} }
func TestSignVerifyECDSA2(t *testing.T) { func TestSignVerifyECDSA2(t *testing.T) {
srv1, err := NewRR("srv.miek.nl. IN SRV 1000 800 0 web1.miek.nl.") srv1 := testRR("srv.miek.nl. IN SRV 1000 800 0 web1.miek.nl.")
if err != nil {
t.Fatal(err)
}
srv := srv1.(*SRV) srv := srv1.(*SRV)
// With this key // With this key
@@ -511,7 +451,7 @@ func TestSignVerifyECDSA2(t *testing.T) {
err = sig.Verify(key, []RR{srv}) err = sig.Verify(key, []RR{srv})
if err != nil { if err != nil {
t.Logf("failure to validate:\n%s\n%s\n%s\n\n%s\n\n%v", t.Errorf("failure to validate:\n%s\n%s\n%s\n\n%s\n\n%v",
key.String(), key.String(),
srv.String(), srv.String(),
sig.String(), sig.String(),
@@ -530,10 +470,7 @@ func TestRFC6605P256(t *testing.T) {
exPriv := `Private-key-format: v1.2 exPriv := `Private-key-format: v1.2
Algorithm: 13 (ECDSAP256SHA256) Algorithm: 13 (ECDSAP256SHA256)
PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=` PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=`
rrDNSKEY, err := NewRR(exDNSKEY) rrDNSKEY := testRR(exDNSKEY)
if err != nil {
t.Fatal(err)
}
priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv) priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -542,10 +479,7 @@ PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=`
exDS := `example.net. 3600 IN DS 55648 13 2 ( exDS := `example.net. 3600 IN DS 55648 13 2 (
b4c8c1fe2e7477127b27115656ad6256f424625bf5c1 b4c8c1fe2e7477127b27115656ad6256f424625bf5c1
e2770ce6d6e37df61d17 )` e2770ce6d6e37df61d17 )`
rrDS, err := NewRR(exDS) rrDS := testRR(exDS)
if err != nil {
t.Fatal(err)
}
ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA256) ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA256)
if !reflect.DeepEqual(ourDS, rrDS.(*DS)) { if !reflect.DeepEqual(ourDS, rrDS.(*DS)) {
t.Errorf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS)) t.Errorf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS))
@@ -556,15 +490,9 @@ PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=`
20100909100439 20100812100439 55648 example.net. 20100909100439 20100812100439 55648 example.net.
qx6wLYqmh+l9oCKTN6qIc+bw6ya+KJ8oMz0YP107epXA qx6wLYqmh+l9oCKTN6qIc+bw6ya+KJ8oMz0YP107epXA
yGmt+3SNruPFKG7tZoLBLlUzGGus7ZwmwWep666VCw== )` yGmt+3SNruPFKG7tZoLBLlUzGGus7ZwmwWep666VCw== )`
rrA, err := NewRR(exA) rrA := testRR(exA)
if err != nil { rrRRSIG := testRR(exRRSIG)
t.Fatal(err) if err := rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrA}); err != nil {
}
rrRRSIG, err := NewRR(exRRSIG)
if err != nil {
t.Fatal(err)
}
if err = rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrA}); err != nil {
t.Errorf("failure to validate the spec RRSIG: %v", err) t.Errorf("failure to validate the spec RRSIG: %v", err)
} }
@@ -604,10 +532,7 @@ func TestRFC6605P384(t *testing.T) {
exPriv := `Private-key-format: v1.2 exPriv := `Private-key-format: v1.2
Algorithm: 14 (ECDSAP384SHA384) Algorithm: 14 (ECDSAP384SHA384)
PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR` PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
rrDNSKEY, err := NewRR(exDNSKEY) rrDNSKEY := testRR(exDNSKEY)
if err != nil {
t.Fatal(err)
}
priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv) priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -617,10 +542,7 @@ PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
72d7b62976ce06438e9c0bf319013cf801f09ecc84b8 72d7b62976ce06438e9c0bf319013cf801f09ecc84b8
d7e9495f27e305c6a9b0563a9b5f4d288405c3008a94 d7e9495f27e305c6a9b0563a9b5f4d288405c3008a94
6df983d6 )` 6df983d6 )`
rrDS, err := NewRR(exDS) rrDS := testRR(exDS)
if err != nil {
t.Fatal(err)
}
ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA384) ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA384)
if !reflect.DeepEqual(ourDS, rrDS.(*DS)) { if !reflect.DeepEqual(ourDS, rrDS.(*DS)) {
t.Fatalf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS)) t.Fatalf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS))
@@ -632,11 +554,8 @@ PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
/L5hDKIvGDyI1fcARX3z65qrmPsVz73QD1Mr5CEqOiLP /L5hDKIvGDyI1fcARX3z65qrmPsVz73QD1Mr5CEqOiLP
95hxQouuroGCeZOvzFaxsT8Glr74hbavRKayJNuydCuz 95hxQouuroGCeZOvzFaxsT8Glr74hbavRKayJNuydCuz
WTSSPdz7wnqXL5bdcJzusdnI0RSMROxxwGipWcJm )` WTSSPdz7wnqXL5bdcJzusdnI0RSMROxxwGipWcJm )`
rrA, err := NewRR(exA) rrA := testRR(exA)
if err != nil { rrRRSIG := testRR(exRRSIG)
t.Fatal(err)
}
rrRRSIG, err := NewRR(exRRSIG)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

18
vendor/github.com/miekg/dns/dnsutil/util.go сгенерированный поставляемый
Просмотреть файл

@@ -20,7 +20,9 @@ import (
func AddOrigin(s, origin string) string { func AddOrigin(s, origin string) string {
// ("foo.", "origin.") -> "foo." (already a FQDN) // ("foo.", "origin.") -> "foo." (already a FQDN)
// ("foo", "origin.") -> "foo.origin." // ("foo", "origin.") -> "foo.origin."
// ("foo"), "origin" -> "foo.origin" // ("foo", "origin") -> "foo.origin"
// ("foo", ".") -> "foo." (Same as dns.Fqdn())
// ("foo.", ".") -> "foo." (Same as dns.Fqdn())
// ("@", "origin.") -> "origin." (@ represents the apex (bare) domain) // ("@", "origin.") -> "origin." (@ represents the apex (bare) domain)
// ("", "origin.") -> "origin." (not obvious) // ("", "origin.") -> "origin." (not obvious)
// ("foo", "") -> "foo" (not obvious) // ("foo", "") -> "foo" (not obvious)
@@ -34,32 +36,34 @@ func AddOrigin(s, origin string) string {
if s == "@" || len(s) == 0 { if s == "@" || len(s) == 0 {
return origin // Expand apex. return origin // Expand apex.
} }
if origin == "." { if origin == "." {
return s + origin // AddOrigin(s, ".") is an expensive way to add a ".". return dns.Fqdn(s)
} }
return s + "." + origin // The simple case. return s + "." + origin // The simple case.
} }
// TrimDomainName trims origin from s if s is a subdomain. // TrimDomainName trims origin from s if s is a subdomain.
// This function will never return "", but returns "@" instead (@ represents the apex (bare) domain). // This function will never return "", but returns "@" instead (@ represents the apex domain).
func TrimDomainName(s, origin string) string { func TrimDomainName(s, origin string) string {
// An apex (bare) domain is always returned as "@". // An apex (bare) domain is always returned as "@".
// If the return value ends in a ".", the domain was not the suffix. // If the return value ends in a ".", the domain was not the suffix.
// origin can end in "." or not. Either way the results should be the same. // origin can end in "." or not. Either way the results should be the same.
if len(s) == 0 { if len(s) == 0 {
return "@" // Return the apex (@) rather than "". return "@"
} }
// Someone is using TrimDomainName(s, ".") to remove a dot if it exists. // Someone is using TrimDomainName(s, ".") to remove a dot if it exists.
if origin == "." { if origin == "." {
return strings.TrimSuffix(s, origin) return strings.TrimSuffix(s, origin)
} }
// Dude, you aren't even if the right subdomain! original := s
s = dns.Fqdn(s)
origin = dns.Fqdn(origin)
if !dns.IsSubDomain(origin, s) { if !dns.IsSubDomain(origin, s) {
return s return original
} }
slabels := dns.Split(s) slabels := dns.Split(s)

22
vendor/github.com/miekg/dns/dnsutil/util_test.go сгенерированный поставляемый
Просмотреть файл

@@ -10,6 +10,8 @@ func TestAddOrigin(t *testing.T) {
{"@", "example.com.", "example.com."}, {"@", "example.com.", "example.com."},
{"foo", "example.com.", "foo.example.com."}, {"foo", "example.com.", "foo.example.com."},
{"foo.", "example.com.", "foo."}, {"foo.", "example.com.", "foo."},
{"example.com", ".", "example.com."},
{"example.com.", ".", "example.com."},
// Oddball tests: // Oddball tests:
// In general origin should not be "" or "." but at least // In general origin should not be "" or "." but at least
// these tests verify we don't crash and will keep results // these tests verify we don't crash and will keep results
@@ -26,16 +28,15 @@ func TestAddOrigin(t *testing.T) {
for _, test := range tests { for _, test := range tests {
actual := AddOrigin(test.e1, test.e2) actual := AddOrigin(test.e1, test.e2)
if test.expected != actual { if test.expected != actual {
t.Errorf("AddOrigin(%#v, %#v) expected %#v, go %#v\n", test.e1, test.e2, test.expected, actual) t.Errorf("AddOrigin(%#v, %#v) expected %#v, got %#v\n", test.e1, test.e2, test.expected, actual)
} }
} }
} }
func TestTrimDomainName(t *testing.T) { func TestTrimDomainName(t *testing.T) {
// Basic tests. // Basic tests.
// Try trimming "example.com" and "example.com." from typical use cases. // Try trimming "example.com" and "example.com." from typical use cases.
var tests_examplecom = []struct{ experiment, expected string }{ testsEx := []struct{ experiment, expected string }{
{"foo.example.com", "foo"}, {"foo.example.com", "foo"},
{"foo.example.com.", "foo"}, {"foo.example.com.", "foo"},
{".foo.example.com", ".foo"}, {".foo.example.com", ".foo"},
@@ -51,10 +52,10 @@ func TestTrimDomainName(t *testing.T) {
{".foo.ronco.com.", ".foo.ronco.com."}, {".foo.ronco.com.", ".foo.ronco.com."},
} }
for _, dom := range []string{"example.com", "example.com."} { for _, dom := range []string{"example.com", "example.com."} {
for i, test := range tests_examplecom { for i, test := range testsEx {
actual := TrimDomainName(test.experiment, dom) actual := TrimDomainName(test.experiment, dom)
if test.expected != actual { if test.expected != actual {
t.Errorf("%d TrimDomainName(%#v, %#v): expected (%v) got (%v)\n", i, test.experiment, dom, test.expected, actual) t.Errorf("%d TrimDomainName(%#v, %#v): expected %v, got %v\n", i, test.experiment, dom, test.expected, actual)
} }
} }
} }
@@ -63,7 +64,7 @@ func TestTrimDomainName(t *testing.T) {
// These test shouldn't be needed but I was weary of off-by-one errors. // These test shouldn't be needed but I was weary of off-by-one errors.
// In theory, these can't happen because there are no single-letter TLDs, // In theory, these can't happen because there are no single-letter TLDs,
// but it is good to exercize the code this way. // but it is good to exercize the code this way.
var tests = []struct{ experiment, expected string }{ tests := []struct{ experiment, expected string }{
{"", "@"}, {"", "@"},
{".", "."}, {".", "."},
{"a.b.c.d.e.f.", "a.b.c.d.e"}, {"a.b.c.d.e.f.", "a.b.c.d.e"},
@@ -105,7 +106,7 @@ func TestTrimDomainName(t *testing.T) {
for i, test := range tests { for i, test := range tests {
actual := TrimDomainName(test.experiment, dom) actual := TrimDomainName(test.experiment, dom)
if test.expected != actual { if test.expected != actual {
t.Errorf("%d TrimDomainName(%#v, %#v): expected (%v) got (%v)\n", i, test.experiment, dom, test.expected, actual) t.Errorf("%d TrimDomainName(%#v, %#v): expected %v, got %v\n", i, test.experiment, dom, test.expected, actual)
} }
} }
} }
@@ -114,17 +115,16 @@ func TestTrimDomainName(t *testing.T) {
// These test cases provide both origin, s, and the expected result. // These test cases provide both origin, s, and the expected result.
// If you find a bug in the while, this is probably the easiest place // If you find a bug in the while, this is probably the easiest place
// to add it as a test case. // to add it as a test case.
var tests_wild = []struct{ e1, e2, expected string }{ var testsWild = []struct{ e1, e2, expected string }{
{"mathoverflow.net.", ".", "mathoverflow.net"}, {"mathoverflow.net.", ".", "mathoverflow.net"},
{"mathoverflow.net", ".", "mathoverflow.net"}, {"mathoverflow.net", ".", "mathoverflow.net"},
{"", ".", "@"}, {"", ".", "@"},
{"@", ".", "@"}, {"@", ".", "@"},
} }
for i, test := range tests_wild { for i, test := range testsWild {
actual := TrimDomainName(test.e1, test.e2) actual := TrimDomainName(test.e1, test.e2)
if test.expected != actual { if test.expected != actual {
t.Errorf("%d TrimDomainName(%#v, %#v): expected (%v) got (%v)\n", i, test.e1, test.e2, test.expected, actual) t.Errorf("%d TrimDomainName(%#v, %#v): expected %v, got %v\n", i, test.e1, test.e2, test.expected, actual)
} }
} }
} }

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше