summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--Godeps/Godeps.json52
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/.gitignore24
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/LICENSE21
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/README.md223
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/client.go167
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/client_mock.go21
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/client_mock_test.go24
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/feedback.go102
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/legacy.go15
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/legacy_test.go27
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/mock_feedback_server.go53
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/push_notification.go175
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/push_notification_response.go36
-rw-r--r--Godeps/_workspace/src/github.com/anachronistic/apns/push_notification_test.go111
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypass.go151
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypasssafe.go37
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common.go341
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common_test.go298
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/config.go297
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/doc.go202
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump.go509
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump_test.go1042
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go98
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go26
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/example_test.go226
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format.go419
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format_test.go1558
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internal_test.go87
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go101
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew.go148
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew_test.go309
-rw-r--r--Godeps/_workspace/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go82
-rw-r--r--Godeps/_workspace/src/github.com/go-gorp/gorp/README.md5
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/.gitignore0
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/.travis.yml15
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/LICENSE27
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/README.md55
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/add.go104
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/bind.go135
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/client.go23
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/compare.go85
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/conn.go369
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/control.go332
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/debug.go24
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/del.go79
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/dn.go155
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/dn_test.go70
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/doc.go4
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/error.go137
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/example_test.go305
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/filter.go456
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/filter_test.go248
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/ldap.go286
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/ldap_test.go249
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/modify.go156
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/passwdmodify.go137
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/search.go403
-rw-r--r--Godeps/_workspace/src/github.com/go-ldap/ldap/search_test.go31
-rw-r--r--Godeps/_workspace/src/github.com/gorilla/websocket/client.go13
-rw-r--r--Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go20
-rw-r--r--Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go32
-rw-r--r--Godeps/_workspace/src/github.com/gorilla/websocket/examples/echo/client.go38
-rw-r--r--Godeps/_workspace/src/github.com/lib/pq/conn.go14
-rw-r--r--Godeps/_workspace/src/github.com/lib/pq/conn_test.go53
-rw-r--r--Godeps/_workspace/src/github.com/pborman/uuid/sql.go18
-rw-r--r--Godeps/_workspace/src/github.com/pborman/uuid/sql_test.go5
-rw-r--r--Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib.go758
-rw-r--r--Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib_test.go352
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/.gitignore22
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/LICENSE.md23
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/README.md3
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/accessors.go179
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/accessors_test.go145
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt14
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html86
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt286
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt20
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/constants.go13
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/conversions.go117
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/conversions_test.go94
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/doc.go72
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/fixture_test.go98
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/map.go222
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/map_for_test.go10
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/map_test.go147
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/mutations.go81
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/mutations_test.go77
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/security.go14
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/security_test.go12
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/simple_example_test.go41
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/tests.go17
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/tests_test.go24
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen.go2881
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen_test.go2867
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/value.go56
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/objx/value_test.go66
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go979
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go1089
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go45
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/assert/errors.go10
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go284
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go611
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go157
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go86
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go43
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go624
-rw-r--r--Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go989
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/.travis.yml15
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/LICENSE27
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/README.md24
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/ber.go504
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/ber_test.go168
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/content_int.go25
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/header.go29
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/header_test.go135
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/identifier.go103
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/identifier_test.go344
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/length.go71
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/length_test.go158
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/suite_test.go182
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc1.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc10.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc11.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc12.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc13.berbin0 -> 11 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc14.berbin0 -> 7 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc15.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc16.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc17.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc18.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc19.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc2.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc20.berbin0 -> 11 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc21.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc22.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc23.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc24.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc25.berbin0 -> 5 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc26.berbin0 -> 5 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc27.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc28.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc29.berbin0 -> 3 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc3.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc30.berbin0 -> 5 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc31.berbin0 -> 4 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc32.berbin0 -> 2 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc33.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc34.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc35.berbin0 -> 16 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc36.berbin0 -> 20 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc37.berbin0 -> 14 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc38.berbin0 -> 16 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc39.berbin0 -> 2 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc4.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc40.berbin0 -> 2 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc41.berbin0 -> 16 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc42.berbin0 -> 14 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc43.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc44.berbin0 -> 2 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc45.berbin0 -> 2 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc46.berbin0 -> 11 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc47.berbin0 -> 16 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc48.berbin0 -> 16 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc5.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc6.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc7.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc8.berbin0 -> 5 bytes
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc9.ber1
-rw-r--r--Godeps/_workspace/src/gopkg.in/asn1-ber.v1/util.go24
-rw-r--r--Makefile31
-rw-r--r--api/file.go36
-rw-r--r--api/file_test.go7
-rw-r--r--api/team.go5
-rw-r--r--api/user.go100
-rw-r--r--doc/developer/tests/test-markdown-lists.md19
-rw-r--r--doc/help/Creating-Teams.md38
-rw-r--r--doc/install/Configuration-Settings.md46
-rw-r--r--doc/install/LDAP-Setup.md34
-rw-r--r--doc/install/Production-Debian.md29
-rw-r--r--doc/install/Production-RHEL6.md219
-rw-r--r--doc/install/Production-RHEL7.md226
-rw-r--r--doc/install/Production-Ubuntu.md17
-rw-r--r--doc/process/release-process.md224
-rw-r--r--einterfaces/ldap.go22
-rw-r--r--einterfaces/oauthproviders.go29
-rw-r--r--mattermost.go23
-rw-r--r--model/client.go2
-rw-r--r--model/config.go43
-rw-r--r--model/file_info.go72
-rw-r--r--model/file_info_test.go76
-rw-r--r--model/gitlab/gitlab.go (renamed from model/gitlab.go)34
-rw-r--r--model/version.go1
-rw-r--r--store/sql_user_store.go2
-rw-r--r--utils/config.go4
-rw-r--r--utils/diagnostic.go1
-rw-r--r--web/react/components/about_build_modal.jsx8
-rw-r--r--web/react/components/admin_console/admin_controller.jsx3
-rw-r--r--web/react/components/admin_console/admin_sidebar.jsx2
-rw-r--r--web/react/components/admin_console/ldap_settings.jsx394
-rw-r--r--web/react/components/admin_console/rate_settings.jsx2
-rw-r--r--web/react/components/login.jsx146
-rw-r--r--web/react/components/login_email.jsx137
-rw-r--r--web/react/components/login_ldap.jsx110
-rw-r--r--web/react/components/rhs_root_post.jsx1
-rw-r--r--web/react/components/settings_sidebar.jsx7
-rw-r--r--web/react/components/sidebar.jsx10
-rw-r--r--web/react/components/sidebar_right.jsx19
-rw-r--r--web/react/components/signup_team.jsx11
-rw-r--r--web/react/components/signup_user_complete.jsx14
-rw-r--r--web/react/components/suggestion/search_channel_provider.jsx2
-rw-r--r--web/react/components/suggestion/search_user_provider.jsx2
-rw-r--r--web/react/components/team_signup_choose_auth.jsx18
-rw-r--r--web/react/components/team_signup_with_sso.jsx12
-rw-r--r--web/react/components/user_settings/custom_theme_chooser.jsx2
-rw-r--r--web/react/components/view_image.jsx356
-rw-r--r--web/react/stores/file_store.jsx60
-rw-r--r--web/react/utils/async_client.jsx28
-rw-r--r--web/react/utils/client.jsx26
-rw-r--r--web/react/utils/constants.jsx2
-rw-r--r--web/react/utils/emoticons.jsx42
-rw-r--r--web/react/utils/utils.jsx10
-rw-r--r--web/sass-files/sass/partials/_base.scss4
-rw-r--r--web/sass-files/sass/partials/_content.scss2
-rw-r--r--web/sass-files/sass/partials/_files.scss5
-rw-r--r--web/sass-files/sass/partials/_popover.scss5
-rw-r--r--web/sass-files/sass/partials/_post.scss15
-rw-r--r--web/sass-files/sass/partials/_post_right.scss4
-rw-r--r--web/sass-files/sass/partials/_responsive.scss7
-rw-r--r--web/sass-files/sass/partials/_search.scss9
-rw-r--r--web/sass-files/sass/partials/_settings.scss244
-rw-r--r--web/sass-files/sass/partials/_sidebar--left.scss6
-rw-r--r--web/sass-files/sass/partials/_sidebar--right.scss6
-rw-r--r--web/static/js/velocity.min.js4
-rw-r--r--web/templates/head.html1
-rw-r--r--web/web.go30
236 files changed, 8333 insertions, 21387 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0bbb2be93..d5094f06e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -90,6 +90,7 @@ Multiple settings were added to [`config.json`](./config/config.json). These opt
#### Known Issues
+- System Console does not save Email Settings when "Save" is clicked
- When navigating to a page with new messages as well as message containing inline images added via markdown, the channel may move up and down while loading the inline images
- Microsoft Edge does not yet support drag and drop
- Media files of type .avi .mkv .wmv .mov .flv .mp4a do not play properly
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 0ec79e0a6..bd2392f90 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -8,19 +8,11 @@
"Rev": "c3294304d93f48a37d3bed1d382882a9c2989f99"
},
{
- "ImportPath": "github.com/anachronistic/apns",
- "Rev": "f90152b7e0ae845938ce1258d90072fd116131ac"
- },
- {
"ImportPath": "github.com/braintree/manners",
"Comment": "0.4.0-9-g3fdfada",
"Rev": "3fdfadabc96863ceec055bd73ab1e80324e72706"
},
{
- "ImportPath": "github.com/davecgh/go-spew/spew",
- "Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d"
- },
- {
"ImportPath": "github.com/disintegration/imaging",
"Rev": "546cb3c5137b3f1232e123a26aa033aade6b3066"
},
@@ -34,8 +26,13 @@
},
{
"ImportPath": "github.com/go-gorp/gorp",
- "Comment": "v1.7-146-gc391a3d",
- "Rev": "c391a3da75cf2003f4bf4763d0b5755c4500aef1"
+ "Comment": "v1.7-148-gc0e2e1a",
+ "Rev": "c0e2e1a7adaa00e47c4f6ae8faaad6991a4570ac"
+ },
+ {
+ "ImportPath": "github.com/go-ldap/ldap",
+ "Comment": "v2.2",
+ "Rev": "e9a325d64989e2844be629682cb085d2c58eef8d"
},
{
"ImportPath": "github.com/go-sql-driver/mysql",
@@ -69,12 +66,12 @@
},
{
"ImportPath": "github.com/gorilla/websocket",
- "Rev": "361d4c0ffd78338ebe0a9e6320cdbe115d7dc026"
+ "Rev": "3986be78bf859e01f01af631ad76da5b269d270c"
},
{
"ImportPath": "github.com/lib/pq",
- "Comment": "go1.0-cutoff-61-g83c4f41",
- "Rev": "83c4f410d0aed80a0f44bac6a576a7f2435791f3"
+ "Comment": "go1.0-cutoff-63-g11fc39a",
+ "Rev": "11fc39a580a008f1f39bb3d11d984fb34ed778d9"
},
{
"ImportPath": "github.com/mssola/user_agent",
@@ -83,11 +80,7 @@
},
{
"ImportPath": "github.com/pborman/uuid",
- "Rev": "cccd189d45f7ac3368a0d127efb7f4d08ae0b655"
- },
- {
- "ImportPath": "github.com/pmezard/go-difflib/difflib",
- "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d"
+ "Rev": "dee7705ef7b324f27ceb85a121c61f2c2e8ce988"
},
{
"ImportPath": "github.com/rwcarlsen/goexif/exif",
@@ -98,30 +91,16 @@
"Rev": "709fab3d192d7c62f86043caff1e7e3fb0f42bd8"
},
{
- "ImportPath": "github.com/stretchr/objx",
- "Rev": "1a9d0bb9f541897e62256577b352fdbc1fb4fd94"
- },
- {
- "ImportPath": "github.com/stretchr/testify/assert",
- "Comment": "v1.0-83-gd797d25",
- "Rev": "d797d25e0fa6d53be3b1a216d24e868d6a1912ef"
- },
- {
- "ImportPath": "github.com/stretchr/testify/mock",
- "Comment": "v1.0-83-gd797d25",
- "Rev": "d797d25e0fa6d53be3b1a216d24e868d6a1912ef"
- },
- {
"ImportPath": "github.com/vaughan0/go-ini",
"Rev": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1"
},
{
"ImportPath": "golang.org/x/crypto/bcrypt",
- "Rev": "beef0f4390813b96e8e68fd78570396d0f4751fc"
+ "Rev": "f18420efc3b4f8e9f3d51f6bd2476e92c46260e9"
},
{
"ImportPath": "golang.org/x/crypto/blowfish",
- "Rev": "beef0f4390813b96e8e68fd78570396d0f4751fc"
+ "Rev": "f18420efc3b4f8e9f3d51f6bd2476e92c46260e9"
},
{
"ImportPath": "golang.org/x/image/bmp",
@@ -140,6 +119,11 @@
"Rev": "baddd3465a05d84a6d8d3507547a91cb188c81ea"
},
{
+ "ImportPath": "gopkg.in/asn1-ber.v1",
+ "Comment": "v1.1",
+ "Rev": "4e86f4367175e39f69d9358a5f17b4dda270378d"
+ },
+ {
"ImportPath": "gopkg.in/fsnotify.v1",
"Comment": "v1.2.5",
"Rev": "2cdd39bd6129c6a49c74fb07fb9d77ba1271c572"
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/.gitignore b/Godeps/_workspace/src/github.com/anachronistic/apns/.gitignore
deleted file mode 100644
index d73587219..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
-*.o
-*.a
-*.so
-
-# Folders
-_obj
-_test
-
-# Architecture specific extensions/prefixes
-*.[568vq]
-[568vq].out
-
-*.cgo1.go
-*.cgo2.c
-_cgo_defun.c
-_cgo_gotypes.go
-_cgo_export.*
-
-_testmain.go
-
-*.exe
-
-*.pem \ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/LICENSE b/Godeps/_workspace/src/github.com/anachronistic/apns/LICENSE
deleted file mode 100644
index b80ffbd8d..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Alan Harris
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE. \ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/README.md b/Godeps/_workspace/src/github.com/anachronistic/apns/README.md
deleted file mode 100644
index 02b012fd3..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/README.md
+++ /dev/null
@@ -1,223 +0,0 @@
-# apns
-
-Utilities for Apple Push Notification and Feedback Services.
-
-[![GoDoc](https://godoc.org/github.com/anachronistic/apns?status.png)](https://godoc.org/github.com/anachronistic/apns)
-
-## Installation
-
-`go get github.com/anachronistic/apns`
-
-## Documentation
-
-- [APNS package documentation](http://godoc.org/github.com/anachronistic/apns)
-- [Information on the APN JSON payloads](http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html)
-- [Information on the APN binary protocols](http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html)
-- [Information on APN troubleshooting](http://developer.apple.com/library/ios/#technotes/tn2265/_index.html)
-
-## Usage
-
-### Creating pns and payloads manually
-```go
-package main
-
-import (
- "fmt"
- apns "github.com/anachronistic/apns"
-)
-
-func main() {
- payload := apns.NewPayload()
- payload.Alert = "Hello, world!"
- payload.Badge = 42
- payload.Sound = "bingbong.aiff"
-
- pn := apns.NewPushNotification()
- pn.AddPayload(payload)
-
- alert, _ := pn.PayloadString()
- fmt.Println(alert)
-}
-```
-
-#### Returns
-```json
-{
- "aps": {
- "alert": "Hello, world!",
- "badge": 42,
- "sound": "bingbong.aiff"
- }
-}
-```
-
-### Using an alert dictionary for complex payloads
-```go
-package main
-
-import (
- "fmt"
- apns "github.com/anachronistic/apns"
-)
-
-func main() {
- args := make([]string, 1)
- args[0] = "localized args"
-
- dict := apns.NewAlertDictionary()
- dict.Body = "Alice wants Bob to join in the fun!"
- dict.ActionLocKey = "Play a Game!"
- dict.LocKey = "localized key"
- dict.LocArgs = args
- dict.LaunchImage = "image.jpg"
-
- payload := apns.NewPayload()
- payload.Alert = dict
- payload.Badge = 42
- payload.Sound = "bingbong.aiff"
-
- pn := apns.NewPushNotification()
- pn.AddPayload(payload)
-
- alert, _ := pn.PayloadString()
- fmt.Println(alert)
-}
-```
-
-#### Returns
-```json
-{
- "aps": {
- "alert": {
- "body": "Alice wants Bob to join in the fun!",
- "action-loc-key": "Play a Game!",
- "loc-key": "localized key",
- "loc-args": [
- "localized args"
- ],
- "launch-image": "image.jpg"
- },
- "badge": 42,
- "sound": "bingbong.aiff"
- }
-}
-```
-
-### Setting custom properties
-```go
-package main
-
-import (
- "fmt"
- apns "github.com/anachronistic/apns"
-)
-
-func main() {
- payload := apns.NewPayload()
- payload.Alert = "Hello, world!"
- payload.Badge = 42
- payload.Sound = "bingbong.aiff"
-
- pn := apns.NewPushNotification()
- pn.AddPayload(payload)
-
- pn.Set("foo", "bar")
- pn.Set("doctor", "who?")
- pn.Set("the_ultimate_answer", 42)
-
- alert, _ := pn.PayloadString()
- fmt.Println(alert)
-}
-```
-
-#### Returns
-```json
-{
- "aps": {
- "alert": "Hello, world!",
- "badge": 42,
- "sound": "bingbong.aiff"
- },
- "doctor": "who?",
- "foo": "bar",
- "the_ultimate_answer": 42
-}
-```
-
-### Sending a notification
-```go
-package main
-
-import (
- "fmt"
- apns "github.com/anachronistic/apns"
-)
-
-func main() {
- payload := apns.NewPayload()
- payload.Alert = "Hello, world!"
- payload.Badge = 42
- payload.Sound = "bingbong.aiff"
-
- pn := apns.NewPushNotification()
- pn.DeviceToken = "YOUR_DEVICE_TOKEN_HERE"
- pn.AddPayload(payload)
-
- client := apns.NewClient("gateway.sandbox.push.apple.com:2195", "YOUR_CERT_PEM", "YOUR_KEY_NOENC_PEM")
- resp := client.Send(pn)
-
- alert, _ := pn.PayloadString()
- fmt.Println(" Alert:", alert)
- fmt.Println("Success:", resp.Success)
- fmt.Println(" Error:", resp.Error)
-}
-```
-
-#### Returns
-```shell
- Alert: {"aps":{"alert":"Hello, world!","badge":42,"sound":"bingbong.aiff"}}
-Success: true
- Error: <nil>
-```
-
-### Checking the feedback service
-```go
-package main
-
-import (
- "fmt"
- apns "github.com/anachronistic/apns"
- "os"
-)
-
-func main() {
- fmt.Println("- connecting to check for deactivated tokens (maximum read timeout =", apns.FeedbackTimeoutSeconds, "seconds)")
-
- client := apns.NewClient("feedback.sandbox.push.apple.com:2196", "YOUR_CERT_PEM", "YOUR_KEY_NOENC_PEM")
- go client.ListenForFeedback()
-
- for {
- select {
- case resp := <-apns.FeedbackChannel:
- fmt.Println("- recv'd:", resp.DeviceToken)
- case <-apns.ShutdownChannel:
- fmt.Println("- nothing returned from the feedback service")
- os.Exit(1)
- }
- }
-}
-```
-
-#### Returns
-```shell
-- connecting to check for deactivated tokens (maximum read timeout = 5 seconds)
-- nothing returned from the feedback service
-exit status 1
-```
-
-Your output will differ if the service returns device tokens.
-
-```shell
-- recv'd: DEVICE_TOKEN_HERE
-...etc.
-```
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/client.go b/Godeps/_workspace/src/github.com/anachronistic/apns/client.go
deleted file mode 100644
index 3fc079a87..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/client.go
+++ /dev/null
@@ -1,167 +0,0 @@
-package apns
-
-import (
- "crypto/tls"
- "errors"
- "net"
- "strings"
- "time"
-)
-
-var _ APNSClient = &Client{}
-
-// APNSClient is an APNS client.
-type APNSClient interface {
- ConnectAndWrite(resp *PushNotificationResponse, payload []byte) (err error)
- Send(pn *PushNotification) (resp *PushNotificationResponse)
-}
-
-// Client contains the fields necessary to communicate
-// with Apple, such as the gateway to use and your
-// certificate contents.
-//
-// You'll need to provide your own CertificateFile
-// and KeyFile to send notifications. Ideally, you'll
-// just set the CertificateFile and KeyFile fields to
-// a location on drive where the certs can be loaded,
-// but if you prefer you can use the CertificateBase64
-// and KeyBase64 fields to store the actual contents.
-type Client struct {
- Gateway string
- CertificateFile string
- CertificateBase64 string
- KeyFile string
- KeyBase64 string
-}
-
-// BareClient can be used to set the contents of your
-// certificate and key blocks manually.
-func BareClient(gateway, certificateBase64, keyBase64 string) (c *Client) {
- c = new(Client)
- c.Gateway = gateway
- c.CertificateBase64 = certificateBase64
- c.KeyBase64 = keyBase64
- return
-}
-
-// NewClient assumes you'll be passing in paths that
-// point to your certificate and key.
-func NewClient(gateway, certificateFile, keyFile string) (c *Client) {
- c = new(Client)
- c.Gateway = gateway
- c.CertificateFile = certificateFile
- c.KeyFile = keyFile
- return
-}
-
-// Send connects to the APN service and sends your push notification.
-// Remember that if the submission is successful, Apple won't reply.
-func (client *Client) Send(pn *PushNotification) (resp *PushNotificationResponse) {
- resp = new(PushNotificationResponse)
-
- payload, err := pn.ToBytes()
- if err != nil {
- resp.Success = false
- resp.Error = err
- return
- }
-
- err = client.ConnectAndWrite(resp, payload)
- if err != nil {
- resp.Success = false
- resp.Error = err
- return
- }
-
- resp.Success = true
- resp.Error = nil
-
- return
-}
-
-// ConnectAndWrite establishes the connection to Apple and handles the
-// transmission of your push notification, as well as waiting for a reply.
-//
-// In lieu of a timeout (which would be available in Go 1.1)
-// we use a timeout channel pattern instead. We start two goroutines,
-// one of which just sleeps for TimeoutSeconds seconds, while the other
-// waits for a response from the Apple servers.
-//
-// Whichever channel puts data on first is the "winner". As such, it's
-// possible to get a false positive if Apple takes a long time to respond.
-// It's probably not a deal-breaker, but something to be aware of.
-func (client *Client) ConnectAndWrite(resp *PushNotificationResponse, payload []byte) (err error) {
- var cert tls.Certificate
-
- if len(client.CertificateBase64) == 0 && len(client.KeyBase64) == 0 {
- // The user did not specify raw block contents, so check the filesystem.
- cert, err = tls.LoadX509KeyPair(client.CertificateFile, client.KeyFile)
- } else {
- // The user provided the raw block contents, so use that.
- cert, err = tls.X509KeyPair([]byte(client.CertificateBase64), []byte(client.KeyBase64))
- }
-
- if err != nil {
- return err
- }
-
- gatewayParts := strings.Split(client.Gateway, ":")
- conf := &tls.Config{
- Certificates: []tls.Certificate{cert},
- ServerName: gatewayParts[0],
- }
-
- conn, err := net.Dial("tcp", client.Gateway)
- if err != nil {
- return err
- }
- defer conn.Close()
-
- tlsConn := tls.Client(conn, conf)
- err = tlsConn.Handshake()
- if err != nil {
- return err
- }
- defer tlsConn.Close()
-
- _, err = tlsConn.Write(payload)
- if err != nil {
- return err
- }
-
- // Create one channel that will serve to handle
- // timeouts when the notification succeeds.
- timeoutChannel := make(chan bool, 1)
- go func() {
- time.Sleep(time.Second * TimeoutSeconds)
- timeoutChannel <- true
- }()
-
- // This channel will contain the binary response
- // from Apple in the event of a failure.
- responseChannel := make(chan []byte, 1)
- go func() {
- buffer := make([]byte, 6, 6)
- tlsConn.Read(buffer)
- responseChannel <- buffer
- }()
-
- // First one back wins!
- // The data structure for an APN response is as follows:
- //
- // command -> 1 byte
- // status -> 1 byte
- // identifier -> 4 bytes
- //
- // The first byte will always be set to 8.
- select {
- case r := <-responseChannel:
- resp.Success = false
- resp.AppleResponse = ApplePushResponses[r[1]]
- err = errors.New(resp.AppleResponse)
- case <-timeoutChannel:
- resp.Success = true
- }
-
- return err
-}
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/client_mock.go b/Godeps/_workspace/src/github.com/anachronistic/apns/client_mock.go
deleted file mode 100644
index 29a1f4b23..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/client_mock.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package apns
-
-import "github.com/stretchr/testify/mock"
-
-type MockClient struct {
- mock.Mock
-}
-
-func (m *MockClient) ConnectAndWrite(resp *PushNotificationResponse, payload []byte) (err error) {
- return m.Called(resp, payload).Error(0)
-}
-
-func (m *MockClient) Send(pn *PushNotification) (resp *PushNotificationResponse) {
- r := m.Called(pn).Get(0)
- if r != nil {
- if r, ok := r.(*PushNotificationResponse); ok {
- return r
- }
- }
- return nil
-}
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/client_mock_test.go b/Godeps/_workspace/src/github.com/anachronistic/apns/client_mock_test.go
deleted file mode 100644
index 86e997b5a..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/client_mock_test.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package apns
-
-import (
- "errors"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestMockClientConnectAndWrite(t *testing.T) {
- m := &MockClient{}
- m.On("ConnectAndWrite", (*PushNotificationResponse)(nil), []byte(nil)).Return(nil)
- assert.Nil(t, m.ConnectAndWrite(nil, nil))
- m.On("ConnectAndWrite", &PushNotificationResponse{}, []byte{}).Return(errors.New("test"))
- assert.Equal(t, errors.New("test"), m.ConnectAndWrite(&PushNotificationResponse{}, []byte{}))
-}
-
-func TestMockClientSend(t *testing.T) {
- m := &MockClient{}
- m.On("Send", (*PushNotification)(nil)).Return(nil)
- assert.Nil(t, m.Send(nil))
- m.On("Send", &PushNotification{}).Return(&PushNotificationResponse{})
- assert.Equal(t, &PushNotificationResponse{}, m.Send(&PushNotification{}))
-}
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/feedback.go b/Godeps/_workspace/src/github.com/anachronistic/apns/feedback.go
deleted file mode 100644
index 32e7f0f15..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/feedback.go
+++ /dev/null
@@ -1,102 +0,0 @@
-package apns
-
-import (
- "bytes"
- "crypto/tls"
- "encoding/binary"
- "encoding/hex"
- "errors"
- "net"
- "strings"
- "time"
-)
-
-// Wait at most this many seconds for feedback data from Apple.
-const FeedbackTimeoutSeconds = 5
-
-// FeedbackChannel will receive individual responses from Apple.
-var FeedbackChannel = make(chan (*FeedbackResponse))
-
-// If there's nothing to read, ShutdownChannel gets a true.
-var ShutdownChannel = make(chan bool)
-
-// FeedbackResponse represents a device token that Apple has
-// indicated should not be sent to in the future.
-type FeedbackResponse struct {
- Timestamp uint32
- DeviceToken string
-}
-
-// NewFeedbackResponse creates and returns a FeedbackResponse structure.
-func NewFeedbackResponse() (resp *FeedbackResponse) {
- resp = new(FeedbackResponse)
- return
-}
-
-// ListenForFeedback connects to the Apple Feedback Service
-// and checks for device tokens.
-//
-// Feedback consists of device tokens that should
-// not be sent to in the future; Apple *does* monitor that
-// you respect this so you should be checking it ;)
-func (client *Client) ListenForFeedback() (err error) {
- var cert tls.Certificate
-
- if len(client.CertificateBase64) == 0 && len(client.KeyBase64) == 0 {
- // The user did not specify raw block contents, so check the filesystem.
- cert, err = tls.LoadX509KeyPair(client.CertificateFile, client.KeyFile)
- } else {
- // The user provided the raw block contents, so use that.
- cert, err = tls.X509KeyPair([]byte(client.CertificateBase64), []byte(client.KeyBase64))
- }
-
- if err != nil {
- return err
- }
-
- gatewayParts := strings.Split(client.Gateway, ":")
- conf := &tls.Config{
- Certificates: []tls.Certificate{cert},
- ServerName: gatewayParts[0],
- }
-
- conn, err := net.Dial("tcp", client.Gateway)
- if err != nil {
- return err
- }
- defer conn.Close()
- conn.SetReadDeadline(time.Now().Add(FeedbackTimeoutSeconds * time.Second))
-
- tlsConn := tls.Client(conn, conf)
- err = tlsConn.Handshake()
- if err != nil {
- return err
- }
-
- var tokenLength uint16
- buffer := make([]byte, 38, 38)
- deviceToken := make([]byte, 32, 32)
-
- for {
- _, err := tlsConn.Read(buffer)
- if err != nil {
- ShutdownChannel <- true
- break
- }
-
- resp := NewFeedbackResponse()
-
- r := bytes.NewReader(buffer)
- binary.Read(r, binary.BigEndian, &resp.Timestamp)
- binary.Read(r, binary.BigEndian, &tokenLength)
- binary.Read(r, binary.BigEndian, &deviceToken)
- if tokenLength != 32 {
- return errors.New("token length should be equal to 32, but isn't")
- }
- resp.DeviceToken = hex.EncodeToString(deviceToken)
-
- FeedbackChannel <- resp
- }
-
- return nil
-}
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/legacy.go b/Godeps/_workspace/src/github.com/anachronistic/apns/legacy.go
deleted file mode 100644
index 44da3dde8..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/legacy.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package apns
-
-// This file exists to support backward-compatibility
-// as I gradually refactor and overhaul. Ideally, golint
-// should only complain about this file (and we should
-// try to keep its complaints to a minimum).
-
-// These variables map old identifiers to their current format.
-var (
- APPLE_PUSH_RESPONSES = ApplePushResponses
- FEEDBACK_TIMEOUT_SECONDS = FeedbackTimeoutSeconds
- IDENTIFIER_UBOUND = IdentifierUbound
- MAX_PAYLOAD_SIZE_BYTES = MaxPayloadSizeBytes
- TIMEOUT_SECONDS = TimeoutSeconds
-)
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/legacy_test.go b/Godeps/_workspace/src/github.com/anachronistic/apns/legacy_test.go
deleted file mode 100644
index 4b983c128..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/legacy_test.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package apns
-
-import (
- "reflect"
- "testing"
-)
-
-// These identifiers were changed to resolve golint violations.
-// However, it's possible that legacy code may rely on them. This
-// will help avoid springing a breaking change on people.
-func TestLegacyConstants(t *testing.T) {
- if !reflect.DeepEqual(APPLE_PUSH_RESPONSES, ApplePushResponses) {
- t.Error("expected APPLE_PUSH_RESPONSES to equal ApplePushResponses")
- }
- if !reflect.DeepEqual(FEEDBACK_TIMEOUT_SECONDS, FeedbackTimeoutSeconds) {
- t.Error("expected FEEDBACK_TIMEOUT_SECONDS to equal FeedbackTimeoutSeconds")
- }
- if !reflect.DeepEqual(IDENTIFIER_UBOUND, IdentifierUbound) {
- t.Error("expected IDENTIFIER_UBOUND to equal IdentifierUbound")
- }
- if !reflect.DeepEqual(MAX_PAYLOAD_SIZE_BYTES, MaxPayloadSizeBytes) {
- t.Error("expected MAX_PAYLOAD_SIZE_BYTES to equal MaxPayloadSizeBytes")
- }
- if !reflect.DeepEqual(TIMEOUT_SECONDS, TimeoutSeconds) {
- t.Error("expected TIMEOUT_SECONDS to equal TimeoutSeconds")
- }
-}
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/mock_feedback_server.go b/Godeps/_workspace/src/github.com/anachronistic/apns/mock_feedback_server.go
deleted file mode 100644
index d7536f261..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/mock_feedback_server.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package apns
-
-import (
- "bytes"
- "crypto/tls"
- "encoding/binary"
- "log"
- "net"
- "time"
-)
-
-// StartMockFeedbackServer spins up a simple stand-in for the Apple
-// feedback service that can be used for testing purposes. Doesn't
-// handle many errors, etc. Just for the sake of having something "live"
-// to hit.
-func StartMockFeedbackServer(certFile, keyFile string) {
- cert, err := tls.LoadX509KeyPair(certFile, keyFile)
- if err != nil {
- log.Panic(err)
- }
- config := tls.Config{Certificates: []tls.Certificate{cert}, ClientAuth: tls.RequireAnyClientCert}
- log.Print("- starting Mock Apple Feedback TCP server at 0.0.0.0:5555")
-
- srv, _ := tls.Listen("tcp", "0.0.0.0:5555", &config)
- for {
- conn, err := srv.Accept()
- if err != nil {
- log.Panic(err)
- }
- go loop(conn)
- }
-}
-
-// Writes binary data to the client in the same
-// manner as the Apple service would.
-//
-// [4 bytes, 2 bytes, 32 bytes] = 38 bytes total
-func loop(conn net.Conn) {
- defer conn.Close()
- for {
- timeT := uint32(1368809290) // 2013-05-17 12:48:10 -0400
- token := "abcd1234efab5678abcd1234efab5678"
-
- buf := new(bytes.Buffer)
- binary.Write(buf, binary.BigEndian, timeT)
- binary.Write(buf, binary.BigEndian, uint16(len(token)))
- binary.Write(buf, binary.BigEndian, []byte(token))
- conn.Write(buf.Bytes())
-
- dur, _ := time.ParseDuration("1s")
- time.Sleep(dur)
- }
-}
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/push_notification.go b/Godeps/_workspace/src/github.com/anachronistic/apns/push_notification.go
deleted file mode 100644
index e6b58d575..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/push_notification.go
+++ /dev/null
@@ -1,175 +0,0 @@
-package apns
-
-import (
- "bytes"
- "encoding/binary"
- "encoding/hex"
- "encoding/json"
- "errors"
- "math/rand"
- "strconv"
- "time"
-)
-
-// Push commands always start with command value 2.
-const pushCommandValue = 2
-
-// Your total notification payload cannot exceed 2 KB.
-const MaxPayloadSizeBytes = 2048
-
-// Every push notification gets a pseudo-unique identifier;
-// this establishes the upper boundary for it. Apple will return
-// this identifier if there is an issue sending your notification.
-const IdentifierUbound = 9999
-
-// Constants related to the payload fields and their lengths.
-const (
- deviceTokenItemid = 1
- payloadItemid = 2
- notificationIdentifierItemid = 3
- expirationDateItemid = 4
- priorityItemid = 5
- deviceTokenLength = 32
- notificationIdentifierLength = 4
- expirationDateLength = 4
- priorityLength = 1
-)
-
-// Payload contains the notification data for your request.
-//
-// Alert is an interface here because it supports either a string
-// or a dictionary, represented within by an AlertDictionary struct.
-type Payload struct {
- Alert interface{} `json:"alert,omitempty"`
- Badge int `json:"badge,omitempty"`
- Sound string `json:"sound,omitempty"`
- ContentAvailable int `json:"content-available,omitempty"`
- Category string `json:"category,omitempty"`
-}
-
-// NewPayload creates and returns a Payload structure.
-func NewPayload() *Payload {
- return new(Payload)
-}
-
-// AlertDictionary is a more complex notification payload.
-//
-// From the APN docs: "Use the ... alert dictionary in general only if you absolutely need to."
-// The AlertDictionary is suitable for specific localization needs.
-type AlertDictionary struct {
- Body string `json:"body,omitempty"`
- ActionLocKey string `json:"action-loc-key,omitempty"`
- LocKey string `json:"loc-key,omitempty"`
- LocArgs []string `json:"loc-args,omitempty"`
- LaunchImage string `json:"launch-image,omitempty"`
-}
-
-// NewAlertDictionary creates and returns an AlertDictionary structure.
-func NewAlertDictionary() *AlertDictionary {
- return new(AlertDictionary)
-}
-
-// PushNotification is the wrapper for the Payload.
-// The length fields are computed in ToBytes() and aren't represented here.
-type PushNotification struct {
- Identifier int32
- Expiry uint32
- DeviceToken string
- payload map[string]interface{}
- Priority uint8
-}
-
-// NewPushNotification creates and returns a PushNotification structure.
-// It also initializes the pseudo-random identifier.
-func NewPushNotification() (pn *PushNotification) {
- pn = new(PushNotification)
- pn.payload = make(map[string]interface{})
- pn.Identifier = rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(IdentifierUbound)
- pn.Priority = 10
- return
-}
-
-// AddPayload sets the "aps" payload section of the request. It also
-// has a hack described within to deal with specific zero values.
-func (pn *PushNotification) AddPayload(p *Payload) {
- // This deserves some explanation.
- //
- // Setting an exported field of type int to 0
- // triggers the omitempty behavior if you've set it.
- // Since the badge is optional, we should omit it if
- // it's not set. However, we want to include it if the
- // value is 0, so there's a hack in push_notification.go
- // that exploits the fact that Apple treats -1 for a
- // badge value as though it were 0 (i.e. it clears the
- // badge but doesn't stop the notification from going
- // through successfully.)
- //
- // Still a hack though :)
- if p.Badge == 0 {
- p.Badge = -1
- }
- pn.Set("aps", p)
-}
-
-// Get returns the value of a payload key, if it exists.
-func (pn *PushNotification) Get(key string) interface{} {
- return pn.payload[key]
-}
-
-// Set defines the value of a payload key.
-func (pn *PushNotification) Set(key string, value interface{}) {
- pn.payload[key] = value
-}
-
-// PayloadJSON returns the current payload in JSON format.
-func (pn *PushNotification) PayloadJSON() ([]byte, error) {
- return json.Marshal(pn.payload)
-}
-
-// PayloadString returns the current payload in string format.
-func (pn *PushNotification) PayloadString() (string, error) {
- j, err := pn.PayloadJSON()
- return string(j), err
-}
-
-// ToBytes returns a byte array of the complete PushNotification
-// struct. This array is what should be transmitted to the APN Service.
-func (pn *PushNotification) ToBytes() ([]byte, error) {
- token, err := hex.DecodeString(pn.DeviceToken)
- if err != nil {
- return nil, err
- }
- if len(token) != deviceTokenLength {
- return nil, errors.New("device token has incorrect length")
- }
- payload, err := pn.PayloadJSON()
- if err != nil {
- return nil, err
- }
- if len(payload) > MaxPayloadSizeBytes {
- return nil, errors.New("payload is larger than the " + strconv.Itoa(MaxPayloadSizeBytes) + " byte limit")
- }
-
- frameBuffer := new(bytes.Buffer)
- binary.Write(frameBuffer, binary.BigEndian, uint8(deviceTokenItemid))
- binary.Write(frameBuffer, binary.BigEndian, uint16(deviceTokenLength))
- binary.Write(frameBuffer, binary.BigEndian, token)
- binary.Write(frameBuffer, binary.BigEndian, uint8(payloadItemid))
- binary.Write(frameBuffer, binary.BigEndian, uint16(len(payload)))
- binary.Write(frameBuffer, binary.BigEndian, payload)
- binary.Write(frameBuffer, binary.BigEndian, uint8(notificationIdentifierItemid))
- binary.Write(frameBuffer, binary.BigEndian, uint16(notificationIdentifierLength))
- binary.Write(frameBuffer, binary.BigEndian, pn.Identifier)
- binary.Write(frameBuffer, binary.BigEndian, uint8(expirationDateItemid))
- binary.Write(frameBuffer, binary.BigEndian, uint16(expirationDateLength))
- binary.Write(frameBuffer, binary.BigEndian, pn.Expiry)
- binary.Write(frameBuffer, binary.BigEndian, uint8(priorityItemid))
- binary.Write(frameBuffer, binary.BigEndian, uint16(priorityLength))
- binary.Write(frameBuffer, binary.BigEndian, pn.Priority)
-
- buffer := bytes.NewBuffer([]byte{})
- binary.Write(buffer, binary.BigEndian, uint8(pushCommandValue))
- binary.Write(buffer, binary.BigEndian, uint32(frameBuffer.Len()))
- binary.Write(buffer, binary.BigEndian, frameBuffer.Bytes())
- return buffer.Bytes(), nil
-}
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/push_notification_response.go b/Godeps/_workspace/src/github.com/anachronistic/apns/push_notification_response.go
deleted file mode 100644
index f08dc06e4..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/push_notification_response.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package apns
-
-// The maximum number of seconds we're willing to wait for a response
-// from the Apple Push Notification Service.
-const TimeoutSeconds = 5
-
-// This enumerates the response codes that Apple defines
-// for push notification attempts.
-var ApplePushResponses = map[uint8]string{
- 0: "NO_ERRORS",
- 1: "PROCESSING_ERROR",
- 2: "MISSING_DEVICE_TOKEN",
- 3: "MISSING_TOPIC",
- 4: "MISSING_PAYLOAD",
- 5: "INVALID_TOKEN_SIZE",
- 6: "INVALID_TOPIC_SIZE",
- 7: "INVALID_PAYLOAD_SIZE",
- 8: "INVALID_TOKEN",
- 10: "SHUTDOWN",
- 255: "UNKNOWN",
-}
-
-// PushNotificationResponse details what Apple had to say, if anything.
-type PushNotificationResponse struct {
- Success bool
- AppleResponse string
- Error error
-}
-
-// NewPushNotificationResponse creates and returns a new PushNotificationResponse
-// structure; it defaults to being unsuccessful at first.
-func NewPushNotificationResponse() (resp *PushNotificationResponse) {
- resp = new(PushNotificationResponse)
- resp.Success = false
- return
-}
diff --git a/Godeps/_workspace/src/github.com/anachronistic/apns/push_notification_test.go b/Godeps/_workspace/src/github.com/anachronistic/apns/push_notification_test.go
deleted file mode 100644
index a17b1c833..000000000
--- a/Godeps/_workspace/src/github.com/anachronistic/apns/push_notification_test.go
+++ /dev/null
@@ -1,111 +0,0 @@
-package apns
-
-import (
- "testing"
-)
-
-const testDeviceToken = "e93b7686988b4b5fd334298e60e73d90035f6d12628a80b4029bde0dec514df9"
-
-// Create a new Payload that specifies simple text,
-// a badge counter, and a custom notification sound.
-func mockPayload() (payload *Payload) {
- payload = NewPayload()
- payload.Alert = "You have mail!"
- payload.Badge = 42
- payload.Sound = "bingbong.aiff"
- return
-}
-
-// See the commentary in push_notification.go for information
-// on why we're testing a badge of value 0.
-func mockZeroBadgePayload() (payload *Payload) {
- payload = mockPayload()
- payload.Badge = 0
- return
-}
-
-// Create a new AlertDictionary. Apple recommends you not use
-// the more complex alert style unless absolutely necessary.
-func mockAlertDictionary() (dict *AlertDictionary) {
- args := make([]string, 1)
- args[0] = "localized args"
-
- dict = NewAlertDictionary()
- dict.Body = "Complex Message"
- dict.ActionLocKey = "Play a Game!"
- dict.LocKey = "localized key"
- dict.LocArgs = args
- dict.LaunchImage = "image.jpg"
- return
-}
-
-func TestBasicAlert(t *testing.T) {
- payload := mockPayload()
- pn := NewPushNotification()
-
- pn.DeviceToken = testDeviceToken
- pn.AddPayload(payload)
-
- bytes, _ := pn.ToBytes()
- json, _ := pn.PayloadJSON()
- if len(bytes) != 130 {
- t.Error("expected 130 bytes; got", len(bytes))
- }
- if len(json) != 69 {
- t.Error("expected 69 bytes; got", len(json))
- }
-}
-
-func TestAlertDictionary(t *testing.T) {
- dict := mockAlertDictionary()
- payload := mockPayload()
- payload.Alert = dict
-
- pn := NewPushNotification()
- pn.DeviceToken = testDeviceToken
- pn.AddPayload(payload)
-
- bytes, _ := pn.ToBytes()
- json, _ := pn.PayloadJSON()
- if len(bytes) != 255 {
- t.Error("expected 255 bytes; got", len(bytes))
- }
- if len(json) != 194 {
- t.Error("expected 194 bytes; got", len(bytes))
- }
-}
-
-func TestCustomParameters(t *testing.T) {
- payload := mockPayload()
- pn := NewPushNotification()
-
- pn.DeviceToken = testDeviceToken
- pn.AddPayload(payload)
- pn.Set("foo", "bar")
-
- if pn.Get("foo") != "bar" {
- t.Error("unable to set a custom property")
- }
- if pn.Get("not_set") != nil {
- t.Error("expected a missing key to return nil")
- }
-
- bytes, _ := pn.ToBytes()
- json, _ := pn.PayloadJSON()
- if len(bytes) != 142 {
- t.Error("expected 110 bytes; got", len(bytes))
- }
- if len(json) != 81 {
- t.Error("expected 81 bytes; got", len(json))
- }
-}
-
-func TestZeroBadgeChangesToNegativeOne(t *testing.T) {
- payload := mockZeroBadgePayload()
- pn := NewPushNotification()
- pn.AddPayload(payload)
-
- if payload.Badge != -1 {
- t.Error("expected 0 badge value to be converted to -1; got", payload.Badge)
- }
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypass.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypass.go
deleted file mode 100644
index 565bf5899..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypass.go
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2015 Dave Collins <dave@davec.name>
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-// NOTE: Due to the following build constraints, this file will only be compiled
-// when the code is not running on Google App Engine and "-tags disableunsafe"
-// is not added to the go build command line.
-// +build !appengine,!disableunsafe
-
-package spew
-
-import (
- "reflect"
- "unsafe"
-)
-
-const (
- // UnsafeDisabled is a build-time constant which specifies whether or
- // not access to the unsafe package is available.
- UnsafeDisabled = false
-
- // ptrSize is the size of a pointer on the current arch.
- ptrSize = unsafe.Sizeof((*byte)(nil))
-)
-
-var (
- // offsetPtr, offsetScalar, and offsetFlag are the offsets for the
- // internal reflect.Value fields. These values are valid before golang
- // commit ecccf07e7f9d which changed the format. The are also valid
- // after commit 82f48826c6c7 which changed the format again to mirror
- // the original format. Code in the init function updates these offsets
- // as necessary.
- offsetPtr = uintptr(ptrSize)
- offsetScalar = uintptr(0)
- offsetFlag = uintptr(ptrSize * 2)
-
- // flagKindWidth and flagKindShift indicate various bits that the
- // reflect package uses internally to track kind information.
- //
- // flagRO indicates whether or not the value field of a reflect.Value is
- // read-only.
- //
- // flagIndir indicates whether the value field of a reflect.Value is
- // the actual data or a pointer to the data.
- //
- // These values are valid before golang commit 90a7c3c86944 which
- // changed their positions. Code in the init function updates these
- // flags as necessary.
- flagKindWidth = uintptr(5)
- flagKindShift = uintptr(flagKindWidth - 1)
- flagRO = uintptr(1 << 0)
- flagIndir = uintptr(1 << 1)
-)
-
-func init() {
- // Older versions of reflect.Value stored small integers directly in the
- // ptr field (which is named val in the older versions). Versions
- // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named
- // scalar for this purpose which unfortunately came before the flag
- // field, so the offset of the flag field is different for those
- // versions.
- //
- // This code constructs a new reflect.Value from a known small integer
- // and checks if the size of the reflect.Value struct indicates it has
- // the scalar field. When it does, the offsets are updated accordingly.
- vv := reflect.ValueOf(0xf00)
- if unsafe.Sizeof(vv) == (ptrSize * 4) {
- offsetScalar = ptrSize * 2
- offsetFlag = ptrSize * 3
- }
-
- // Commit 90a7c3c86944 changed the flag positions such that the low
- // order bits are the kind. This code extracts the kind from the flags
- // field and ensures it's the correct type. When it's not, the flag
- // order has been changed to the newer format, so the flags are updated
- // accordingly.
- upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag)
- upfv := *(*uintptr)(upf)
- flagKindMask := uintptr((1<<flagKindWidth - 1) << flagKindShift)
- if (upfv&flagKindMask)>>flagKindShift != uintptr(reflect.Int) {
- flagKindShift = 0
- flagRO = 1 << 5
- flagIndir = 1 << 6
-
- // Commit adf9b30e5594 modified the flags to separate the
- // flagRO flag into two bits which specifies whether or not the
- // field is embedded. This causes flagIndir to move over a bit
- // and means that flagRO is the combination of either of the
- // original flagRO bit and the new bit.
- //
- // This code detects the change by extracting what used to be
- // the indirect bit to ensure it's set. When it's not, the flag
- // order has been changed to the newer format, so the flags are
- // updated accordingly.
- if upfv&flagIndir == 0 {
- flagRO = 3 << 5
- flagIndir = 1 << 7
- }
- }
-}
-
-// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
-// the typical safety restrictions preventing access to unaddressable and
-// unexported data. It works by digging the raw pointer to the underlying
-// value out of the protected value and generating a new unprotected (unsafe)
-// reflect.Value to it.
-//
-// This allows us to check for implementations of the Stringer and error
-// interfaces to be used for pretty printing ordinarily unaddressable and
-// inaccessible values such as unexported struct fields.
-func unsafeReflectValue(v reflect.Value) (rv reflect.Value) {
- indirects := 1
- vt := v.Type()
- upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr)
- rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag))
- if rvf&flagIndir != 0 {
- vt = reflect.PtrTo(v.Type())
- indirects++
- } else if offsetScalar != 0 {
- // The value is in the scalar field when it's not one of the
- // reference types.
- switch vt.Kind() {
- case reflect.Uintptr:
- case reflect.Chan:
- case reflect.Func:
- case reflect.Map:
- case reflect.Ptr:
- case reflect.UnsafePointer:
- default:
- upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) +
- offsetScalar)
- }
- }
-
- pv := reflect.NewAt(vt, upv)
- rv = pv
- for i := 0; i < indirects; i++ {
- rv = rv.Elem()
- }
- return rv
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypasssafe.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypasssafe.go
deleted file mode 100644
index 457e41235..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypasssafe.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2015 Dave Collins <dave@davec.name>
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-// NOTE: Due to the following build constraints, this file will only be compiled
-// when either the code is running on Google App Engine or "-tags disableunsafe"
-// is added to the go build command line.
-// +build appengine disableunsafe
-
-package spew
-
-import "reflect"
-
-const (
- // UnsafeDisabled is a build-time constant which specifies whether or
- // not access to the unsafe package is available.
- UnsafeDisabled = true
-)
-
-// unsafeReflectValue typically converts the passed reflect.Value into a one
-// that bypasses the typical safety restrictions preventing access to
-// unaddressable and unexported data. However, doing this relies on access to
-// the unsafe package. This is a stub version which simply returns the passed
-// reflect.Value when the unsafe package is not available.
-func unsafeReflectValue(v reflect.Value) reflect.Value {
- return v
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common.go
deleted file mode 100644
index 14f02dc15..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common.go
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package spew
-
-import (
- "bytes"
- "fmt"
- "io"
- "reflect"
- "sort"
- "strconv"
-)
-
-// Some constants in the form of bytes to avoid string overhead. This mirrors
-// the technique used in the fmt package.
-var (
- panicBytes = []byte("(PANIC=")
- plusBytes = []byte("+")
- iBytes = []byte("i")
- trueBytes = []byte("true")
- falseBytes = []byte("false")
- interfaceBytes = []byte("(interface {})")
- commaNewlineBytes = []byte(",\n")
- newlineBytes = []byte("\n")
- openBraceBytes = []byte("{")
- openBraceNewlineBytes = []byte("{\n")
- closeBraceBytes = []byte("}")
- asteriskBytes = []byte("*")
- colonBytes = []byte(":")
- colonSpaceBytes = []byte(": ")
- openParenBytes = []byte("(")
- closeParenBytes = []byte(")")
- spaceBytes = []byte(" ")
- pointerChainBytes = []byte("->")
- nilAngleBytes = []byte("<nil>")
- maxNewlineBytes = []byte("<max depth reached>\n")
- maxShortBytes = []byte("<max>")
- circularBytes = []byte("<already shown>")
- circularShortBytes = []byte("<shown>")
- invalidAngleBytes = []byte("<invalid>")
- openBracketBytes = []byte("[")
- closeBracketBytes = []byte("]")
- percentBytes = []byte("%")
- precisionBytes = []byte(".")
- openAngleBytes = []byte("<")
- closeAngleBytes = []byte(">")
- openMapBytes = []byte("map[")
- closeMapBytes = []byte("]")
- lenEqualsBytes = []byte("len=")
- capEqualsBytes = []byte("cap=")
-)
-
-// hexDigits is used to map a decimal value to a hex digit.
-var hexDigits = "0123456789abcdef"
-
-// catchPanic handles any panics that might occur during the handleMethods
-// calls.
-func catchPanic(w io.Writer, v reflect.Value) {
- if err := recover(); err != nil {
- w.Write(panicBytes)
- fmt.Fprintf(w, "%v", err)
- w.Write(closeParenBytes)
- }
-}
-
-// handleMethods attempts to call the Error and String methods on the underlying
-// type the passed reflect.Value represents and outputes the result to Writer w.
-//
-// It handles panics in any called methods by catching and displaying the error
-// as the formatted value.
-func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
- // We need an interface to check if the type implements the error or
- // Stringer interface. However, the reflect package won't give us an
- // interface on certain things like unexported struct fields in order
- // to enforce visibility rules. We use unsafe, when it's available,
- // to bypass these restrictions since this package does not mutate the
- // values.
- if !v.CanInterface() {
- if UnsafeDisabled {
- return false
- }
-
- v = unsafeReflectValue(v)
- }
-
- // Choose whether or not to do error and Stringer interface lookups against
- // the base type or a pointer to the base type depending on settings.
- // Technically calling one of these methods with a pointer receiver can
- // mutate the value, however, types which choose to satisify an error or
- // Stringer interface with a pointer receiver should not be mutating their
- // state inside these interface methods.
- if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
- v = unsafeReflectValue(v)
- }
- if v.CanAddr() {
- v = v.Addr()
- }
-
- // Is it an error or Stringer?
- switch iface := v.Interface().(type) {
- case error:
- defer catchPanic(w, v)
- if cs.ContinueOnMethod {
- w.Write(openParenBytes)
- w.Write([]byte(iface.Error()))
- w.Write(closeParenBytes)
- w.Write(spaceBytes)
- return false
- }
-
- w.Write([]byte(iface.Error()))
- return true
-
- case fmt.Stringer:
- defer catchPanic(w, v)
- if cs.ContinueOnMethod {
- w.Write(openParenBytes)
- w.Write([]byte(iface.String()))
- w.Write(closeParenBytes)
- w.Write(spaceBytes)
- return false
- }
- w.Write([]byte(iface.String()))
- return true
- }
- return false
-}
-
-// printBool outputs a boolean value as true or false to Writer w.
-func printBool(w io.Writer, val bool) {
- if val {
- w.Write(trueBytes)
- } else {
- w.Write(falseBytes)
- }
-}
-
-// printInt outputs a signed integer value to Writer w.
-func printInt(w io.Writer, val int64, base int) {
- w.Write([]byte(strconv.FormatInt(val, base)))
-}
-
-// printUint outputs an unsigned integer value to Writer w.
-func printUint(w io.Writer, val uint64, base int) {
- w.Write([]byte(strconv.FormatUint(val, base)))
-}
-
-// printFloat outputs a floating point value using the specified precision,
-// which is expected to be 32 or 64bit, to Writer w.
-func printFloat(w io.Writer, val float64, precision int) {
- w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
-}
-
-// printComplex outputs a complex value using the specified float precision
-// for the real and imaginary parts to Writer w.
-func printComplex(w io.Writer, c complex128, floatPrecision int) {
- r := real(c)
- w.Write(openParenBytes)
- w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
- i := imag(c)
- if i >= 0 {
- w.Write(plusBytes)
- }
- w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
- w.Write(iBytes)
- w.Write(closeParenBytes)
-}
-
-// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
-// prefix to Writer w.
-func printHexPtr(w io.Writer, p uintptr) {
- // Null pointer.
- num := uint64(p)
- if num == 0 {
- w.Write(nilAngleBytes)
- return
- }
-
- // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
- buf := make([]byte, 18)
-
- // It's simpler to construct the hex string right to left.
- base := uint64(16)
- i := len(buf) - 1
- for num >= base {
- buf[i] = hexDigits[num%base]
- num /= base
- i--
- }
- buf[i] = hexDigits[num]
-
- // Add '0x' prefix.
- i--
- buf[i] = 'x'
- i--
- buf[i] = '0'
-
- // Strip unused leading bytes.
- buf = buf[i:]
- w.Write(buf)
-}
-
-// valuesSorter implements sort.Interface to allow a slice of reflect.Value
-// elements to be sorted.
-type valuesSorter struct {
- values []reflect.Value
- strings []string // either nil or same len and values
- cs *ConfigState
-}
-
-// newValuesSorter initializes a valuesSorter instance, which holds a set of
-// surrogate keys on which the data should be sorted. It uses flags in
-// ConfigState to decide if and how to populate those surrogate keys.
-func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
- vs := &valuesSorter{values: values, cs: cs}
- if canSortSimply(vs.values[0].Kind()) {
- return vs
- }
- if !cs.DisableMethods {
- vs.strings = make([]string, len(values))
- for i := range vs.values {
- b := bytes.Buffer{}
- if !handleMethods(cs, &b, vs.values[i]) {
- vs.strings = nil
- break
- }
- vs.strings[i] = b.String()
- }
- }
- if vs.strings == nil && cs.SpewKeys {
- vs.strings = make([]string, len(values))
- for i := range vs.values {
- vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
- }
- }
- return vs
-}
-
-// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
-// directly, or whether it should be considered for sorting by surrogate keys
-// (if the ConfigState allows it).
-func canSortSimply(kind reflect.Kind) bool {
- // This switch parallels valueSortLess, except for the default case.
- switch kind {
- case reflect.Bool:
- return true
- case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
- return true
- case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
- return true
- case reflect.Float32, reflect.Float64:
- return true
- case reflect.String:
- return true
- case reflect.Uintptr:
- return true
- case reflect.Array:
- return true
- }
- return false
-}
-
-// Len returns the number of values in the slice. It is part of the
-// sort.Interface implementation.
-func (s *valuesSorter) Len() int {
- return len(s.values)
-}
-
-// Swap swaps the values at the passed indices. It is part of the
-// sort.Interface implementation.
-func (s *valuesSorter) Swap(i, j int) {
- s.values[i], s.values[j] = s.values[j], s.values[i]
- if s.strings != nil {
- s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
- }
-}
-
-// valueSortLess returns whether the first value should sort before the second
-// value. It is used by valueSorter.Less as part of the sort.Interface
-// implementation.
-func valueSortLess(a, b reflect.Value) bool {
- switch a.Kind() {
- case reflect.Bool:
- return !a.Bool() && b.Bool()
- case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
- return a.Int() < b.Int()
- case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
- return a.Uint() < b.Uint()
- case reflect.Float32, reflect.Float64:
- return a.Float() < b.Float()
- case reflect.String:
- return a.String() < b.String()
- case reflect.Uintptr:
- return a.Uint() < b.Uint()
- case reflect.Array:
- // Compare the contents of both arrays.
- l := a.Len()
- for i := 0; i < l; i++ {
- av := a.Index(i)
- bv := b.Index(i)
- if av.Interface() == bv.Interface() {
- continue
- }
- return valueSortLess(av, bv)
- }
- }
- return a.String() < b.String()
-}
-
-// Less returns whether the value at index i should sort before the
-// value at index j. It is part of the sort.Interface implementation.
-func (s *valuesSorter) Less(i, j int) bool {
- if s.strings == nil {
- return valueSortLess(s.values[i], s.values[j])
- }
- return s.strings[i] < s.strings[j]
-}
-
-// sortValues is a sort function that handles both native types and any type that
-// can be converted to error or Stringer. Other inputs are sorted according to
-// their Value.String() value to ensure display stability.
-func sortValues(values []reflect.Value, cs *ConfigState) {
- if len(values) == 0 {
- return
- }
- sort.Sort(newValuesSorter(values, cs))
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common_test.go
deleted file mode 100644
index 39b7525b3..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common_test.go
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package spew_test
-
-import (
- "fmt"
- "reflect"
- "testing"
-
- "github.com/davecgh/go-spew/spew"
-)
-
-// custom type to test Stinger interface on non-pointer receiver.
-type stringer string
-
-// String implements the Stringer interface for testing invocation of custom
-// stringers on types with non-pointer receivers.
-func (s stringer) String() string {
- return "stringer " + string(s)
-}
-
-// custom type to test Stinger interface on pointer receiver.
-type pstringer string
-
-// String implements the Stringer interface for testing invocation of custom
-// stringers on types with only pointer receivers.
-func (s *pstringer) String() string {
- return "stringer " + string(*s)
-}
-
-// xref1 and xref2 are cross referencing structs for testing circular reference
-// detection.
-type xref1 struct {
- ps2 *xref2
-}
-type xref2 struct {
- ps1 *xref1
-}
-
-// indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular
-// reference for testing detection.
-type indirCir1 struct {
- ps2 *indirCir2
-}
-type indirCir2 struct {
- ps3 *indirCir3
-}
-type indirCir3 struct {
- ps1 *indirCir1
-}
-
-// embed is used to test embedded structures.
-type embed struct {
- a string
-}
-
-// embedwrap is used to test embedded structures.
-type embedwrap struct {
- *embed
- e *embed
-}
-
-// panicer is used to intentionally cause a panic for testing spew properly
-// handles them
-type panicer int
-
-func (p panicer) String() string {
- panic("test panic")
-}
-
-// customError is used to test custom error interface invocation.
-type customError int
-
-func (e customError) Error() string {
- return fmt.Sprintf("error: %d", int(e))
-}
-
-// stringizeWants converts a slice of wanted test output into a format suitable
-// for a test error message.
-func stringizeWants(wants []string) string {
- s := ""
- for i, want := range wants {
- if i > 0 {
- s += fmt.Sprintf("want%d: %s", i+1, want)
- } else {
- s += "want: " + want
- }
- }
- return s
-}
-
-// testFailed returns whether or not a test failed by checking if the result
-// of the test is in the slice of wanted strings.
-func testFailed(result string, wants []string) bool {
- for _, want := range wants {
- if result == want {
- return false
- }
- }
- return true
-}
-
-type sortableStruct struct {
- x int
-}
-
-func (ss sortableStruct) String() string {
- return fmt.Sprintf("ss.%d", ss.x)
-}
-
-type unsortableStruct struct {
- x int
-}
-
-type sortTestCase struct {
- input []reflect.Value
- expected []reflect.Value
-}
-
-func helpTestSortValues(tests []sortTestCase, cs *spew.ConfigState, t *testing.T) {
- getInterfaces := func(values []reflect.Value) []interface{} {
- interfaces := []interface{}{}
- for _, v := range values {
- interfaces = append(interfaces, v.Interface())
- }
- return interfaces
- }
-
- for _, test := range tests {
- spew.SortValues(test.input, cs)
- // reflect.DeepEqual cannot really make sense of reflect.Value,
- // probably because of all the pointer tricks. For instance,
- // v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{}
- // instead.
- input := getInterfaces(test.input)
- expected := getInterfaces(test.expected)
- if !reflect.DeepEqual(input, expected) {
- t.Errorf("Sort mismatch:\n %v != %v", input, expected)
- }
- }
-}
-
-// TestSortValues ensures the sort functionality for relect.Value based sorting
-// works as intended.
-func TestSortValues(t *testing.T) {
- v := reflect.ValueOf
-
- a := v("a")
- b := v("b")
- c := v("c")
- embedA := v(embed{"a"})
- embedB := v(embed{"b"})
- embedC := v(embed{"c"})
- tests := []sortTestCase{
- // No values.
- {
- []reflect.Value{},
- []reflect.Value{},
- },
- // Bools.
- {
- []reflect.Value{v(false), v(true), v(false)},
- []reflect.Value{v(false), v(false), v(true)},
- },
- // Ints.
- {
- []reflect.Value{v(2), v(1), v(3)},
- []reflect.Value{v(1), v(2), v(3)},
- },
- // Uints.
- {
- []reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))},
- []reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))},
- },
- // Floats.
- {
- []reflect.Value{v(2.0), v(1.0), v(3.0)},
- []reflect.Value{v(1.0), v(2.0), v(3.0)},
- },
- // Strings.
- {
- []reflect.Value{b, a, c},
- []reflect.Value{a, b, c},
- },
- // Array
- {
- []reflect.Value{v([3]int{3, 2, 1}), v([3]int{1, 3, 2}), v([3]int{1, 2, 3})},
- []reflect.Value{v([3]int{1, 2, 3}), v([3]int{1, 3, 2}), v([3]int{3, 2, 1})},
- },
- // Uintptrs.
- {
- []reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))},
- []reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))},
- },
- // SortableStructs.
- {
- // Note: not sorted - DisableMethods is set.
- []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
- []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
- },
- // UnsortableStructs.
- {
- // Note: not sorted - SpewKeys is false.
- []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
- []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
- },
- // Invalid.
- {
- []reflect.Value{embedB, embedA, embedC},
- []reflect.Value{embedB, embedA, embedC},
- },
- }
- cs := spew.ConfigState{DisableMethods: true, SpewKeys: false}
- helpTestSortValues(tests, &cs, t)
-}
-
-// TestSortValuesWithMethods ensures the sort functionality for relect.Value
-// based sorting works as intended when using string methods.
-func TestSortValuesWithMethods(t *testing.T) {
- v := reflect.ValueOf
-
- a := v("a")
- b := v("b")
- c := v("c")
- tests := []sortTestCase{
- // Ints.
- {
- []reflect.Value{v(2), v(1), v(3)},
- []reflect.Value{v(1), v(2), v(3)},
- },
- // Strings.
- {
- []reflect.Value{b, a, c},
- []reflect.Value{a, b, c},
- },
- // SortableStructs.
- {
- []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
- []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})},
- },
- // UnsortableStructs.
- {
- // Note: not sorted - SpewKeys is false.
- []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
- []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
- },
- }
- cs := spew.ConfigState{DisableMethods: false, SpewKeys: false}
- helpTestSortValues(tests, &cs, t)
-}
-
-// TestSortValuesWithSpew ensures the sort functionality for relect.Value
-// based sorting works as intended when using spew to stringify keys.
-func TestSortValuesWithSpew(t *testing.T) {
- v := reflect.ValueOf
-
- a := v("a")
- b := v("b")
- c := v("c")
- tests := []sortTestCase{
- // Ints.
- {
- []reflect.Value{v(2), v(1), v(3)},
- []reflect.Value{v(1), v(2), v(3)},
- },
- // Strings.
- {
- []reflect.Value{b, a, c},
- []reflect.Value{a, b, c},
- },
- // SortableStructs.
- {
- []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
- []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})},
- },
- // UnsortableStructs.
- {
- []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
- []reflect.Value{v(unsortableStruct{1}), v(unsortableStruct{2}), v(unsortableStruct{3})},
- },
- }
- cs := spew.ConfigState{DisableMethods: true, SpewKeys: true}
- helpTestSortValues(tests, &cs, t)
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/config.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/config.go
deleted file mode 100644
index ee1ab07b3..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/config.go
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package spew
-
-import (
- "bytes"
- "fmt"
- "io"
- "os"
-)
-
-// ConfigState houses the configuration options used by spew to format and
-// display values. There is a global instance, Config, that is used to control
-// all top-level Formatter and Dump functionality. Each ConfigState instance
-// provides methods equivalent to the top-level functions.
-//
-// The zero value for ConfigState provides no indentation. You would typically
-// want to set it to a space or a tab.
-//
-// Alternatively, you can use NewDefaultConfig to get a ConfigState instance
-// with default settings. See the documentation of NewDefaultConfig for default
-// values.
-type ConfigState struct {
- // Indent specifies the string to use for each indentation level. The
- // global config instance that all top-level functions use set this to a
- // single space by default. If you would like more indentation, you might
- // set this to a tab with "\t" or perhaps two spaces with " ".
- Indent string
-
- // MaxDepth controls the maximum number of levels to descend into nested
- // data structures. The default, 0, means there is no limit.
- //
- // NOTE: Circular data structures are properly detected, so it is not
- // necessary to set this value unless you specifically want to limit deeply
- // nested data structures.
- MaxDepth int
-
- // DisableMethods specifies whether or not error and Stringer interfaces are
- // invoked for types that implement them.
- DisableMethods bool
-
- // DisablePointerMethods specifies whether or not to check for and invoke
- // error and Stringer interfaces on types which only accept a pointer
- // receiver when the current type is not a pointer.
- //
- // NOTE: This might be an unsafe action since calling one of these methods
- // with a pointer receiver could technically mutate the value, however,
- // in practice, types which choose to satisify an error or Stringer
- // interface with a pointer receiver should not be mutating their state
- // inside these interface methods. As a result, this option relies on
- // access to the unsafe package, so it will not have any effect when
- // running in environments without access to the unsafe package such as
- // Google App Engine or with the "disableunsafe" build tag specified.
- DisablePointerMethods bool
-
- // ContinueOnMethod specifies whether or not recursion should continue once
- // a custom error or Stringer interface is invoked. The default, false,
- // means it will print the results of invoking the custom error or Stringer
- // interface and return immediately instead of continuing to recurse into
- // the internals of the data type.
- //
- // NOTE: This flag does not have any effect if method invocation is disabled
- // via the DisableMethods or DisablePointerMethods options.
- ContinueOnMethod bool
-
- // SortKeys specifies map keys should be sorted before being printed. Use
- // this to have a more deterministic, diffable output. Note that only
- // native types (bool, int, uint, floats, uintptr and string) and types
- // that support the error or Stringer interfaces (if methods are
- // enabled) are supported, with other types sorted according to the
- // reflect.Value.String() output which guarantees display stability.
- SortKeys bool
-
- // SpewKeys specifies that, as a last resort attempt, map keys should
- // be spewed to strings and sorted by those strings. This is only
- // considered if SortKeys is true.
- SpewKeys bool
-}
-
-// Config is the active configuration of the top-level functions.
-// The configuration can be changed by modifying the contents of spew.Config.
-var Config = ConfigState{Indent: " "}
-
-// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
-// passed with a Formatter interface returned by c.NewFormatter. It returns
-// the formatted string as a value that satisfies error. See NewFormatter
-// for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b))
-func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) {
- return fmt.Errorf(format, c.convertArgs(a)...)
-}
-
-// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
-// passed with a Formatter interface returned by c.NewFormatter. It returns
-// the number of bytes written and any write error encountered. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b))
-func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
- return fmt.Fprint(w, c.convertArgs(a)...)
-}
-
-// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
-// passed with a Formatter interface returned by c.NewFormatter. It returns
-// the number of bytes written and any write error encountered. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b))
-func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
- return fmt.Fprintf(w, format, c.convertArgs(a)...)
-}
-
-// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
-// passed with a Formatter interface returned by c.NewFormatter. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b))
-func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
- return fmt.Fprintln(w, c.convertArgs(a)...)
-}
-
-// Print is a wrapper for fmt.Print that treats each argument as if it were
-// passed with a Formatter interface returned by c.NewFormatter. It returns
-// the number of bytes written and any write error encountered. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Print(c.NewFormatter(a), c.NewFormatter(b))
-func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
- return fmt.Print(c.convertArgs(a)...)
-}
-
-// Printf is a wrapper for fmt.Printf that treats each argument as if it were
-// passed with a Formatter interface returned by c.NewFormatter. It returns
-// the number of bytes written and any write error encountered. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b))
-func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) {
- return fmt.Printf(format, c.convertArgs(a)...)
-}
-
-// Println is a wrapper for fmt.Println that treats each argument as if it were
-// passed with a Formatter interface returned by c.NewFormatter. It returns
-// the number of bytes written and any write error encountered. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Println(c.NewFormatter(a), c.NewFormatter(b))
-func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
- return fmt.Println(c.convertArgs(a)...)
-}
-
-// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
-// passed with a Formatter interface returned by c.NewFormatter. It returns
-// the resulting string. See NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
-func (c *ConfigState) Sprint(a ...interface{}) string {
- return fmt.Sprint(c.convertArgs(a)...)
-}
-
-// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
-// passed with a Formatter interface returned by c.NewFormatter. It returns
-// the resulting string. See NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
-func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
- return fmt.Sprintf(format, c.convertArgs(a)...)
-}
-
-// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
-// were passed with a Formatter interface returned by c.NewFormatter. It
-// returns the resulting string. See NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
-func (c *ConfigState) Sprintln(a ...interface{}) string {
- return fmt.Sprintln(c.convertArgs(a)...)
-}
-
-/*
-NewFormatter returns a custom formatter that satisfies the fmt.Formatter
-interface. As a result, it integrates cleanly with standard fmt package
-printing functions. The formatter is useful for inline printing of smaller data
-types similar to the standard %v format specifier.
-
-The custom formatter only responds to the %v (most compact), %+v (adds pointer
-addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb
-combinations. Any other verbs such as %x and %q will be sent to the the
-standard fmt package for formatting. In addition, the custom formatter ignores
-the width and precision arguments (however they will still work on the format
-specifiers not handled by the custom formatter).
-
-Typically this function shouldn't be called directly. It is much easier to make
-use of the custom formatter by calling one of the convenience functions such as
-c.Printf, c.Println, or c.Printf.
-*/
-func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
- return newFormatter(c, v)
-}
-
-// Fdump formats and displays the passed arguments to io.Writer w. It formats
-// exactly the same as Dump.
-func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
- fdump(c, w, a...)
-}
-
-/*
-Dump displays the passed parameters to standard out with newlines, customizable
-indentation, and additional debug information such as complete types and all
-pointer addresses used to indirect to the final value. It provides the
-following features over the built-in printing facilities provided by the fmt
-package:
-
- * Pointers are dereferenced and followed
- * Circular data structures are detected and handled properly
- * Custom Stringer/error interfaces are optionally invoked, including
- on unexported types
- * Custom types which only implement the Stringer/error interfaces via
- a pointer receiver are optionally invoked when passing non-pointer
- variables
- * Byte arrays and slices are dumped like the hexdump -C command which
- includes offsets, byte values in hex, and ASCII output
-
-The configuration options are controlled by modifying the public members
-of c. See ConfigState for options documentation.
-
-See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
-get the formatted result as a string.
-*/
-func (c *ConfigState) Dump(a ...interface{}) {
- fdump(c, os.Stdout, a...)
-}
-
-// Sdump returns a string with the passed arguments formatted exactly the same
-// as Dump.
-func (c *ConfigState) Sdump(a ...interface{}) string {
- var buf bytes.Buffer
- fdump(c, &buf, a...)
- return buf.String()
-}
-
-// convertArgs accepts a slice of arguments and returns a slice of the same
-// length with each argument converted to a spew Formatter interface using
-// the ConfigState associated with s.
-func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) {
- formatters = make([]interface{}, len(args))
- for index, arg := range args {
- formatters[index] = newFormatter(c, arg)
- }
- return formatters
-}
-
-// NewDefaultConfig returns a ConfigState with the following default settings.
-//
-// Indent: " "
-// MaxDepth: 0
-// DisableMethods: false
-// DisablePointerMethods: false
-// ContinueOnMethod: false
-// SortKeys: false
-func NewDefaultConfig() *ConfigState {
- return &ConfigState{Indent: " "}
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/doc.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/doc.go
deleted file mode 100644
index 5be0c4060..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/doc.go
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
-Package spew implements a deep pretty printer for Go data structures to aid in
-debugging.
-
-A quick overview of the additional features spew provides over the built-in
-printing facilities for Go data types are as follows:
-
- * Pointers are dereferenced and followed
- * Circular data structures are detected and handled properly
- * Custom Stringer/error interfaces are optionally invoked, including
- on unexported types
- * Custom types which only implement the Stringer/error interfaces via
- a pointer receiver are optionally invoked when passing non-pointer
- variables
- * Byte arrays and slices are dumped like the hexdump -C command which
- includes offsets, byte values in hex, and ASCII output (only when using
- Dump style)
-
-There are two different approaches spew allows for dumping Go data structures:
-
- * Dump style which prints with newlines, customizable indentation,
- and additional debug information such as types and all pointer addresses
- used to indirect to the final value
- * A custom Formatter interface that integrates cleanly with the standard fmt
- package and replaces %v, %+v, %#v, and %#+v to provide inline printing
- similar to the default %v while providing the additional functionality
- outlined above and passing unsupported format verbs such as %x and %q
- along to fmt
-
-Quick Start
-
-This section demonstrates how to quickly get started with spew. See the
-sections below for further details on formatting and configuration options.
-
-To dump a variable with full newlines, indentation, type, and pointer
-information use Dump, Fdump, or Sdump:
- spew.Dump(myVar1, myVar2, ...)
- spew.Fdump(someWriter, myVar1, myVar2, ...)
- str := spew.Sdump(myVar1, myVar2, ...)
-
-Alternatively, if you would prefer to use format strings with a compacted inline
-printing style, use the convenience wrappers Printf, Fprintf, etc with
-%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
-%#+v (adds types and pointer addresses):
- spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
- spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
- spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
- spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
-
-Configuration Options
-
-Configuration of spew is handled by fields in the ConfigState type. For
-convenience, all of the top-level functions use a global state available
-via the spew.Config global.
-
-It is also possible to create a ConfigState instance that provides methods
-equivalent to the top-level functions. This allows concurrent configuration
-options. See the ConfigState documentation for more details.
-
-The following configuration options are available:
- * Indent
- String to use for each indentation level for Dump functions.
- It is a single space by default. A popular alternative is "\t".
-
- * MaxDepth
- Maximum number of levels to descend into nested data structures.
- There is no limit by default.
-
- * DisableMethods
- Disables invocation of error and Stringer interface methods.
- Method invocation is enabled by default.
-
- * DisablePointerMethods
- Disables invocation of error and Stringer interface methods on types
- which only accept pointer receivers from non-pointer variables.
- Pointer method invocation is enabled by default.
-
- * ContinueOnMethod
- Enables recursion into types after invoking error and Stringer interface
- methods. Recursion after method invocation is disabled by default.
-
- * SortKeys
- Specifies map keys should be sorted before being printed. Use
- this to have a more deterministic, diffable output. Note that
- only native types (bool, int, uint, floats, uintptr and string)
- and types which implement error or Stringer interfaces are
- supported with other types sorted according to the
- reflect.Value.String() output which guarantees display
- stability. Natural map order is used by default.
-
- * SpewKeys
- Specifies that, as a last resort attempt, map keys should be
- spewed to strings and sorted by those strings. This is only
- considered if SortKeys is true.
-
-Dump Usage
-
-Simply call spew.Dump with a list of variables you want to dump:
-
- spew.Dump(myVar1, myVar2, ...)
-
-You may also call spew.Fdump if you would prefer to output to an arbitrary
-io.Writer. For example, to dump to standard error:
-
- spew.Fdump(os.Stderr, myVar1, myVar2, ...)
-
-A third option is to call spew.Sdump to get the formatted output as a string:
-
- str := spew.Sdump(myVar1, myVar2, ...)
-
-Sample Dump Output
-
-See the Dump example for details on the setup of the types and variables being
-shown here.
-
- (main.Foo) {
- unexportedField: (*main.Bar)(0xf84002e210)({
- flag: (main.Flag) flagTwo,
- data: (uintptr) <nil>
- }),
- ExportedField: (map[interface {}]interface {}) (len=1) {
- (string) (len=3) "one": (bool) true
- }
- }
-
-Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
-command as shown.
- ([]uint8) (len=32 cap=32) {
- 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
- 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
- 00000020 31 32 |12|
- }
-
-Custom Formatter
-
-Spew provides a custom formatter that implements the fmt.Formatter interface
-so that it integrates cleanly with standard fmt package printing functions. The
-formatter is useful for inline printing of smaller data types similar to the
-standard %v format specifier.
-
-The custom formatter only responds to the %v (most compact), %+v (adds pointer
-addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
-combinations. Any other verbs such as %x and %q will be sent to the the
-standard fmt package for formatting. In addition, the custom formatter ignores
-the width and precision arguments (however they will still work on the format
-specifiers not handled by the custom formatter).
-
-Custom Formatter Usage
-
-The simplest way to make use of the spew custom formatter is to call one of the
-convenience functions such as spew.Printf, spew.Println, or spew.Printf. The
-functions have syntax you are most likely already familiar with:
-
- spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
- spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
- spew.Println(myVar, myVar2)
- spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
- spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
-
-See the Index for the full list convenience functions.
-
-Sample Formatter Output
-
-Double pointer to a uint8:
- %v: <**>5
- %+v: <**>(0xf8400420d0->0xf8400420c8)5
- %#v: (**uint8)5
- %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
-
-Pointer to circular struct with a uint8 field and a pointer to itself:
- %v: <*>{1 <*><shown>}
- %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
- %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
- %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
-
-See the Printf example for details on the setup of variables being shown
-here.
-
-Errors
-
-Since it is possible for custom Stringer/error interfaces to panic, spew
-detects them and handles them internally by printing the panic information
-inline with the output. Since spew is intended to provide deep pretty printing
-capabilities on structures, it intentionally does not return any errors.
-*/
-package spew
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump.go
deleted file mode 100644
index a0ff95e27..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump.go
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package spew
-
-import (
- "bytes"
- "encoding/hex"
- "fmt"
- "io"
- "os"
- "reflect"
- "regexp"
- "strconv"
- "strings"
-)
-
-var (
- // uint8Type is a reflect.Type representing a uint8. It is used to
- // convert cgo types to uint8 slices for hexdumping.
- uint8Type = reflect.TypeOf(uint8(0))
-
- // cCharRE is a regular expression that matches a cgo char.
- // It is used to detect character arrays to hexdump them.
- cCharRE = regexp.MustCompile("^.*\\._Ctype_char$")
-
- // cUnsignedCharRE is a regular expression that matches a cgo unsigned
- // char. It is used to detect unsigned character arrays to hexdump
- // them.
- cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$")
-
- // cUint8tCharRE is a regular expression that matches a cgo uint8_t.
- // It is used to detect uint8_t arrays to hexdump them.
- cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$")
-)
-
-// dumpState contains information about the state of a dump operation.
-type dumpState struct {
- w io.Writer
- depth int
- pointers map[uintptr]int
- ignoreNextType bool
- ignoreNextIndent bool
- cs *ConfigState
-}
-
-// indent performs indentation according to the depth level and cs.Indent
-// option.
-func (d *dumpState) indent() {
- if d.ignoreNextIndent {
- d.ignoreNextIndent = false
- return
- }
- d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
-}
-
-// unpackValue returns values inside of non-nil interfaces when possible.
-// This is useful for data types like structs, arrays, slices, and maps which
-// can contain varying types packed inside an interface.
-func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
- if v.Kind() == reflect.Interface && !v.IsNil() {
- v = v.Elem()
- }
- return v
-}
-
-// dumpPtr handles formatting of pointers by indirecting them as necessary.
-func (d *dumpState) dumpPtr(v reflect.Value) {
- // Remove pointers at or below the current depth from map used to detect
- // circular refs.
- for k, depth := range d.pointers {
- if depth >= d.depth {
- delete(d.pointers, k)
- }
- }
-
- // Keep list of all dereferenced pointers to show later.
- pointerChain := make([]uintptr, 0)
-
- // Figure out how many levels of indirection there are by dereferencing
- // pointers and unpacking interfaces down the chain while detecting circular
- // references.
- nilFound := false
- cycleFound := false
- indirects := 0
- ve := v
- for ve.Kind() == reflect.Ptr {
- if ve.IsNil() {
- nilFound = true
- break
- }
- indirects++
- addr := ve.Pointer()
- pointerChain = append(pointerChain, addr)
- if pd, ok := d.pointers[addr]; ok && pd < d.depth {
- cycleFound = true
- indirects--
- break
- }
- d.pointers[addr] = d.depth
-
- ve = ve.Elem()
- if ve.Kind() == reflect.Interface {
- if ve.IsNil() {
- nilFound = true
- break
- }
- ve = ve.Elem()
- }
- }
-
- // Display type information.
- d.w.Write(openParenBytes)
- d.w.Write(bytes.Repeat(asteriskBytes, indirects))
- d.w.Write([]byte(ve.Type().String()))
- d.w.Write(closeParenBytes)
-
- // Display pointer information.
- if len(pointerChain) > 0 {
- d.w.Write(openParenBytes)
- for i, addr := range pointerChain {
- if i > 0 {
- d.w.Write(pointerChainBytes)
- }
- printHexPtr(d.w, addr)
- }
- d.w.Write(closeParenBytes)
- }
-
- // Display dereferenced value.
- d.w.Write(openParenBytes)
- switch {
- case nilFound == true:
- d.w.Write(nilAngleBytes)
-
- case cycleFound == true:
- d.w.Write(circularBytes)
-
- default:
- d.ignoreNextType = true
- d.dump(ve)
- }
- d.w.Write(closeParenBytes)
-}
-
-// dumpSlice handles formatting of arrays and slices. Byte (uint8 under
-// reflection) arrays and slices are dumped in hexdump -C fashion.
-func (d *dumpState) dumpSlice(v reflect.Value) {
- // Determine whether this type should be hex dumped or not. Also,
- // for types which should be hexdumped, try to use the underlying data
- // first, then fall back to trying to convert them to a uint8 slice.
- var buf []uint8
- doConvert := false
- doHexDump := false
- numEntries := v.Len()
- if numEntries > 0 {
- vt := v.Index(0).Type()
- vts := vt.String()
- switch {
- // C types that need to be converted.
- case cCharRE.MatchString(vts):
- fallthrough
- case cUnsignedCharRE.MatchString(vts):
- fallthrough
- case cUint8tCharRE.MatchString(vts):
- doConvert = true
-
- // Try to use existing uint8 slices and fall back to converting
- // and copying if that fails.
- case vt.Kind() == reflect.Uint8:
- // We need an addressable interface to convert the type
- // to a byte slice. However, the reflect package won't
- // give us an interface on certain things like
- // unexported struct fields in order to enforce
- // visibility rules. We use unsafe, when available, to
- // bypass these restrictions since this package does not
- // mutate the values.
- vs := v
- if !vs.CanInterface() || !vs.CanAddr() {
- vs = unsafeReflectValue(vs)
- }
- if !UnsafeDisabled {
- vs = vs.Slice(0, numEntries)
-
- // Use the existing uint8 slice if it can be
- // type asserted.
- iface := vs.Interface()
- if slice, ok := iface.([]uint8); ok {
- buf = slice
- doHexDump = true
- break
- }
- }
-
- // The underlying data needs to be converted if it can't
- // be type asserted to a uint8 slice.
- doConvert = true
- }
-
- // Copy and convert the underlying type if needed.
- if doConvert && vt.ConvertibleTo(uint8Type) {
- // Convert and copy each element into a uint8 byte
- // slice.
- buf = make([]uint8, numEntries)
- for i := 0; i < numEntries; i++ {
- vv := v.Index(i)
- buf[i] = uint8(vv.Convert(uint8Type).Uint())
- }
- doHexDump = true
- }
- }
-
- // Hexdump the entire slice as needed.
- if doHexDump {
- indent := strings.Repeat(d.cs.Indent, d.depth)
- str := indent + hex.Dump(buf)
- str = strings.Replace(str, "\n", "\n"+indent, -1)
- str = strings.TrimRight(str, d.cs.Indent)
- d.w.Write([]byte(str))
- return
- }
-
- // Recursively call dump for each item.
- for i := 0; i < numEntries; i++ {
- d.dump(d.unpackValue(v.Index(i)))
- if i < (numEntries - 1) {
- d.w.Write(commaNewlineBytes)
- } else {
- d.w.Write(newlineBytes)
- }
- }
-}
-
-// dump is the main workhorse for dumping a value. It uses the passed reflect
-// value to figure out what kind of object we are dealing with and formats it
-// appropriately. It is a recursive function, however circular data structures
-// are detected and handled properly.
-func (d *dumpState) dump(v reflect.Value) {
- // Handle invalid reflect values immediately.
- kind := v.Kind()
- if kind == reflect.Invalid {
- d.w.Write(invalidAngleBytes)
- return
- }
-
- // Handle pointers specially.
- if kind == reflect.Ptr {
- d.indent()
- d.dumpPtr(v)
- return
- }
-
- // Print type information unless already handled elsewhere.
- if !d.ignoreNextType {
- d.indent()
- d.w.Write(openParenBytes)
- d.w.Write([]byte(v.Type().String()))
- d.w.Write(closeParenBytes)
- d.w.Write(spaceBytes)
- }
- d.ignoreNextType = false
-
- // Display length and capacity if the built-in len and cap functions
- // work with the value's kind and the len/cap itself is non-zero.
- valueLen, valueCap := 0, 0
- switch v.Kind() {
- case reflect.Array, reflect.Slice, reflect.Chan:
- valueLen, valueCap = v.Len(), v.Cap()
- case reflect.Map, reflect.String:
- valueLen = v.Len()
- }
- if valueLen != 0 || valueCap != 0 {
- d.w.Write(openParenBytes)
- if valueLen != 0 {
- d.w.Write(lenEqualsBytes)
- printInt(d.w, int64(valueLen), 10)
- }
- if valueCap != 0 {
- if valueLen != 0 {
- d.w.Write(spaceBytes)
- }
- d.w.Write(capEqualsBytes)
- printInt(d.w, int64(valueCap), 10)
- }
- d.w.Write(closeParenBytes)
- d.w.Write(spaceBytes)
- }
-
- // Call Stringer/error interfaces if they exist and the handle methods flag
- // is enabled
- if !d.cs.DisableMethods {
- if (kind != reflect.Invalid) && (kind != reflect.Interface) {
- if handled := handleMethods(d.cs, d.w, v); handled {
- return
- }
- }
- }
-
- switch kind {
- case reflect.Invalid:
- // Do nothing. We should never get here since invalid has already
- // been handled above.
-
- case reflect.Bool:
- printBool(d.w, v.Bool())
-
- case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
- printInt(d.w, v.Int(), 10)
-
- case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
- printUint(d.w, v.Uint(), 10)
-
- case reflect.Float32:
- printFloat(d.w, v.Float(), 32)
-
- case reflect.Float64:
- printFloat(d.w, v.Float(), 64)
-
- case reflect.Complex64:
- printComplex(d.w, v.Complex(), 32)
-
- case reflect.Complex128:
- printComplex(d.w, v.Complex(), 64)
-
- case reflect.Slice:
- if v.IsNil() {
- d.w.Write(nilAngleBytes)
- break
- }
- fallthrough
-
- case reflect.Array:
- d.w.Write(openBraceNewlineBytes)
- d.depth++
- if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
- d.indent()
- d.w.Write(maxNewlineBytes)
- } else {
- d.dumpSlice(v)
- }
- d.depth--
- d.indent()
- d.w.Write(closeBraceBytes)
-
- case reflect.String:
- d.w.Write([]byte(strconv.Quote(v.String())))
-
- case reflect.Interface:
- // The only time we should get here is for nil interfaces due to
- // unpackValue calls.
- if v.IsNil() {
- d.w.Write(nilAngleBytes)
- }
-
- case reflect.Ptr:
- // Do nothing. We should never get here since pointers have already
- // been handled above.
-
- case reflect.Map:
- // nil maps should be indicated as different than empty maps
- if v.IsNil() {
- d.w.Write(nilAngleBytes)
- break
- }
-
- d.w.Write(openBraceNewlineBytes)
- d.depth++
- if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
- d.indent()
- d.w.Write(maxNewlineBytes)
- } else {
- numEntries := v.Len()
- keys := v.MapKeys()
- if d.cs.SortKeys {
- sortValues(keys, d.cs)
- }
- for i, key := range keys {
- d.dump(d.unpackValue(key))
- d.w.Write(colonSpaceBytes)
- d.ignoreNextIndent = true
- d.dump(d.unpackValue(v.MapIndex(key)))
- if i < (numEntries - 1) {
- d.w.Write(commaNewlineBytes)
- } else {
- d.w.Write(newlineBytes)
- }
- }
- }
- d.depth--
- d.indent()
- d.w.Write(closeBraceBytes)
-
- case reflect.Struct:
- d.w.Write(openBraceNewlineBytes)
- d.depth++
- if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
- d.indent()
- d.w.Write(maxNewlineBytes)
- } else {
- vt := v.Type()
- numFields := v.NumField()
- for i := 0; i < numFields; i++ {
- d.indent()
- vtf := vt.Field(i)
- d.w.Write([]byte(vtf.Name))
- d.w.Write(colonSpaceBytes)
- d.ignoreNextIndent = true
- d.dump(d.unpackValue(v.Field(i)))
- if i < (numFields - 1) {
- d.w.Write(commaNewlineBytes)
- } else {
- d.w.Write(newlineBytes)
- }
- }
- }
- d.depth--
- d.indent()
- d.w.Write(closeBraceBytes)
-
- case reflect.Uintptr:
- printHexPtr(d.w, uintptr(v.Uint()))
-
- case reflect.UnsafePointer, reflect.Chan, reflect.Func:
- printHexPtr(d.w, v.Pointer())
-
- // There were not any other types at the time this code was written, but
- // fall back to letting the default fmt package handle it in case any new
- // types are added.
- default:
- if v.CanInterface() {
- fmt.Fprintf(d.w, "%v", v.Interface())
- } else {
- fmt.Fprintf(d.w, "%v", v.String())
- }
- }
-}
-
-// fdump is a helper function to consolidate the logic from the various public
-// methods which take varying writers and config states.
-func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
- for _, arg := range a {
- if arg == nil {
- w.Write(interfaceBytes)
- w.Write(spaceBytes)
- w.Write(nilAngleBytes)
- w.Write(newlineBytes)
- continue
- }
-
- d := dumpState{w: w, cs: cs}
- d.pointers = make(map[uintptr]int)
- d.dump(reflect.ValueOf(arg))
- d.w.Write(newlineBytes)
- }
-}
-
-// Fdump formats and displays the passed arguments to io.Writer w. It formats
-// exactly the same as Dump.
-func Fdump(w io.Writer, a ...interface{}) {
- fdump(&Config, w, a...)
-}
-
-// Sdump returns a string with the passed arguments formatted exactly the same
-// as Dump.
-func Sdump(a ...interface{}) string {
- var buf bytes.Buffer
- fdump(&Config, &buf, a...)
- return buf.String()
-}
-
-/*
-Dump displays the passed parameters to standard out with newlines, customizable
-indentation, and additional debug information such as complete types and all
-pointer addresses used to indirect to the final value. It provides the
-following features over the built-in printing facilities provided by the fmt
-package:
-
- * Pointers are dereferenced and followed
- * Circular data structures are detected and handled properly
- * Custom Stringer/error interfaces are optionally invoked, including
- on unexported types
- * Custom types which only implement the Stringer/error interfaces via
- a pointer receiver are optionally invoked when passing non-pointer
- variables
- * Byte arrays and slices are dumped like the hexdump -C command which
- includes offsets, byte values in hex, and ASCII output
-
-The configuration options are controlled by an exported package global,
-spew.Config. See ConfigState for options documentation.
-
-See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
-get the formatted result as a string.
-*/
-func Dump(a ...interface{}) {
- fdump(&Config, os.Stdout, a...)
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump_test.go
deleted file mode 100644
index 2b320401d..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump_test.go
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
-Test Summary:
-NOTE: For each test, a nil pointer, a single pointer and double pointer to the
-base test element are also tested to ensure proper indirection across all types.
-
-- Max int8, int16, int32, int64, int
-- Max uint8, uint16, uint32, uint64, uint
-- Boolean true and false
-- Standard complex64 and complex128
-- Array containing standard ints
-- Array containing type with custom formatter on pointer receiver only
-- Array containing interfaces
-- Array containing bytes
-- Slice containing standard float32 values
-- Slice containing type with custom formatter on pointer receiver only
-- Slice containing interfaces
-- Slice containing bytes
-- Nil slice
-- Standard string
-- Nil interface
-- Sub-interface
-- Map with string keys and int vals
-- Map with custom formatter type on pointer receiver only keys and vals
-- Map with interface keys and values
-- Map with nil interface value
-- Struct with primitives
-- Struct that contains another struct
-- Struct that contains custom type with Stringer pointer interface via both
- exported and unexported fields
-- Struct that contains embedded struct and field to same struct
-- Uintptr to 0 (null pointer)
-- Uintptr address of real variable
-- Unsafe.Pointer to 0 (null pointer)
-- Unsafe.Pointer to address of real variable
-- Nil channel
-- Standard int channel
-- Function with no params and no returns
-- Function with param and no returns
-- Function with multiple params and multiple returns
-- Struct that is circular through self referencing
-- Structs that are circular through cross referencing
-- Structs that are indirectly circular
-- Type that panics in its Stringer interface
-*/
-
-package spew_test
-
-import (
- "bytes"
- "fmt"
- "testing"
- "unsafe"
-
- "github.com/davecgh/go-spew/spew"
-)
-
-// dumpTest is used to describe a test to be perfomed against the Dump method.
-type dumpTest struct {
- in interface{}
- wants []string
-}
-
-// dumpTests houses all of the tests to be performed against the Dump method.
-var dumpTests = make([]dumpTest, 0)
-
-// addDumpTest is a helper method to append the passed input and desired result
-// to dumpTests
-func addDumpTest(in interface{}, wants ...string) {
- test := dumpTest{in, wants}
- dumpTests = append(dumpTests, test)
-}
-
-func addIntDumpTests() {
- // Max int8.
- v := int8(127)
- nv := (*int8)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "int8"
- vs := "127"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-
- // Max int16.
- v2 := int16(32767)
- nv2 := (*int16)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "int16"
- v2s := "32767"
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
- addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
-
- // Max int32.
- v3 := int32(2147483647)
- nv3 := (*int32)(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "int32"
- v3s := "2147483647"
- addDumpTest(v3, "("+v3t+") "+v3s+"\n")
- addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n")
- addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n")
- addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
-
- // Max int64.
- v4 := int64(9223372036854775807)
- nv4 := (*int64)(nil)
- pv4 := &v4
- v4Addr := fmt.Sprintf("%p", pv4)
- pv4Addr := fmt.Sprintf("%p", &pv4)
- v4t := "int64"
- v4s := "9223372036854775807"
- addDumpTest(v4, "("+v4t+") "+v4s+"\n")
- addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n")
- addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n")
- addDumpTest(nv4, "(*"+v4t+")(<nil>)\n")
-
- // Max int.
- v5 := int(2147483647)
- nv5 := (*int)(nil)
- pv5 := &v5
- v5Addr := fmt.Sprintf("%p", pv5)
- pv5Addr := fmt.Sprintf("%p", &pv5)
- v5t := "int"
- v5s := "2147483647"
- addDumpTest(v5, "("+v5t+") "+v5s+"\n")
- addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n")
- addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n")
- addDumpTest(nv5, "(*"+v5t+")(<nil>)\n")
-}
-
-func addUintDumpTests() {
- // Max uint8.
- v := uint8(255)
- nv := (*uint8)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "uint8"
- vs := "255"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-
- // Max uint16.
- v2 := uint16(65535)
- nv2 := (*uint16)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "uint16"
- v2s := "65535"
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
- addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
-
- // Max uint32.
- v3 := uint32(4294967295)
- nv3 := (*uint32)(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "uint32"
- v3s := "4294967295"
- addDumpTest(v3, "("+v3t+") "+v3s+"\n")
- addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n")
- addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n")
- addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
-
- // Max uint64.
- v4 := uint64(18446744073709551615)
- nv4 := (*uint64)(nil)
- pv4 := &v4
- v4Addr := fmt.Sprintf("%p", pv4)
- pv4Addr := fmt.Sprintf("%p", &pv4)
- v4t := "uint64"
- v4s := "18446744073709551615"
- addDumpTest(v4, "("+v4t+") "+v4s+"\n")
- addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n")
- addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n")
- addDumpTest(nv4, "(*"+v4t+")(<nil>)\n")
-
- // Max uint.
- v5 := uint(4294967295)
- nv5 := (*uint)(nil)
- pv5 := &v5
- v5Addr := fmt.Sprintf("%p", pv5)
- pv5Addr := fmt.Sprintf("%p", &pv5)
- v5t := "uint"
- v5s := "4294967295"
- addDumpTest(v5, "("+v5t+") "+v5s+"\n")
- addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n")
- addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n")
- addDumpTest(nv5, "(*"+v5t+")(<nil>)\n")
-}
-
-func addBoolDumpTests() {
- // Boolean true.
- v := bool(true)
- nv := (*bool)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "bool"
- vs := "true"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-
- // Boolean false.
- v2 := bool(false)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "bool"
- v2s := "false"
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
-}
-
-func addFloatDumpTests() {
- // Standard float32.
- v := float32(3.1415)
- nv := (*float32)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "float32"
- vs := "3.1415"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-
- // Standard float64.
- v2 := float64(3.1415926)
- nv2 := (*float64)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "float64"
- v2s := "3.1415926"
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
- addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
-}
-
-func addComplexDumpTests() {
- // Standard complex64.
- v := complex(float32(6), -2)
- nv := (*complex64)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "complex64"
- vs := "(6-2i)"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-
- // Standard complex128.
- v2 := complex(float64(-6), 2)
- nv2 := (*complex128)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "complex128"
- v2s := "(-6+2i)"
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
- addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
-}
-
-func addArrayDumpTests() {
- // Array containing standard ints.
- v := [3]int{1, 2, 3}
- vLen := fmt.Sprintf("%d", len(v))
- vCap := fmt.Sprintf("%d", cap(v))
- nv := (*[3]int)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "int"
- vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 1,\n (" +
- vt + ") 2,\n (" + vt + ") 3\n}"
- addDumpTest(v, "([3]"+vt+") "+vs+"\n")
- addDumpTest(pv, "(*[3]"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**[3]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*[3]"+vt+")(<nil>)\n")
-
- // Array containing type with custom formatter on pointer receiver only.
- v2i0 := pstringer("1")
- v2i1 := pstringer("2")
- v2i2 := pstringer("3")
- v2 := [3]pstringer{v2i0, v2i1, v2i2}
- v2i0Len := fmt.Sprintf("%d", len(v2i0))
- v2i1Len := fmt.Sprintf("%d", len(v2i1))
- v2i2Len := fmt.Sprintf("%d", len(v2i2))
- v2Len := fmt.Sprintf("%d", len(v2))
- v2Cap := fmt.Sprintf("%d", cap(v2))
- nv2 := (*[3]pstringer)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "spew_test.pstringer"
- v2sp := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t +
- ") (len=" + v2i0Len + ") stringer 1,\n (" + v2t +
- ") (len=" + v2i1Len + ") stringer 2,\n (" + v2t +
- ") (len=" + v2i2Len + ") " + "stringer 3\n}"
- v2s := v2sp
- if spew.UnsafeDisabled {
- v2s = "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t +
- ") (len=" + v2i0Len + ") \"1\",\n (" + v2t + ") (len=" +
- v2i1Len + ") \"2\",\n (" + v2t + ") (len=" + v2i2Len +
- ") " + "\"3\"\n}"
- }
- addDumpTest(v2, "([3]"+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*[3]"+v2t+")("+v2Addr+")("+v2sp+")\n")
- addDumpTest(&pv2, "(**[3]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2sp+")\n")
- addDumpTest(nv2, "(*[3]"+v2t+")(<nil>)\n")
-
- // Array containing interfaces.
- v3i0 := "one"
- v3 := [3]interface{}{v3i0, int(2), uint(3)}
- v3i0Len := fmt.Sprintf("%d", len(v3i0))
- v3Len := fmt.Sprintf("%d", len(v3))
- v3Cap := fmt.Sprintf("%d", cap(v3))
- nv3 := (*[3]interface{})(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "[3]interface {}"
- v3t2 := "string"
- v3t3 := "int"
- v3t4 := "uint"
- v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " +
- "(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" +
- v3t4 + ") 3\n}"
- addDumpTest(v3, "("+v3t+") "+v3s+"\n")
- addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n")
- addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n")
- addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
-
- // Array containing bytes.
- v4 := [34]byte{
- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32,
- }
- v4Len := fmt.Sprintf("%d", len(v4))
- v4Cap := fmt.Sprintf("%d", cap(v4))
- nv4 := (*[34]byte)(nil)
- pv4 := &v4
- v4Addr := fmt.Sprintf("%p", pv4)
- pv4Addr := fmt.Sprintf("%p", &pv4)
- v4t := "[34]uint8"
- v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " +
- "{\n 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20" +
- " |............... |\n" +
- " 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30" +
- " |!\"#$%&'()*+,-./0|\n" +
- " 00000020 31 32 " +
- " |12|\n}"
- addDumpTest(v4, "("+v4t+") "+v4s+"\n")
- addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n")
- addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n")
- addDumpTest(nv4, "(*"+v4t+")(<nil>)\n")
-}
-
-func addSliceDumpTests() {
- // Slice containing standard float32 values.
- v := []float32{3.14, 6.28, 12.56}
- vLen := fmt.Sprintf("%d", len(v))
- vCap := fmt.Sprintf("%d", cap(v))
- nv := (*[]float32)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "float32"
- vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 3.14,\n (" +
- vt + ") 6.28,\n (" + vt + ") 12.56\n}"
- addDumpTest(v, "([]"+vt+") "+vs+"\n")
- addDumpTest(pv, "(*[]"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**[]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*[]"+vt+")(<nil>)\n")
-
- // Slice containing type with custom formatter on pointer receiver only.
- v2i0 := pstringer("1")
- v2i1 := pstringer("2")
- v2i2 := pstringer("3")
- v2 := []pstringer{v2i0, v2i1, v2i2}
- v2i0Len := fmt.Sprintf("%d", len(v2i0))
- v2i1Len := fmt.Sprintf("%d", len(v2i1))
- v2i2Len := fmt.Sprintf("%d", len(v2i2))
- v2Len := fmt.Sprintf("%d", len(v2))
- v2Cap := fmt.Sprintf("%d", cap(v2))
- nv2 := (*[]pstringer)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "spew_test.pstringer"
- v2s := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + ") (len=" +
- v2i0Len + ") stringer 1,\n (" + v2t + ") (len=" + v2i1Len +
- ") stringer 2,\n (" + v2t + ") (len=" + v2i2Len + ") " +
- "stringer 3\n}"
- addDumpTest(v2, "([]"+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*[]"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**[]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
- addDumpTest(nv2, "(*[]"+v2t+")(<nil>)\n")
-
- // Slice containing interfaces.
- v3i0 := "one"
- v3 := []interface{}{v3i0, int(2), uint(3), nil}
- v3i0Len := fmt.Sprintf("%d", len(v3i0))
- v3Len := fmt.Sprintf("%d", len(v3))
- v3Cap := fmt.Sprintf("%d", cap(v3))
- nv3 := (*[]interface{})(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "[]interface {}"
- v3t2 := "string"
- v3t3 := "int"
- v3t4 := "uint"
- v3t5 := "interface {}"
- v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " +
- "(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" +
- v3t4 + ") 3,\n (" + v3t5 + ") <nil>\n}"
- addDumpTest(v3, "("+v3t+") "+v3s+"\n")
- addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n")
- addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n")
- addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
-
- // Slice containing bytes.
- v4 := []byte{
- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32,
- }
- v4Len := fmt.Sprintf("%d", len(v4))
- v4Cap := fmt.Sprintf("%d", cap(v4))
- nv4 := (*[]byte)(nil)
- pv4 := &v4
- v4Addr := fmt.Sprintf("%p", pv4)
- pv4Addr := fmt.Sprintf("%p", &pv4)
- v4t := "[]uint8"
- v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " +
- "{\n 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20" +
- " |............... |\n" +
- " 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30" +
- " |!\"#$%&'()*+,-./0|\n" +
- " 00000020 31 32 " +
- " |12|\n}"
- addDumpTest(v4, "("+v4t+") "+v4s+"\n")
- addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n")
- addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n")
- addDumpTest(nv4, "(*"+v4t+")(<nil>)\n")
-
- // Nil slice.
- v5 := []int(nil)
- nv5 := (*[]int)(nil)
- pv5 := &v5
- v5Addr := fmt.Sprintf("%p", pv5)
- pv5Addr := fmt.Sprintf("%p", &pv5)
- v5t := "[]int"
- v5s := "<nil>"
- addDumpTest(v5, "("+v5t+") "+v5s+"\n")
- addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n")
- addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n")
- addDumpTest(nv5, "(*"+v5t+")(<nil>)\n")
-}
-
-func addStringDumpTests() {
- // Standard string.
- v := "test"
- vLen := fmt.Sprintf("%d", len(v))
- nv := (*string)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "string"
- vs := "(len=" + vLen + ") \"test\""
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-}
-
-func addInterfaceDumpTests() {
- // Nil interface.
- var v interface{}
- nv := (*interface{})(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "interface {}"
- vs := "<nil>"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-
- // Sub-interface.
- v2 := interface{}(uint16(65535))
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "uint16"
- v2s := "65535"
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
-}
-
-func addMapDumpTests() {
- // Map with string keys and int vals.
- k := "one"
- kk := "two"
- m := map[string]int{k: 1, kk: 2}
- klen := fmt.Sprintf("%d", len(k)) // not kLen to shut golint up
- kkLen := fmt.Sprintf("%d", len(kk))
- mLen := fmt.Sprintf("%d", len(m))
- nilMap := map[string]int(nil)
- nm := (*map[string]int)(nil)
- pm := &m
- mAddr := fmt.Sprintf("%p", pm)
- pmAddr := fmt.Sprintf("%p", &pm)
- mt := "map[string]int"
- mt1 := "string"
- mt2 := "int"
- ms := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + klen + ") " +
- "\"one\": (" + mt2 + ") 1,\n (" + mt1 + ") (len=" + kkLen +
- ") \"two\": (" + mt2 + ") 2\n}"
- ms2 := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + kkLen + ") " +
- "\"two\": (" + mt2 + ") 2,\n (" + mt1 + ") (len=" + klen +
- ") \"one\": (" + mt2 + ") 1\n}"
- addDumpTest(m, "("+mt+") "+ms+"\n", "("+mt+") "+ms2+"\n")
- addDumpTest(pm, "(*"+mt+")("+mAddr+")("+ms+")\n",
- "(*"+mt+")("+mAddr+")("+ms2+")\n")
- addDumpTest(&pm, "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms+")\n",
- "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms2+")\n")
- addDumpTest(nm, "(*"+mt+")(<nil>)\n")
- addDumpTest(nilMap, "("+mt+") <nil>\n")
-
- // Map with custom formatter type on pointer receiver only keys and vals.
- k2 := pstringer("one")
- v2 := pstringer("1")
- m2 := map[pstringer]pstringer{k2: v2}
- k2Len := fmt.Sprintf("%d", len(k2))
- v2Len := fmt.Sprintf("%d", len(v2))
- m2Len := fmt.Sprintf("%d", len(m2))
- nilMap2 := map[pstringer]pstringer(nil)
- nm2 := (*map[pstringer]pstringer)(nil)
- pm2 := &m2
- m2Addr := fmt.Sprintf("%p", pm2)
- pm2Addr := fmt.Sprintf("%p", &pm2)
- m2t := "map[spew_test.pstringer]spew_test.pstringer"
- m2t1 := "spew_test.pstringer"
- m2t2 := "spew_test.pstringer"
- m2s := "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len + ") " +
- "stringer one: (" + m2t2 + ") (len=" + v2Len + ") stringer 1\n}"
- if spew.UnsafeDisabled {
- m2s = "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len +
- ") " + "\"one\": (" + m2t2 + ") (len=" + v2Len +
- ") \"1\"\n}"
- }
- addDumpTest(m2, "("+m2t+") "+m2s+"\n")
- addDumpTest(pm2, "(*"+m2t+")("+m2Addr+")("+m2s+")\n")
- addDumpTest(&pm2, "(**"+m2t+")("+pm2Addr+"->"+m2Addr+")("+m2s+")\n")
- addDumpTest(nm2, "(*"+m2t+")(<nil>)\n")
- addDumpTest(nilMap2, "("+m2t+") <nil>\n")
-
- // Map with interface keys and values.
- k3 := "one"
- k3Len := fmt.Sprintf("%d", len(k3))
- m3 := map[interface{}]interface{}{k3: 1}
- m3Len := fmt.Sprintf("%d", len(m3))
- nilMap3 := map[interface{}]interface{}(nil)
- nm3 := (*map[interface{}]interface{})(nil)
- pm3 := &m3
- m3Addr := fmt.Sprintf("%p", pm3)
- pm3Addr := fmt.Sprintf("%p", &pm3)
- m3t := "map[interface {}]interface {}"
- m3t1 := "string"
- m3t2 := "int"
- m3s := "(len=" + m3Len + ") {\n (" + m3t1 + ") (len=" + k3Len + ") " +
- "\"one\": (" + m3t2 + ") 1\n}"
- addDumpTest(m3, "("+m3t+") "+m3s+"\n")
- addDumpTest(pm3, "(*"+m3t+")("+m3Addr+")("+m3s+")\n")
- addDumpTest(&pm3, "(**"+m3t+")("+pm3Addr+"->"+m3Addr+")("+m3s+")\n")
- addDumpTest(nm3, "(*"+m3t+")(<nil>)\n")
- addDumpTest(nilMap3, "("+m3t+") <nil>\n")
-
- // Map with nil interface value.
- k4 := "nil"
- k4Len := fmt.Sprintf("%d", len(k4))
- m4 := map[string]interface{}{k4: nil}
- m4Len := fmt.Sprintf("%d", len(m4))
- nilMap4 := map[string]interface{}(nil)
- nm4 := (*map[string]interface{})(nil)
- pm4 := &m4
- m4Addr := fmt.Sprintf("%p", pm4)
- pm4Addr := fmt.Sprintf("%p", &pm4)
- m4t := "map[string]interface {}"
- m4t1 := "string"
- m4t2 := "interface {}"
- m4s := "(len=" + m4Len + ") {\n (" + m4t1 + ") (len=" + k4Len + ")" +
- " \"nil\": (" + m4t2 + ") <nil>\n}"
- addDumpTest(m4, "("+m4t+") "+m4s+"\n")
- addDumpTest(pm4, "(*"+m4t+")("+m4Addr+")("+m4s+")\n")
- addDumpTest(&pm4, "(**"+m4t+")("+pm4Addr+"->"+m4Addr+")("+m4s+")\n")
- addDumpTest(nm4, "(*"+m4t+")(<nil>)\n")
- addDumpTest(nilMap4, "("+m4t+") <nil>\n")
-}
-
-func addStructDumpTests() {
- // Struct with primitives.
- type s1 struct {
- a int8
- b uint8
- }
- v := s1{127, 255}
- nv := (*s1)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "spew_test.s1"
- vt2 := "int8"
- vt3 := "uint8"
- vs := "{\n a: (" + vt2 + ") 127,\n b: (" + vt3 + ") 255\n}"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-
- // Struct that contains another struct.
- type s2 struct {
- s1 s1
- b bool
- }
- v2 := s2{s1{127, 255}, true}
- nv2 := (*s2)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "spew_test.s2"
- v2t2 := "spew_test.s1"
- v2t3 := "int8"
- v2t4 := "uint8"
- v2t5 := "bool"
- v2s := "{\n s1: (" + v2t2 + ") {\n a: (" + v2t3 + ") 127,\n b: (" +
- v2t4 + ") 255\n },\n b: (" + v2t5 + ") true\n}"
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
- addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
-
- // Struct that contains custom type with Stringer pointer interface via both
- // exported and unexported fields.
- type s3 struct {
- s pstringer
- S pstringer
- }
- v3 := s3{"test", "test2"}
- nv3 := (*s3)(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "spew_test.s3"
- v3t2 := "spew_test.pstringer"
- v3s := "{\n s: (" + v3t2 + ") (len=4) stringer test,\n S: (" + v3t2 +
- ") (len=5) stringer test2\n}"
- v3sp := v3s
- if spew.UnsafeDisabled {
- v3s = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" +
- v3t2 + ") (len=5) \"test2\"\n}"
- v3sp = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" +
- v3t2 + ") (len=5) stringer test2\n}"
- }
- addDumpTest(v3, "("+v3t+") "+v3s+"\n")
- addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3sp+")\n")
- addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3sp+")\n")
- addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
-
- // Struct that contains embedded struct and field to same struct.
- e := embed{"embedstr"}
- eLen := fmt.Sprintf("%d", len("embedstr"))
- v4 := embedwrap{embed: &e, e: &e}
- nv4 := (*embedwrap)(nil)
- pv4 := &v4
- eAddr := fmt.Sprintf("%p", &e)
- v4Addr := fmt.Sprintf("%p", pv4)
- pv4Addr := fmt.Sprintf("%p", &pv4)
- v4t := "spew_test.embedwrap"
- v4t2 := "spew_test.embed"
- v4t3 := "string"
- v4s := "{\n embed: (*" + v4t2 + ")(" + eAddr + ")({\n a: (" + v4t3 +
- ") (len=" + eLen + ") \"embedstr\"\n }),\n e: (*" + v4t2 +
- ")(" + eAddr + ")({\n a: (" + v4t3 + ") (len=" + eLen + ")" +
- " \"embedstr\"\n })\n}"
- addDumpTest(v4, "("+v4t+") "+v4s+"\n")
- addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n")
- addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n")
- addDumpTest(nv4, "(*"+v4t+")(<nil>)\n")
-}
-
-func addUintptrDumpTests() {
- // Null pointer.
- v := uintptr(0)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "uintptr"
- vs := "<nil>"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
-
- // Address of real variable.
- i := 1
- v2 := uintptr(unsafe.Pointer(&i))
- nv2 := (*uintptr)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "uintptr"
- v2s := fmt.Sprintf("%p", &i)
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
- addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
-}
-
-func addUnsafePointerDumpTests() {
- // Null pointer.
- v := unsafe.Pointer(uintptr(0))
- nv := (*unsafe.Pointer)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "unsafe.Pointer"
- vs := "<nil>"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-
- // Address of real variable.
- i := 1
- v2 := unsafe.Pointer(&i)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "unsafe.Pointer"
- v2s := fmt.Sprintf("%p", &i)
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-}
-
-func addChanDumpTests() {
- // Nil channel.
- var v chan int
- pv := &v
- nv := (*chan int)(nil)
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "chan int"
- vs := "<nil>"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-
- // Real channel.
- v2 := make(chan int)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "chan int"
- v2s := fmt.Sprintf("%p", v2)
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
-}
-
-func addFuncDumpTests() {
- // Function with no params and no returns.
- v := addIntDumpTests
- nv := (*func())(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "func()"
- vs := fmt.Sprintf("%p", v)
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-
- // Function with param and no returns.
- v2 := TestDump
- nv2 := (*func(*testing.T))(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "func(*testing.T)"
- v2s := fmt.Sprintf("%p", v2)
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
- addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
-
- // Function with multiple params and multiple returns.
- var v3 = func(i int, s string) (b bool, err error) {
- return true, nil
- }
- nv3 := (*func(int, string) (bool, error))(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "func(int, string) (bool, error)"
- v3s := fmt.Sprintf("%p", v3)
- addDumpTest(v3, "("+v3t+") "+v3s+"\n")
- addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n")
- addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n")
- addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
-}
-
-func addCircularDumpTests() {
- // Struct that is circular through self referencing.
- type circular struct {
- c *circular
- }
- v := circular{nil}
- v.c = &v
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "spew_test.circular"
- vs := "{\n c: (*" + vt + ")(" + vAddr + ")({\n c: (*" + vt + ")(" +
- vAddr + ")(<already shown>)\n })\n}"
- vs2 := "{\n c: (*" + vt + ")(" + vAddr + ")(<already shown>)\n}"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs2+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs2+")\n")
-
- // Structs that are circular through cross referencing.
- v2 := xref1{nil}
- ts2 := xref2{&v2}
- v2.ps2 = &ts2
- pv2 := &v2
- ts2Addr := fmt.Sprintf("%p", &ts2)
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "spew_test.xref1"
- v2t2 := "spew_test.xref2"
- v2s := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n ps1: (*" + v2t +
- ")(" + v2Addr + ")({\n ps2: (*" + v2t2 + ")(" + ts2Addr +
- ")(<already shown>)\n })\n })\n}"
- v2s2 := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n ps1: (*" + v2t +
- ")(" + v2Addr + ")(<already shown>)\n })\n}"
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
- addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s2+")\n")
- addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s2+")\n")
-
- // Structs that are indirectly circular.
- v3 := indirCir1{nil}
- tic2 := indirCir2{nil}
- tic3 := indirCir3{&v3}
- tic2.ps3 = &tic3
- v3.ps2 = &tic2
- pv3 := &v3
- tic2Addr := fmt.Sprintf("%p", &tic2)
- tic3Addr := fmt.Sprintf("%p", &tic3)
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "spew_test.indirCir1"
- v3t2 := "spew_test.indirCir2"
- v3t3 := "spew_test.indirCir3"
- v3s := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n ps3: (*" + v3t3 +
- ")(" + tic3Addr + ")({\n ps1: (*" + v3t + ")(" + v3Addr +
- ")({\n ps2: (*" + v3t2 + ")(" + tic2Addr +
- ")(<already shown>)\n })\n })\n })\n}"
- v3s2 := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n ps3: (*" + v3t3 +
- ")(" + tic3Addr + ")({\n ps1: (*" + v3t + ")(" + v3Addr +
- ")(<already shown>)\n })\n })\n}"
- addDumpTest(v3, "("+v3t+") "+v3s+"\n")
- addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s2+")\n")
- addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s2+")\n")
-}
-
-func addPanicDumpTests() {
- // Type that panics in its Stringer interface.
- v := panicer(127)
- nv := (*panicer)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "spew_test.panicer"
- vs := "(PANIC=test panic)127"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-}
-
-func addErrorDumpTests() {
- // Type that has a custom Error interface.
- v := customError(127)
- nv := (*customError)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "spew_test.customError"
- vs := "error: 127"
- addDumpTest(v, "("+vt+") "+vs+"\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
- addDumpTest(nv, "(*"+vt+")(<nil>)\n")
-}
-
-// TestDump executes all of the tests described by dumpTests.
-func TestDump(t *testing.T) {
- // Setup tests.
- addIntDumpTests()
- addUintDumpTests()
- addBoolDumpTests()
- addFloatDumpTests()
- addComplexDumpTests()
- addArrayDumpTests()
- addSliceDumpTests()
- addStringDumpTests()
- addInterfaceDumpTests()
- addMapDumpTests()
- addStructDumpTests()
- addUintptrDumpTests()
- addUnsafePointerDumpTests()
- addChanDumpTests()
- addFuncDumpTests()
- addCircularDumpTests()
- addPanicDumpTests()
- addErrorDumpTests()
- addCgoDumpTests()
-
- t.Logf("Running %d tests", len(dumpTests))
- for i, test := range dumpTests {
- buf := new(bytes.Buffer)
- spew.Fdump(buf, test.in)
- s := buf.String()
- if testFailed(s, test.wants) {
- t.Errorf("Dump #%d\n got: %s %s", i, s, stringizeWants(test.wants))
- continue
- }
- }
-}
-
-func TestDumpSortedKeys(t *testing.T) {
- cfg := spew.ConfigState{SortKeys: true}
- s := cfg.Sdump(map[int]string{1: "1", 3: "3", 2: "2"})
- expected := "(map[int]string) (len=3) {\n(int) 1: (string) (len=1) " +
- "\"1\",\n(int) 2: (string) (len=1) \"2\",\n(int) 3: (string) " +
- "(len=1) \"3\"\n" +
- "}\n"
- if s != expected {
- t.Errorf("Sorted keys mismatch:\n %v %v", s, expected)
- }
-
- s = cfg.Sdump(map[stringer]int{"1": 1, "3": 3, "2": 2})
- expected = "(map[spew_test.stringer]int) (len=3) {\n" +
- "(spew_test.stringer) (len=1) stringer 1: (int) 1,\n" +
- "(spew_test.stringer) (len=1) stringer 2: (int) 2,\n" +
- "(spew_test.stringer) (len=1) stringer 3: (int) 3\n" +
- "}\n"
- if s != expected {
- t.Errorf("Sorted keys mismatch:\n %v %v", s, expected)
- }
-
- s = cfg.Sdump(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2})
- expected = "(map[spew_test.pstringer]int) (len=3) {\n" +
- "(spew_test.pstringer) (len=1) stringer 1: (int) 1,\n" +
- "(spew_test.pstringer) (len=1) stringer 2: (int) 2,\n" +
- "(spew_test.pstringer) (len=1) stringer 3: (int) 3\n" +
- "}\n"
- if spew.UnsafeDisabled {
- expected = "(map[spew_test.pstringer]int) (len=3) {\n" +
- "(spew_test.pstringer) (len=1) \"1\": (int) 1,\n" +
- "(spew_test.pstringer) (len=1) \"2\": (int) 2,\n" +
- "(spew_test.pstringer) (len=1) \"3\": (int) 3\n" +
- "}\n"
- }
- if s != expected {
- t.Errorf("Sorted keys mismatch:\n %v %v", s, expected)
- }
-
- s = cfg.Sdump(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2})
- expected = "(map[spew_test.customError]int) (len=3) {\n" +
- "(spew_test.customError) error: 1: (int) 1,\n" +
- "(spew_test.customError) error: 2: (int) 2,\n" +
- "(spew_test.customError) error: 3: (int) 3\n" +
- "}\n"
- if s != expected {
- t.Errorf("Sorted keys mismatch:\n %v %v", s, expected)
- }
-
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go
deleted file mode 100644
index 18a38358e..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2013 Dave Collins <dave@davec.name>
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-// NOTE: Due to the following build constraints, this file will only be compiled
-// when both cgo is supported and "-tags testcgo" is added to the go test
-// command line. This means the cgo tests are only added (and hence run) when
-// specifially requested. This configuration is used because spew itself
-// does not require cgo to run even though it does handle certain cgo types
-// specially. Rather than forcing all clients to require cgo and an external
-// C compiler just to run the tests, this scheme makes them optional.
-// +build cgo,testcgo
-
-package spew_test
-
-import (
- "fmt"
-
- "github.com/davecgh/go-spew/spew/testdata"
-)
-
-func addCgoDumpTests() {
- // C char pointer.
- v := testdata.GetCgoCharPointer()
- nv := testdata.GetCgoNullCharPointer()
- pv := &v
- vcAddr := fmt.Sprintf("%p", v)
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "*testdata._Ctype_char"
- vs := "116"
- addDumpTest(v, "("+vt+")("+vcAddr+")("+vs+")\n")
- addDumpTest(pv, "(*"+vt+")("+vAddr+"->"+vcAddr+")("+vs+")\n")
- addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+"->"+vcAddr+")("+vs+")\n")
- addDumpTest(nv, "("+vt+")(<nil>)\n")
-
- // C char array.
- v2, v2l, v2c := testdata.GetCgoCharArray()
- v2Len := fmt.Sprintf("%d", v2l)
- v2Cap := fmt.Sprintf("%d", v2c)
- v2t := "[6]testdata._Ctype_char"
- v2s := "(len=" + v2Len + " cap=" + v2Cap + ") " +
- "{\n 00000000 74 65 73 74 32 00 " +
- " |test2.|\n}"
- addDumpTest(v2, "("+v2t+") "+v2s+"\n")
-
- // C unsigned char array.
- v3, v3l, v3c := testdata.GetCgoUnsignedCharArray()
- v3Len := fmt.Sprintf("%d", v3l)
- v3Cap := fmt.Sprintf("%d", v3c)
- v3t := "[6]testdata._Ctype_unsignedchar"
- v3s := "(len=" + v3Len + " cap=" + v3Cap + ") " +
- "{\n 00000000 74 65 73 74 33 00 " +
- " |test3.|\n}"
- addDumpTest(v3, "("+v3t+") "+v3s+"\n")
-
- // C signed char array.
- v4, v4l, v4c := testdata.GetCgoSignedCharArray()
- v4Len := fmt.Sprintf("%d", v4l)
- v4Cap := fmt.Sprintf("%d", v4c)
- v4t := "[6]testdata._Ctype_schar"
- v4t2 := "testdata._Ctype_schar"
- v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " +
- "{\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 101,\n (" + v4t2 +
- ") 115,\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 52,\n (" + v4t2 +
- ") 0\n}"
- addDumpTest(v4, "("+v4t+") "+v4s+"\n")
-
- // C uint8_t array.
- v5, v5l, v5c := testdata.GetCgoUint8tArray()
- v5Len := fmt.Sprintf("%d", v5l)
- v5Cap := fmt.Sprintf("%d", v5c)
- v5t := "[6]testdata._Ctype_uint8_t"
- v5s := "(len=" + v5Len + " cap=" + v5Cap + ") " +
- "{\n 00000000 74 65 73 74 35 00 " +
- " |test5.|\n}"
- addDumpTest(v5, "("+v5t+") "+v5s+"\n")
-
- // C typedefed unsigned char array.
- v6, v6l, v6c := testdata.GetCgoTypdefedUnsignedCharArray()
- v6Len := fmt.Sprintf("%d", v6l)
- v6Cap := fmt.Sprintf("%d", v6c)
- v6t := "[6]testdata._Ctype_custom_uchar_t"
- v6s := "(len=" + v6Len + " cap=" + v6Cap + ") " +
- "{\n 00000000 74 65 73 74 36 00 " +
- " |test6.|\n}"
- addDumpTest(v6, "("+v6t+") "+v6s+"\n")
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go
deleted file mode 100644
index 52a0971fb..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2013 Dave Collins <dave@davec.name>
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-// NOTE: Due to the following build constraints, this file will only be compiled
-// when either cgo is not supported or "-tags testcgo" is not added to the go
-// test command line. This file intentionally does not setup any cgo tests in
-// this scenario.
-// +build !cgo !testcgo
-
-package spew_test
-
-func addCgoDumpTests() {
- // Don't add any tests for cgo since this file is only compiled when
- // there should not be any cgo tests.
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/example_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/example_test.go
deleted file mode 100644
index de6c4e309..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/example_test.go
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package spew_test
-
-import (
- "fmt"
-
- "github.com/davecgh/go-spew/spew"
-)
-
-type Flag int
-
-const (
- flagOne Flag = iota
- flagTwo
-)
-
-var flagStrings = map[Flag]string{
- flagOne: "flagOne",
- flagTwo: "flagTwo",
-}
-
-func (f Flag) String() string {
- if s, ok := flagStrings[f]; ok {
- return s
- }
- return fmt.Sprintf("Unknown flag (%d)", int(f))
-}
-
-type Bar struct {
- data uintptr
-}
-
-type Foo struct {
- unexportedField Bar
- ExportedField map[interface{}]interface{}
-}
-
-// This example demonstrates how to use Dump to dump variables to stdout.
-func ExampleDump() {
- // The following package level declarations are assumed for this example:
- /*
- type Flag int
-
- const (
- flagOne Flag = iota
- flagTwo
- )
-
- var flagStrings = map[Flag]string{
- flagOne: "flagOne",
- flagTwo: "flagTwo",
- }
-
- func (f Flag) String() string {
- if s, ok := flagStrings[f]; ok {
- return s
- }
- return fmt.Sprintf("Unknown flag (%d)", int(f))
- }
-
- type Bar struct {
- data uintptr
- }
-
- type Foo struct {
- unexportedField Bar
- ExportedField map[interface{}]interface{}
- }
- */
-
- // Setup some sample data structures for the example.
- bar := Bar{uintptr(0)}
- s1 := Foo{bar, map[interface{}]interface{}{"one": true}}
- f := Flag(5)
- b := []byte{
- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32,
- }
-
- // Dump!
- spew.Dump(s1, f, b)
-
- // Output:
- // (spew_test.Foo) {
- // unexportedField: (spew_test.Bar) {
- // data: (uintptr) <nil>
- // },
- // ExportedField: (map[interface {}]interface {}) (len=1) {
- // (string) (len=3) "one": (bool) true
- // }
- // }
- // (spew_test.Flag) Unknown flag (5)
- // ([]uint8) (len=34 cap=34) {
- // 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
- // 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
- // 00000020 31 32 |12|
- // }
- //
-}
-
-// This example demonstrates how to use Printf to display a variable with a
-// format string and inline formatting.
-func ExamplePrintf() {
- // Create a double pointer to a uint 8.
- ui8 := uint8(5)
- pui8 := &ui8
- ppui8 := &pui8
-
- // Create a circular data type.
- type circular struct {
- ui8 uint8
- c *circular
- }
- c := circular{ui8: 1}
- c.c = &c
-
- // Print!
- spew.Printf("ppui8: %v\n", ppui8)
- spew.Printf("circular: %v\n", c)
-
- // Output:
- // ppui8: <**>5
- // circular: {1 <*>{1 <*><shown>}}
-}
-
-// This example demonstrates how to use a ConfigState.
-func ExampleConfigState() {
- // Modify the indent level of the ConfigState only. The global
- // configuration is not modified.
- scs := spew.ConfigState{Indent: "\t"}
-
- // Output using the ConfigState instance.
- v := map[string]int{"one": 1}
- scs.Printf("v: %v\n", v)
- scs.Dump(v)
-
- // Output:
- // v: map[one:1]
- // (map[string]int) (len=1) {
- // (string) (len=3) "one": (int) 1
- // }
-}
-
-// This example demonstrates how to use ConfigState.Dump to dump variables to
-// stdout
-func ExampleConfigState_Dump() {
- // See the top-level Dump example for details on the types used in this
- // example.
-
- // Create two ConfigState instances with different indentation.
- scs := spew.ConfigState{Indent: "\t"}
- scs2 := spew.ConfigState{Indent: " "}
-
- // Setup some sample data structures for the example.
- bar := Bar{uintptr(0)}
- s1 := Foo{bar, map[interface{}]interface{}{"one": true}}
-
- // Dump using the ConfigState instances.
- scs.Dump(s1)
- scs2.Dump(s1)
-
- // Output:
- // (spew_test.Foo) {
- // unexportedField: (spew_test.Bar) {
- // data: (uintptr) <nil>
- // },
- // ExportedField: (map[interface {}]interface {}) (len=1) {
- // (string) (len=3) "one": (bool) true
- // }
- // }
- // (spew_test.Foo) {
- // unexportedField: (spew_test.Bar) {
- // data: (uintptr) <nil>
- // },
- // ExportedField: (map[interface {}]interface {}) (len=1) {
- // (string) (len=3) "one": (bool) true
- // }
- // }
- //
-}
-
-// This example demonstrates how to use ConfigState.Printf to display a variable
-// with a format string and inline formatting.
-func ExampleConfigState_Printf() {
- // See the top-level Dump example for details on the types used in this
- // example.
-
- // Create two ConfigState instances and modify the method handling of the
- // first ConfigState only.
- scs := spew.NewDefaultConfig()
- scs2 := spew.NewDefaultConfig()
- scs.DisableMethods = true
-
- // Alternatively
- // scs := spew.ConfigState{Indent: " ", DisableMethods: true}
- // scs2 := spew.ConfigState{Indent: " "}
-
- // This is of type Flag which implements a Stringer and has raw value 1.
- f := flagTwo
-
- // Dump using the ConfigState instances.
- scs.Printf("f: %v\n", f)
- scs2.Printf("f: %v\n", f)
-
- // Output:
- // f: 1
- // f: flagTwo
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format.go
deleted file mode 100644
index ecf3b80e2..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format.go
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package spew
-
-import (
- "bytes"
- "fmt"
- "reflect"
- "strconv"
- "strings"
-)
-
-// supportedFlags is a list of all the character flags supported by fmt package.
-const supportedFlags = "0-+# "
-
-// formatState implements the fmt.Formatter interface and contains information
-// about the state of a formatting operation. The NewFormatter function can
-// be used to get a new Formatter which can be used directly as arguments
-// in standard fmt package printing calls.
-type formatState struct {
- value interface{}
- fs fmt.State
- depth int
- pointers map[uintptr]int
- ignoreNextType bool
- cs *ConfigState
-}
-
-// buildDefaultFormat recreates the original format string without precision
-// and width information to pass in to fmt.Sprintf in the case of an
-// unrecognized type. Unless new types are added to the language, this
-// function won't ever be called.
-func (f *formatState) buildDefaultFormat() (format string) {
- buf := bytes.NewBuffer(percentBytes)
-
- for _, flag := range supportedFlags {
- if f.fs.Flag(int(flag)) {
- buf.WriteRune(flag)
- }
- }
-
- buf.WriteRune('v')
-
- format = buf.String()
- return format
-}
-
-// constructOrigFormat recreates the original format string including precision
-// and width information to pass along to the standard fmt package. This allows
-// automatic deferral of all format strings this package doesn't support.
-func (f *formatState) constructOrigFormat(verb rune) (format string) {
- buf := bytes.NewBuffer(percentBytes)
-
- for _, flag := range supportedFlags {
- if f.fs.Flag(int(flag)) {
- buf.WriteRune(flag)
- }
- }
-
- if width, ok := f.fs.Width(); ok {
- buf.WriteString(strconv.Itoa(width))
- }
-
- if precision, ok := f.fs.Precision(); ok {
- buf.Write(precisionBytes)
- buf.WriteString(strconv.Itoa(precision))
- }
-
- buf.WriteRune(verb)
-
- format = buf.String()
- return format
-}
-
-// unpackValue returns values inside of non-nil interfaces when possible and
-// ensures that types for values which have been unpacked from an interface
-// are displayed when the show types flag is also set.
-// This is useful for data types like structs, arrays, slices, and maps which
-// can contain varying types packed inside an interface.
-func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
- if v.Kind() == reflect.Interface {
- f.ignoreNextType = false
- if !v.IsNil() {
- v = v.Elem()
- }
- }
- return v
-}
-
-// formatPtr handles formatting of pointers by indirecting them as necessary.
-func (f *formatState) formatPtr(v reflect.Value) {
- // Display nil if top level pointer is nil.
- showTypes := f.fs.Flag('#')
- if v.IsNil() && (!showTypes || f.ignoreNextType) {
- f.fs.Write(nilAngleBytes)
- return
- }
-
- // Remove pointers at or below the current depth from map used to detect
- // circular refs.
- for k, depth := range f.pointers {
- if depth >= f.depth {
- delete(f.pointers, k)
- }
- }
-
- // Keep list of all dereferenced pointers to possibly show later.
- pointerChain := make([]uintptr, 0)
-
- // Figure out how many levels of indirection there are by derferencing
- // pointers and unpacking interfaces down the chain while detecting circular
- // references.
- nilFound := false
- cycleFound := false
- indirects := 0
- ve := v
- for ve.Kind() == reflect.Ptr {
- if ve.IsNil() {
- nilFound = true
- break
- }
- indirects++
- addr := ve.Pointer()
- pointerChain = append(pointerChain, addr)
- if pd, ok := f.pointers[addr]; ok && pd < f.depth {
- cycleFound = true
- indirects--
- break
- }
- f.pointers[addr] = f.depth
-
- ve = ve.Elem()
- if ve.Kind() == reflect.Interface {
- if ve.IsNil() {
- nilFound = true
- break
- }
- ve = ve.Elem()
- }
- }
-
- // Display type or indirection level depending on flags.
- if showTypes && !f.ignoreNextType {
- f.fs.Write(openParenBytes)
- f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
- f.fs.Write([]byte(ve.Type().String()))
- f.fs.Write(closeParenBytes)
- } else {
- if nilFound || cycleFound {
- indirects += strings.Count(ve.Type().String(), "*")
- }
- f.fs.Write(openAngleBytes)
- f.fs.Write([]byte(strings.Repeat("*", indirects)))
- f.fs.Write(closeAngleBytes)
- }
-
- // Display pointer information depending on flags.
- if f.fs.Flag('+') && (len(pointerChain) > 0) {
- f.fs.Write(openParenBytes)
- for i, addr := range pointerChain {
- if i > 0 {
- f.fs.Write(pointerChainBytes)
- }
- printHexPtr(f.fs, addr)
- }
- f.fs.Write(closeParenBytes)
- }
-
- // Display dereferenced value.
- switch {
- case nilFound == true:
- f.fs.Write(nilAngleBytes)
-
- case cycleFound == true:
- f.fs.Write(circularShortBytes)
-
- default:
- f.ignoreNextType = true
- f.format(ve)
- }
-}
-
-// format is the main workhorse for providing the Formatter interface. It
-// uses the passed reflect value to figure out what kind of object we are
-// dealing with and formats it appropriately. It is a recursive function,
-// however circular data structures are detected and handled properly.
-func (f *formatState) format(v reflect.Value) {
- // Handle invalid reflect values immediately.
- kind := v.Kind()
- if kind == reflect.Invalid {
- f.fs.Write(invalidAngleBytes)
- return
- }
-
- // Handle pointers specially.
- if kind == reflect.Ptr {
- f.formatPtr(v)
- return
- }
-
- // Print type information unless already handled elsewhere.
- if !f.ignoreNextType && f.fs.Flag('#') {
- f.fs.Write(openParenBytes)
- f.fs.Write([]byte(v.Type().String()))
- f.fs.Write(closeParenBytes)
- }
- f.ignoreNextType = false
-
- // Call Stringer/error interfaces if they exist and the handle methods
- // flag is enabled.
- if !f.cs.DisableMethods {
- if (kind != reflect.Invalid) && (kind != reflect.Interface) {
- if handled := handleMethods(f.cs, f.fs, v); handled {
- return
- }
- }
- }
-
- switch kind {
- case reflect.Invalid:
- // Do nothing. We should never get here since invalid has already
- // been handled above.
-
- case reflect.Bool:
- printBool(f.fs, v.Bool())
-
- case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
- printInt(f.fs, v.Int(), 10)
-
- case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
- printUint(f.fs, v.Uint(), 10)
-
- case reflect.Float32:
- printFloat(f.fs, v.Float(), 32)
-
- case reflect.Float64:
- printFloat(f.fs, v.Float(), 64)
-
- case reflect.Complex64:
- printComplex(f.fs, v.Complex(), 32)
-
- case reflect.Complex128:
- printComplex(f.fs, v.Complex(), 64)
-
- case reflect.Slice:
- if v.IsNil() {
- f.fs.Write(nilAngleBytes)
- break
- }
- fallthrough
-
- case reflect.Array:
- f.fs.Write(openBracketBytes)
- f.depth++
- if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
- f.fs.Write(maxShortBytes)
- } else {
- numEntries := v.Len()
- for i := 0; i < numEntries; i++ {
- if i > 0 {
- f.fs.Write(spaceBytes)
- }
- f.ignoreNextType = true
- f.format(f.unpackValue(v.Index(i)))
- }
- }
- f.depth--
- f.fs.Write(closeBracketBytes)
-
- case reflect.String:
- f.fs.Write([]byte(v.String()))
-
- case reflect.Interface:
- // The only time we should get here is for nil interfaces due to
- // unpackValue calls.
- if v.IsNil() {
- f.fs.Write(nilAngleBytes)
- }
-
- case reflect.Ptr:
- // Do nothing. We should never get here since pointers have already
- // been handled above.
-
- case reflect.Map:
- // nil maps should be indicated as different than empty maps
- if v.IsNil() {
- f.fs.Write(nilAngleBytes)
- break
- }
-
- f.fs.Write(openMapBytes)
- f.depth++
- if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
- f.fs.Write(maxShortBytes)
- } else {
- keys := v.MapKeys()
- if f.cs.SortKeys {
- sortValues(keys, f.cs)
- }
- for i, key := range keys {
- if i > 0 {
- f.fs.Write(spaceBytes)
- }
- f.ignoreNextType = true
- f.format(f.unpackValue(key))
- f.fs.Write(colonBytes)
- f.ignoreNextType = true
- f.format(f.unpackValue(v.MapIndex(key)))
- }
- }
- f.depth--
- f.fs.Write(closeMapBytes)
-
- case reflect.Struct:
- numFields := v.NumField()
- f.fs.Write(openBraceBytes)
- f.depth++
- if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
- f.fs.Write(maxShortBytes)
- } else {
- vt := v.Type()
- for i := 0; i < numFields; i++ {
- if i > 0 {
- f.fs.Write(spaceBytes)
- }
- vtf := vt.Field(i)
- if f.fs.Flag('+') || f.fs.Flag('#') {
- f.fs.Write([]byte(vtf.Name))
- f.fs.Write(colonBytes)
- }
- f.format(f.unpackValue(v.Field(i)))
- }
- }
- f.depth--
- f.fs.Write(closeBraceBytes)
-
- case reflect.Uintptr:
- printHexPtr(f.fs, uintptr(v.Uint()))
-
- case reflect.UnsafePointer, reflect.Chan, reflect.Func:
- printHexPtr(f.fs, v.Pointer())
-
- // There were not any other types at the time this code was written, but
- // fall back to letting the default fmt package handle it if any get added.
- default:
- format := f.buildDefaultFormat()
- if v.CanInterface() {
- fmt.Fprintf(f.fs, format, v.Interface())
- } else {
- fmt.Fprintf(f.fs, format, v.String())
- }
- }
-}
-
-// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
-// details.
-func (f *formatState) Format(fs fmt.State, verb rune) {
- f.fs = fs
-
- // Use standard formatting for verbs that are not v.
- if verb != 'v' {
- format := f.constructOrigFormat(verb)
- fmt.Fprintf(fs, format, f.value)
- return
- }
-
- if f.value == nil {
- if fs.Flag('#') {
- fs.Write(interfaceBytes)
- }
- fs.Write(nilAngleBytes)
- return
- }
-
- f.format(reflect.ValueOf(f.value))
-}
-
-// newFormatter is a helper function to consolidate the logic from the various
-// public methods which take varying config states.
-func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
- fs := &formatState{value: v, cs: cs}
- fs.pointers = make(map[uintptr]int)
- return fs
-}
-
-/*
-NewFormatter returns a custom formatter that satisfies the fmt.Formatter
-interface. As a result, it integrates cleanly with standard fmt package
-printing functions. The formatter is useful for inline printing of smaller data
-types similar to the standard %v format specifier.
-
-The custom formatter only responds to the %v (most compact), %+v (adds pointer
-addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
-combinations. Any other verbs such as %x and %q will be sent to the the
-standard fmt package for formatting. In addition, the custom formatter ignores
-the width and precision arguments (however they will still work on the format
-specifiers not handled by the custom formatter).
-
-Typically this function shouldn't be called directly. It is much easier to make
-use of the custom formatter by calling one of the convenience functions such as
-Printf, Println, or Fprintf.
-*/
-func NewFormatter(v interface{}) fmt.Formatter {
- return newFormatter(&Config, v)
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format_test.go
deleted file mode 100644
index b664b3f13..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format_test.go
+++ /dev/null
@@ -1,1558 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
-Test Summary:
-NOTE: For each test, a nil pointer, a single pointer and double pointer to the
-base test element are also tested to ensure proper indirection across all types.
-
-- Max int8, int16, int32, int64, int
-- Max uint8, uint16, uint32, uint64, uint
-- Boolean true and false
-- Standard complex64 and complex128
-- Array containing standard ints
-- Array containing type with custom formatter on pointer receiver only
-- Array containing interfaces
-- Slice containing standard float32 values
-- Slice containing type with custom formatter on pointer receiver only
-- Slice containing interfaces
-- Nil slice
-- Standard string
-- Nil interface
-- Sub-interface
-- Map with string keys and int vals
-- Map with custom formatter type on pointer receiver only keys and vals
-- Map with interface keys and values
-- Map with nil interface value
-- Struct with primitives
-- Struct that contains another struct
-- Struct that contains custom type with Stringer pointer interface via both
- exported and unexported fields
-- Struct that contains embedded struct and field to same struct
-- Uintptr to 0 (null pointer)
-- Uintptr address of real variable
-- Unsafe.Pointer to 0 (null pointer)
-- Unsafe.Pointer to address of real variable
-- Nil channel
-- Standard int channel
-- Function with no params and no returns
-- Function with param and no returns
-- Function with multiple params and multiple returns
-- Struct that is circular through self referencing
-- Structs that are circular through cross referencing
-- Structs that are indirectly circular
-- Type that panics in its Stringer interface
-- Type that has a custom Error interface
-- %x passthrough with uint
-- %#x passthrough with uint
-- %f passthrough with precision
-- %f passthrough with width and precision
-- %d passthrough with width
-- %q passthrough with string
-*/
-
-package spew_test
-
-import (
- "bytes"
- "fmt"
- "testing"
- "unsafe"
-
- "github.com/davecgh/go-spew/spew"
-)
-
-// formatterTest is used to describe a test to be perfomed against NewFormatter.
-type formatterTest struct {
- format string
- in interface{}
- wants []string
-}
-
-// formatterTests houses all of the tests to be performed against NewFormatter.
-var formatterTests = make([]formatterTest, 0)
-
-// addFormatterTest is a helper method to append the passed input and desired
-// result to formatterTests.
-func addFormatterTest(format string, in interface{}, wants ...string) {
- test := formatterTest{format, in, wants}
- formatterTests = append(formatterTests, test)
-}
-
-func addIntFormatterTests() {
- // Max int8.
- v := int8(127)
- nv := (*int8)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "int8"
- vs := "127"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Max int16.
- v2 := int16(32767)
- nv2 := (*int16)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "int16"
- v2s := "32767"
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%v", nv2, "<nil>")
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
-
- // Max int32.
- v3 := int32(2147483647)
- nv3 := (*int32)(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "int32"
- v3s := "2147483647"
- addFormatterTest("%v", v3, v3s)
- addFormatterTest("%v", pv3, "<*>"+v3s)
- addFormatterTest("%v", &pv3, "<**>"+v3s)
- addFormatterTest("%v", nv3, "<nil>")
- addFormatterTest("%+v", v3, v3s)
- addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
- addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%#v", v3, "("+v3t+")"+v3s)
- addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s)
- addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s)
- addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
- addFormatterTest("%#+v", v3, "("+v3t+")"+v3s)
- addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s)
- addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s)
- addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
-
- // Max int64.
- v4 := int64(9223372036854775807)
- nv4 := (*int64)(nil)
- pv4 := &v4
- v4Addr := fmt.Sprintf("%p", pv4)
- pv4Addr := fmt.Sprintf("%p", &pv4)
- v4t := "int64"
- v4s := "9223372036854775807"
- addFormatterTest("%v", v4, v4s)
- addFormatterTest("%v", pv4, "<*>"+v4s)
- addFormatterTest("%v", &pv4, "<**>"+v4s)
- addFormatterTest("%v", nv4, "<nil>")
- addFormatterTest("%+v", v4, v4s)
- addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s)
- addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s)
- addFormatterTest("%+v", nv4, "<nil>")
- addFormatterTest("%#v", v4, "("+v4t+")"+v4s)
- addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s)
- addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s)
- addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>")
- addFormatterTest("%#+v", v4, "("+v4t+")"+v4s)
- addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s)
- addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s)
- addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>")
-
- // Max int.
- v5 := int(2147483647)
- nv5 := (*int)(nil)
- pv5 := &v5
- v5Addr := fmt.Sprintf("%p", pv5)
- pv5Addr := fmt.Sprintf("%p", &pv5)
- v5t := "int"
- v5s := "2147483647"
- addFormatterTest("%v", v5, v5s)
- addFormatterTest("%v", pv5, "<*>"+v5s)
- addFormatterTest("%v", &pv5, "<**>"+v5s)
- addFormatterTest("%v", nv5, "<nil>")
- addFormatterTest("%+v", v5, v5s)
- addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s)
- addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s)
- addFormatterTest("%+v", nv5, "<nil>")
- addFormatterTest("%#v", v5, "("+v5t+")"+v5s)
- addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s)
- addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s)
- addFormatterTest("%#v", nv5, "(*"+v5t+")"+"<nil>")
- addFormatterTest("%#+v", v5, "("+v5t+")"+v5s)
- addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s)
- addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s)
- addFormatterTest("%#+v", nv5, "(*"+v5t+")"+"<nil>")
-}
-
-func addUintFormatterTests() {
- // Max uint8.
- v := uint8(255)
- nv := (*uint8)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "uint8"
- vs := "255"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Max uint16.
- v2 := uint16(65535)
- nv2 := (*uint16)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "uint16"
- v2s := "65535"
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%v", nv2, "<nil>")
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
-
- // Max uint32.
- v3 := uint32(4294967295)
- nv3 := (*uint32)(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "uint32"
- v3s := "4294967295"
- addFormatterTest("%v", v3, v3s)
- addFormatterTest("%v", pv3, "<*>"+v3s)
- addFormatterTest("%v", &pv3, "<**>"+v3s)
- addFormatterTest("%v", nv3, "<nil>")
- addFormatterTest("%+v", v3, v3s)
- addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
- addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%#v", v3, "("+v3t+")"+v3s)
- addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s)
- addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s)
- addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
- addFormatterTest("%#+v", v3, "("+v3t+")"+v3s)
- addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s)
- addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s)
- addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
-
- // Max uint64.
- v4 := uint64(18446744073709551615)
- nv4 := (*uint64)(nil)
- pv4 := &v4
- v4Addr := fmt.Sprintf("%p", pv4)
- pv4Addr := fmt.Sprintf("%p", &pv4)
- v4t := "uint64"
- v4s := "18446744073709551615"
- addFormatterTest("%v", v4, v4s)
- addFormatterTest("%v", pv4, "<*>"+v4s)
- addFormatterTest("%v", &pv4, "<**>"+v4s)
- addFormatterTest("%v", nv4, "<nil>")
- addFormatterTest("%+v", v4, v4s)
- addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s)
- addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s)
- addFormatterTest("%+v", nv4, "<nil>")
- addFormatterTest("%#v", v4, "("+v4t+")"+v4s)
- addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s)
- addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s)
- addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>")
- addFormatterTest("%#+v", v4, "("+v4t+")"+v4s)
- addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s)
- addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s)
- addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>")
-
- // Max uint.
- v5 := uint(4294967295)
- nv5 := (*uint)(nil)
- pv5 := &v5
- v5Addr := fmt.Sprintf("%p", pv5)
- pv5Addr := fmt.Sprintf("%p", &pv5)
- v5t := "uint"
- v5s := "4294967295"
- addFormatterTest("%v", v5, v5s)
- addFormatterTest("%v", pv5, "<*>"+v5s)
- addFormatterTest("%v", &pv5, "<**>"+v5s)
- addFormatterTest("%v", nv5, "<nil>")
- addFormatterTest("%+v", v5, v5s)
- addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s)
- addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s)
- addFormatterTest("%+v", nv5, "<nil>")
- addFormatterTest("%#v", v5, "("+v5t+")"+v5s)
- addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s)
- addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s)
- addFormatterTest("%#v", nv5, "(*"+v5t+")"+"<nil>")
- addFormatterTest("%#+v", v5, "("+v5t+")"+v5s)
- addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s)
- addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s)
- addFormatterTest("%#v", nv5, "(*"+v5t+")"+"<nil>")
-}
-
-func addBoolFormatterTests() {
- // Boolean true.
- v := bool(true)
- nv := (*bool)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "bool"
- vs := "true"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Boolean false.
- v2 := bool(false)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "bool"
- v2s := "false"
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
-}
-
-func addFloatFormatterTests() {
- // Standard float32.
- v := float32(3.1415)
- nv := (*float32)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "float32"
- vs := "3.1415"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Standard float64.
- v2 := float64(3.1415926)
- nv2 := (*float64)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "float64"
- v2s := "3.1415926"
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
-}
-
-func addComplexFormatterTests() {
- // Standard complex64.
- v := complex(float32(6), -2)
- nv := (*complex64)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "complex64"
- vs := "(6-2i)"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Standard complex128.
- v2 := complex(float64(-6), 2)
- nv2 := (*complex128)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "complex128"
- v2s := "(-6+2i)"
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
-}
-
-func addArrayFormatterTests() {
- // Array containing standard ints.
- v := [3]int{1, 2, 3}
- nv := (*[3]int)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "[3]int"
- vs := "[1 2 3]"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Array containing type with custom formatter on pointer receiver only.
- v2 := [3]pstringer{"1", "2", "3"}
- nv2 := (*[3]pstringer)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "[3]spew_test.pstringer"
- v2sp := "[stringer 1 stringer 2 stringer 3]"
- v2s := v2sp
- if spew.UnsafeDisabled {
- v2s = "[1 2 3]"
- }
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2sp)
- addFormatterTest("%v", &pv2, "<**>"+v2sp)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2sp)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2sp)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2sp)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2sp)
- addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2sp)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2sp)
- addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
-
- // Array containing interfaces.
- v3 := [3]interface{}{"one", int(2), uint(3)}
- nv3 := (*[3]interface{})(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "[3]interface {}"
- v3t2 := "string"
- v3t3 := "int"
- v3t4 := "uint"
- v3s := "[one 2 3]"
- v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3]"
- addFormatterTest("%v", v3, v3s)
- addFormatterTest("%v", pv3, "<*>"+v3s)
- addFormatterTest("%v", &pv3, "<**>"+v3s)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%+v", v3, v3s)
- addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
- addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%#v", v3, "("+v3t+")"+v3s2)
- addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2)
- addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2)
- addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
- addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2)
- addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2)
- addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2)
- addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>")
-}
-
-func addSliceFormatterTests() {
- // Slice containing standard float32 values.
- v := []float32{3.14, 6.28, 12.56}
- nv := (*[]float32)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "[]float32"
- vs := "[3.14 6.28 12.56]"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Slice containing type with custom formatter on pointer receiver only.
- v2 := []pstringer{"1", "2", "3"}
- nv2 := (*[]pstringer)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "[]spew_test.pstringer"
- v2s := "[stringer 1 stringer 2 stringer 3]"
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
-
- // Slice containing interfaces.
- v3 := []interface{}{"one", int(2), uint(3), nil}
- nv3 := (*[]interface{})(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "[]interface {}"
- v3t2 := "string"
- v3t3 := "int"
- v3t4 := "uint"
- v3t5 := "interface {}"
- v3s := "[one 2 3 <nil>]"
- v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3 (" + v3t5 +
- ")<nil>]"
- addFormatterTest("%v", v3, v3s)
- addFormatterTest("%v", pv3, "<*>"+v3s)
- addFormatterTest("%v", &pv3, "<**>"+v3s)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%+v", v3, v3s)
- addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
- addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%#v", v3, "("+v3t+")"+v3s2)
- addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2)
- addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2)
- addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
- addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2)
- addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2)
- addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2)
- addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>")
-
- // Nil slice.
- var v4 []int
- nv4 := (*[]int)(nil)
- pv4 := &v4
- v4Addr := fmt.Sprintf("%p", pv4)
- pv4Addr := fmt.Sprintf("%p", &pv4)
- v4t := "[]int"
- v4s := "<nil>"
- addFormatterTest("%v", v4, v4s)
- addFormatterTest("%v", pv4, "<*>"+v4s)
- addFormatterTest("%v", &pv4, "<**>"+v4s)
- addFormatterTest("%+v", nv4, "<nil>")
- addFormatterTest("%+v", v4, v4s)
- addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s)
- addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s)
- addFormatterTest("%+v", nv4, "<nil>")
- addFormatterTest("%#v", v4, "("+v4t+")"+v4s)
- addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s)
- addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s)
- addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>")
- addFormatterTest("%#+v", v4, "("+v4t+")"+v4s)
- addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s)
- addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s)
- addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>")
-}
-
-func addStringFormatterTests() {
- // Standard string.
- v := "test"
- nv := (*string)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "string"
- vs := "test"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-}
-
-func addInterfaceFormatterTests() {
- // Nil interface.
- var v interface{}
- nv := (*interface{})(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "interface {}"
- vs := "<nil>"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Sub-interface.
- v2 := interface{}(uint16(65535))
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "uint16"
- v2s := "65535"
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
-}
-
-func addMapFormatterTests() {
- // Map with string keys and int vals.
- v := map[string]int{"one": 1, "two": 2}
- nilMap := map[string]int(nil)
- nv := (*map[string]int)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "map[string]int"
- vs := "map[one:1 two:2]"
- vs2 := "map[two:2 one:1]"
- addFormatterTest("%v", v, vs, vs2)
- addFormatterTest("%v", pv, "<*>"+vs, "<*>"+vs2)
- addFormatterTest("%v", &pv, "<**>"+vs, "<**>"+vs2)
- addFormatterTest("%+v", nilMap, "<nil>")
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs, vs2)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs, "<*>("+vAddr+")"+vs2)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs,
- "<**>("+pvAddr+"->"+vAddr+")"+vs2)
- addFormatterTest("%+v", nilMap, "<nil>")
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs, "("+vt+")"+vs2)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs, "(*"+vt+")"+vs2)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs, "(**"+vt+")"+vs2)
- addFormatterTest("%#v", nilMap, "("+vt+")"+"<nil>")
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs, "("+vt+")"+vs2)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs,
- "(*"+vt+")("+vAddr+")"+vs2)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs,
- "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs2)
- addFormatterTest("%#+v", nilMap, "("+vt+")"+"<nil>")
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Map with custom formatter type on pointer receiver only keys and vals.
- v2 := map[pstringer]pstringer{"one": "1"}
- nv2 := (*map[pstringer]pstringer)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "map[spew_test.pstringer]spew_test.pstringer"
- v2s := "map[stringer one:stringer 1]"
- if spew.UnsafeDisabled {
- v2s = "map[one:1]"
- }
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
-
- // Map with interface keys and values.
- v3 := map[interface{}]interface{}{"one": 1}
- nv3 := (*map[interface{}]interface{})(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "map[interface {}]interface {}"
- v3t1 := "string"
- v3t2 := "int"
- v3s := "map[one:1]"
- v3s2 := "map[(" + v3t1 + ")one:(" + v3t2 + ")1]"
- addFormatterTest("%v", v3, v3s)
- addFormatterTest("%v", pv3, "<*>"+v3s)
- addFormatterTest("%v", &pv3, "<**>"+v3s)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%+v", v3, v3s)
- addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
- addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%#v", v3, "("+v3t+")"+v3s2)
- addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2)
- addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2)
- addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
- addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2)
- addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2)
- addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2)
- addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>")
-
- // Map with nil interface value
- v4 := map[string]interface{}{"nil": nil}
- nv4 := (*map[string]interface{})(nil)
- pv4 := &v4
- v4Addr := fmt.Sprintf("%p", pv4)
- pv4Addr := fmt.Sprintf("%p", &pv4)
- v4t := "map[string]interface {}"
- v4t1 := "interface {}"
- v4s := "map[nil:<nil>]"
- v4s2 := "map[nil:(" + v4t1 + ")<nil>]"
- addFormatterTest("%v", v4, v4s)
- addFormatterTest("%v", pv4, "<*>"+v4s)
- addFormatterTest("%v", &pv4, "<**>"+v4s)
- addFormatterTest("%+v", nv4, "<nil>")
- addFormatterTest("%+v", v4, v4s)
- addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s)
- addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s)
- addFormatterTest("%+v", nv4, "<nil>")
- addFormatterTest("%#v", v4, "("+v4t+")"+v4s2)
- addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s2)
- addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s2)
- addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>")
- addFormatterTest("%#+v", v4, "("+v4t+")"+v4s2)
- addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s2)
- addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s2)
- addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>")
-}
-
-func addStructFormatterTests() {
- // Struct with primitives.
- type s1 struct {
- a int8
- b uint8
- }
- v := s1{127, 255}
- nv := (*s1)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "spew_test.s1"
- vt2 := "int8"
- vt3 := "uint8"
- vs := "{127 255}"
- vs2 := "{a:127 b:255}"
- vs3 := "{a:(" + vt2 + ")127 b:(" + vt3 + ")255}"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs2)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs2)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs2)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs3)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs3)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs3)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs3)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs3)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs3)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Struct that contains another struct.
- type s2 struct {
- s1 s1
- b bool
- }
- v2 := s2{s1{127, 255}, true}
- nv2 := (*s2)(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "spew_test.s2"
- v2t2 := "spew_test.s1"
- v2t3 := "int8"
- v2t4 := "uint8"
- v2t5 := "bool"
- v2s := "{{127 255} true}"
- v2s2 := "{s1:{a:127 b:255} b:true}"
- v2s3 := "{s1:(" + v2t2 + "){a:(" + v2t3 + ")127 b:(" + v2t4 + ")255} b:(" +
- v2t5 + ")true}"
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%+v", v2, v2s2)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s2)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s2)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s3)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s3)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s3)
- addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s3)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s3)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s3)
- addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
-
- // Struct that contains custom type with Stringer pointer interface via both
- // exported and unexported fields.
- type s3 struct {
- s pstringer
- S pstringer
- }
- v3 := s3{"test", "test2"}
- nv3 := (*s3)(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "spew_test.s3"
- v3t2 := "spew_test.pstringer"
- v3s := "{stringer test stringer test2}"
- v3sp := v3s
- v3s2 := "{s:stringer test S:stringer test2}"
- v3s2p := v3s2
- v3s3 := "{s:(" + v3t2 + ")stringer test S:(" + v3t2 + ")stringer test2}"
- v3s3p := v3s3
- if spew.UnsafeDisabled {
- v3s = "{test test2}"
- v3sp = "{test stringer test2}"
- v3s2 = "{s:test S:test2}"
- v3s2p = "{s:test S:stringer test2}"
- v3s3 = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")test2}"
- v3s3p = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")stringer test2}"
- }
- addFormatterTest("%v", v3, v3s)
- addFormatterTest("%v", pv3, "<*>"+v3sp)
- addFormatterTest("%v", &pv3, "<**>"+v3sp)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%+v", v3, v3s2)
- addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s2p)
- addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s2p)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%#v", v3, "("+v3t+")"+v3s3)
- addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s3p)
- addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s3p)
- addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
- addFormatterTest("%#+v", v3, "("+v3t+")"+v3s3)
- addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s3p)
- addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s3p)
- addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>")
-
- // Struct that contains embedded struct and field to same struct.
- e := embed{"embedstr"}
- v4 := embedwrap{embed: &e, e: &e}
- nv4 := (*embedwrap)(nil)
- pv4 := &v4
- eAddr := fmt.Sprintf("%p", &e)
- v4Addr := fmt.Sprintf("%p", pv4)
- pv4Addr := fmt.Sprintf("%p", &pv4)
- v4t := "spew_test.embedwrap"
- v4t2 := "spew_test.embed"
- v4t3 := "string"
- v4s := "{<*>{embedstr} <*>{embedstr}}"
- v4s2 := "{embed:<*>(" + eAddr + "){a:embedstr} e:<*>(" + eAddr +
- "){a:embedstr}}"
- v4s3 := "{embed:(*" + v4t2 + "){a:(" + v4t3 + ")embedstr} e:(*" + v4t2 +
- "){a:(" + v4t3 + ")embedstr}}"
- v4s4 := "{embed:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 +
- ")embedstr} e:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 + ")embedstr}}"
- addFormatterTest("%v", v4, v4s)
- addFormatterTest("%v", pv4, "<*>"+v4s)
- addFormatterTest("%v", &pv4, "<**>"+v4s)
- addFormatterTest("%+v", nv4, "<nil>")
- addFormatterTest("%+v", v4, v4s2)
- addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s2)
- addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s2)
- addFormatterTest("%+v", nv4, "<nil>")
- addFormatterTest("%#v", v4, "("+v4t+")"+v4s3)
- addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s3)
- addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s3)
- addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>")
- addFormatterTest("%#+v", v4, "("+v4t+")"+v4s4)
- addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s4)
- addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s4)
- addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>")
-}
-
-func addUintptrFormatterTests() {
- // Null pointer.
- v := uintptr(0)
- nv := (*uintptr)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "uintptr"
- vs := "<nil>"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Address of real variable.
- i := 1
- v2 := uintptr(unsafe.Pointer(&i))
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "uintptr"
- v2s := fmt.Sprintf("%p", &i)
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
-}
-
-func addUnsafePointerFormatterTests() {
- // Null pointer.
- v := unsafe.Pointer(uintptr(0))
- nv := (*unsafe.Pointer)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "unsafe.Pointer"
- vs := "<nil>"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Address of real variable.
- i := 1
- v2 := unsafe.Pointer(&i)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "unsafe.Pointer"
- v2s := fmt.Sprintf("%p", &i)
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
-}
-
-func addChanFormatterTests() {
- // Nil channel.
- var v chan int
- pv := &v
- nv := (*chan int)(nil)
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "chan int"
- vs := "<nil>"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Real channel.
- v2 := make(chan int)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "chan int"
- v2s := fmt.Sprintf("%p", v2)
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
-}
-
-func addFuncFormatterTests() {
- // Function with no params and no returns.
- v := addIntFormatterTests
- nv := (*func())(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "func()"
- vs := fmt.Sprintf("%p", v)
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-
- // Function with param and no returns.
- v2 := TestFormatter
- nv2 := (*func(*testing.T))(nil)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "func(*testing.T)"
- v2s := fmt.Sprintf("%p", v2)
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s)
- addFormatterTest("%v", &pv2, "<**>"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%+v", v2, v2s)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%+v", nv2, "<nil>")
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
- addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
- addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
-
- // Function with multiple params and multiple returns.
- var v3 = func(i int, s string) (b bool, err error) {
- return true, nil
- }
- nv3 := (*func(int, string) (bool, error))(nil)
- pv3 := &v3
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "func(int, string) (bool, error)"
- v3s := fmt.Sprintf("%p", v3)
- addFormatterTest("%v", v3, v3s)
- addFormatterTest("%v", pv3, "<*>"+v3s)
- addFormatterTest("%v", &pv3, "<**>"+v3s)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%+v", v3, v3s)
- addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
- addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
- addFormatterTest("%+v", nv3, "<nil>")
- addFormatterTest("%#v", v3, "("+v3t+")"+v3s)
- addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s)
- addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s)
- addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
- addFormatterTest("%#+v", v3, "("+v3t+")"+v3s)
- addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s)
- addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s)
- addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>")
-}
-
-func addCircularFormatterTests() {
- // Struct that is circular through self referencing.
- type circular struct {
- c *circular
- }
- v := circular{nil}
- v.c = &v
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "spew_test.circular"
- vs := "{<*>{<*><shown>}}"
- vs2 := "{<*><shown>}"
- vs3 := "{c:<*>(" + vAddr + "){c:<*>(" + vAddr + ")<shown>}}"
- vs4 := "{c:<*>(" + vAddr + ")<shown>}"
- vs5 := "{c:(*" + vt + "){c:(*" + vt + ")<shown>}}"
- vs6 := "{c:(*" + vt + ")<shown>}"
- vs7 := "{c:(*" + vt + ")(" + vAddr + "){c:(*" + vt + ")(" + vAddr +
- ")<shown>}}"
- vs8 := "{c:(*" + vt + ")(" + vAddr + ")<shown>}"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs2)
- addFormatterTest("%v", &pv, "<**>"+vs2)
- addFormatterTest("%+v", v, vs3)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs4)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs4)
- addFormatterTest("%#v", v, "("+vt+")"+vs5)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs6)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs6)
- addFormatterTest("%#+v", v, "("+vt+")"+vs7)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs8)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs8)
-
- // Structs that are circular through cross referencing.
- v2 := xref1{nil}
- ts2 := xref2{&v2}
- v2.ps2 = &ts2
- pv2 := &v2
- ts2Addr := fmt.Sprintf("%p", &ts2)
- v2Addr := fmt.Sprintf("%p", pv2)
- pv2Addr := fmt.Sprintf("%p", &pv2)
- v2t := "spew_test.xref1"
- v2t2 := "spew_test.xref2"
- v2s := "{<*>{<*>{<*><shown>}}}"
- v2s2 := "{<*>{<*><shown>}}"
- v2s3 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + "){ps2:<*>(" +
- ts2Addr + ")<shown>}}}"
- v2s4 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + ")<shown>}}"
- v2s5 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + "){ps2:(*" + v2t2 +
- ")<shown>}}}"
- v2s6 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + ")<shown>}}"
- v2s7 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t +
- ")(" + v2Addr + "){ps2:(*" + v2t2 + ")(" + ts2Addr +
- ")<shown>}}}"
- v2s8 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t +
- ")(" + v2Addr + ")<shown>}}"
- addFormatterTest("%v", v2, v2s)
- addFormatterTest("%v", pv2, "<*>"+v2s2)
- addFormatterTest("%v", &pv2, "<**>"+v2s2)
- addFormatterTest("%+v", v2, v2s3)
- addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s4)
- addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s4)
- addFormatterTest("%#v", v2, "("+v2t+")"+v2s5)
- addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s6)
- addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s6)
- addFormatterTest("%#+v", v2, "("+v2t+")"+v2s7)
- addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s8)
- addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s8)
-
- // Structs that are indirectly circular.
- v3 := indirCir1{nil}
- tic2 := indirCir2{nil}
- tic3 := indirCir3{&v3}
- tic2.ps3 = &tic3
- v3.ps2 = &tic2
- pv3 := &v3
- tic2Addr := fmt.Sprintf("%p", &tic2)
- tic3Addr := fmt.Sprintf("%p", &tic3)
- v3Addr := fmt.Sprintf("%p", pv3)
- pv3Addr := fmt.Sprintf("%p", &pv3)
- v3t := "spew_test.indirCir1"
- v3t2 := "spew_test.indirCir2"
- v3t3 := "spew_test.indirCir3"
- v3s := "{<*>{<*>{<*>{<*><shown>}}}}"
- v3s2 := "{<*>{<*>{<*><shown>}}}"
- v3s3 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" +
- v3Addr + "){ps2:<*>(" + tic2Addr + ")<shown>}}}}"
- v3s4 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" +
- v3Addr + ")<shown>}}}"
- v3s5 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t +
- "){ps2:(*" + v3t2 + ")<shown>}}}}"
- v3s6 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t +
- ")<shown>}}}"
- v3s7 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" +
- tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + "){ps2:(*" + v3t2 +
- ")(" + tic2Addr + ")<shown>}}}}"
- v3s8 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" +
- tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + ")<shown>}}}"
- addFormatterTest("%v", v3, v3s)
- addFormatterTest("%v", pv3, "<*>"+v3s2)
- addFormatterTest("%v", &pv3, "<**>"+v3s2)
- addFormatterTest("%+v", v3, v3s3)
- addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s4)
- addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s4)
- addFormatterTest("%#v", v3, "("+v3t+")"+v3s5)
- addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s6)
- addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s6)
- addFormatterTest("%#+v", v3, "("+v3t+")"+v3s7)
- addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s8)
- addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s8)
-}
-
-func addPanicFormatterTests() {
- // Type that panics in its Stringer interface.
- v := panicer(127)
- nv := (*panicer)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "spew_test.panicer"
- vs := "(PANIC=test panic)127"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-}
-
-func addErrorFormatterTests() {
- // Type that has a custom Error interface.
- v := customError(127)
- nv := (*customError)(nil)
- pv := &v
- vAddr := fmt.Sprintf("%p", pv)
- pvAddr := fmt.Sprintf("%p", &pv)
- vt := "spew_test.customError"
- vs := "error: 127"
- addFormatterTest("%v", v, vs)
- addFormatterTest("%v", pv, "<*>"+vs)
- addFormatterTest("%v", &pv, "<**>"+vs)
- addFormatterTest("%v", nv, "<nil>")
- addFormatterTest("%+v", v, vs)
- addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
- addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%+v", nv, "<nil>")
- addFormatterTest("%#v", v, "("+vt+")"+vs)
- addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
- addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
- addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
- addFormatterTest("%#+v", v, "("+vt+")"+vs)
- addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
- addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
- addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
-}
-
-func addPassthroughFormatterTests() {
- // %x passthrough with uint.
- v := uint(4294967295)
- pv := &v
- vAddr := fmt.Sprintf("%x", pv)
- pvAddr := fmt.Sprintf("%x", &pv)
- vs := "ffffffff"
- addFormatterTest("%x", v, vs)
- addFormatterTest("%x", pv, vAddr)
- addFormatterTest("%x", &pv, pvAddr)
-
- // %#x passthrough with uint.
- v2 := int(2147483647)
- pv2 := &v2
- v2Addr := fmt.Sprintf("%#x", pv2)
- pv2Addr := fmt.Sprintf("%#x", &pv2)
- v2s := "0x7fffffff"
- addFormatterTest("%#x", v2, v2s)
- addFormatterTest("%#x", pv2, v2Addr)
- addFormatterTest("%#x", &pv2, pv2Addr)
-
- // %f passthrough with precision.
- addFormatterTest("%.2f", 3.1415, "3.14")
- addFormatterTest("%.3f", 3.1415, "3.142")
- addFormatterTest("%.4f", 3.1415, "3.1415")
-
- // %f passthrough with width and precision.
- addFormatterTest("%5.2f", 3.1415, " 3.14")
- addFormatterTest("%6.3f", 3.1415, " 3.142")
- addFormatterTest("%7.4f", 3.1415, " 3.1415")
-
- // %d passthrough with width.
- addFormatterTest("%3d", 127, "127")
- addFormatterTest("%4d", 127, " 127")
- addFormatterTest("%5d", 127, " 127")
-
- // %q passthrough with string.
- addFormatterTest("%q", "test", "\"test\"")
-}
-
-// TestFormatter executes all of the tests described by formatterTests.
-func TestFormatter(t *testing.T) {
- // Setup tests.
- addIntFormatterTests()
- addUintFormatterTests()
- addBoolFormatterTests()
- addFloatFormatterTests()
- addComplexFormatterTests()
- addArrayFormatterTests()
- addSliceFormatterTests()
- addStringFormatterTests()
- addInterfaceFormatterTests()
- addMapFormatterTests()
- addStructFormatterTests()
- addUintptrFormatterTests()
- addUnsafePointerFormatterTests()
- addChanFormatterTests()
- addFuncFormatterTests()
- addCircularFormatterTests()
- addPanicFormatterTests()
- addErrorFormatterTests()
- addPassthroughFormatterTests()
-
- t.Logf("Running %d tests", len(formatterTests))
- for i, test := range formatterTests {
- buf := new(bytes.Buffer)
- spew.Fprintf(buf, test.format, test.in)
- s := buf.String()
- if testFailed(s, test.wants) {
- t.Errorf("Formatter #%d format: %s got: %s %s", i, test.format, s,
- stringizeWants(test.wants))
- continue
- }
- }
-}
-
-type testStruct struct {
- x int
-}
-
-func (ts testStruct) String() string {
- return fmt.Sprintf("ts.%d", ts.x)
-}
-
-type testStructP struct {
- x int
-}
-
-func (ts *testStructP) String() string {
- return fmt.Sprintf("ts.%d", ts.x)
-}
-
-func TestPrintSortedKeys(t *testing.T) {
- cfg := spew.ConfigState{SortKeys: true}
- s := cfg.Sprint(map[int]string{1: "1", 3: "3", 2: "2"})
- expected := "map[1:1 2:2 3:3]"
- if s != expected {
- t.Errorf("Sorted keys mismatch 1:\n %v %v", s, expected)
- }
-
- s = cfg.Sprint(map[stringer]int{"1": 1, "3": 3, "2": 2})
- expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]"
- if s != expected {
- t.Errorf("Sorted keys mismatch 2:\n %v %v", s, expected)
- }
-
- s = cfg.Sprint(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2})
- expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]"
- if spew.UnsafeDisabled {
- expected = "map[1:1 2:2 3:3]"
- }
- if s != expected {
- t.Errorf("Sorted keys mismatch 3:\n %v %v", s, expected)
- }
-
- s = cfg.Sprint(map[testStruct]int{testStruct{1}: 1, testStruct{3}: 3, testStruct{2}: 2})
- expected = "map[ts.1:1 ts.2:2 ts.3:3]"
- if s != expected {
- t.Errorf("Sorted keys mismatch 4:\n %v %v", s, expected)
- }
-
- if !spew.UnsafeDisabled {
- s = cfg.Sprint(map[testStructP]int{testStructP{1}: 1, testStructP{3}: 3, testStructP{2}: 2})
- expected = "map[ts.1:1 ts.2:2 ts.3:3]"
- if s != expected {
- t.Errorf("Sorted keys mismatch 5:\n %v %v", s, expected)
- }
- }
-
- s = cfg.Sprint(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2})
- expected = "map[error: 1:1 error: 2:2 error: 3:3]"
- if s != expected {
- t.Errorf("Sorted keys mismatch 6:\n %v %v", s, expected)
- }
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internal_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internal_test.go
deleted file mode 100644
index 1069ee21c..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internal_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
-This test file is part of the spew package rather than than the spew_test
-package because it needs access to internals to properly test certain cases
-which are not possible via the public interface since they should never happen.
-*/
-
-package spew
-
-import (
- "bytes"
- "reflect"
- "testing"
-)
-
-// dummyFmtState implements a fake fmt.State to use for testing invalid
-// reflect.Value handling. This is necessary because the fmt package catches
-// invalid values before invoking the formatter on them.
-type dummyFmtState struct {
- bytes.Buffer
-}
-
-func (dfs *dummyFmtState) Flag(f int) bool {
- if f == int('+') {
- return true
- }
- return false
-}
-
-func (dfs *dummyFmtState) Precision() (int, bool) {
- return 0, false
-}
-
-func (dfs *dummyFmtState) Width() (int, bool) {
- return 0, false
-}
-
-// TestInvalidReflectValue ensures the dump and formatter code handles an
-// invalid reflect value properly. This needs access to internal state since it
-// should never happen in real code and therefore can't be tested via the public
-// API.
-func TestInvalidReflectValue(t *testing.T) {
- i := 1
-
- // Dump invalid reflect value.
- v := new(reflect.Value)
- buf := new(bytes.Buffer)
- d := dumpState{w: buf, cs: &Config}
- d.dump(*v)
- s := buf.String()
- want := "<invalid>"
- if s != want {
- t.Errorf("InvalidReflectValue #%d\n got: %s want: %s", i, s, want)
- }
- i++
-
- // Formatter invalid reflect value.
- buf2 := new(dummyFmtState)
- f := formatState{value: *v, cs: &Config, fs: buf2}
- f.format(*v)
- s = buf2.String()
- want = "<invalid>"
- if s != want {
- t.Errorf("InvalidReflectValue #%d got: %s want: %s", i, s, want)
- }
-}
-
-// SortValues makes the internal sortValues function available to the test
-// package.
-func SortValues(values []reflect.Value, cs *ConfigState) {
- sortValues(values, cs)
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go
deleted file mode 100644
index 83e070e9a..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2013-2015 Dave Collins <dave@davec.name>
-
-// Permission to use, copy, modify, and distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-// NOTE: Due to the following build constraints, this file will only be compiled
-// when the code is not running on Google App Engine and "-tags disableunsafe"
-// is not added to the go build command line.
-// +build !appengine,!disableunsafe
-
-/*
-This test file is part of the spew package rather than than the spew_test
-package because it needs access to internals to properly test certain cases
-which are not possible via the public interface since they should never happen.
-*/
-
-package spew
-
-import (
- "bytes"
- "reflect"
- "testing"
- "unsafe"
-)
-
-// changeKind uses unsafe to intentionally change the kind of a reflect.Value to
-// the maximum kind value which does not exist. This is needed to test the
-// fallback code which punts to the standard fmt library for new types that
-// might get added to the language.
-func changeKind(v *reflect.Value, readOnly bool) {
- rvf := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + offsetFlag))
- *rvf = *rvf | ((1<<flagKindWidth - 1) << flagKindShift)
- if readOnly {
- *rvf |= flagRO
- } else {
- *rvf &= ^uintptr(flagRO)
- }
-}
-
-// TestAddedReflectValue tests functionaly of the dump and formatter code which
-// falls back to the standard fmt library for new types that might get added to
-// the language.
-func TestAddedReflectValue(t *testing.T) {
- i := 1
-
- // Dump using a reflect.Value that is exported.
- v := reflect.ValueOf(int8(5))
- changeKind(&v, false)
- buf := new(bytes.Buffer)
- d := dumpState{w: buf, cs: &Config}
- d.dump(v)
- s := buf.String()
- want := "(int8) 5"
- if s != want {
- t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want)
- }
- i++
-
- // Dump using a reflect.Value that is not exported.
- changeKind(&v, true)
- buf.Reset()
- d.dump(v)
- s = buf.String()
- want = "(int8) <int8 Value>"
- if s != want {
- t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want)
- }
- i++
-
- // Formatter using a reflect.Value that is exported.
- changeKind(&v, false)
- buf2 := new(dummyFmtState)
- f := formatState{value: v, cs: &Config, fs: buf2}
- f.format(v)
- s = buf2.String()
- want = "5"
- if s != want {
- t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want)
- }
- i++
-
- // Formatter using a reflect.Value that is not exported.
- changeKind(&v, true)
- buf2.Reset()
- f = formatState{value: v, cs: &Config, fs: buf2}
- f.format(v)
- s = buf2.String()
- want = "<int8 Value>"
- if s != want {
- t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want)
- }
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew.go
deleted file mode 100644
index d8233f542..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew.go
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package spew
-
-import (
- "fmt"
- "io"
-)
-
-// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
-// passed with a default Formatter interface returned by NewFormatter. It
-// returns the formatted string as a value that satisfies error. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b))
-func Errorf(format string, a ...interface{}) (err error) {
- return fmt.Errorf(format, convertArgs(a)...)
-}
-
-// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
-// passed with a default Formatter interface returned by NewFormatter. It
-// returns the number of bytes written and any write error encountered. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b))
-func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
- return fmt.Fprint(w, convertArgs(a)...)
-}
-
-// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
-// passed with a default Formatter interface returned by NewFormatter. It
-// returns the number of bytes written and any write error encountered. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b))
-func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
- return fmt.Fprintf(w, format, convertArgs(a)...)
-}
-
-// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
-// passed with a default Formatter interface returned by NewFormatter. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
-func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
- return fmt.Fprintln(w, convertArgs(a)...)
-}
-
-// Print is a wrapper for fmt.Print that treats each argument as if it were
-// passed with a default Formatter interface returned by NewFormatter. It
-// returns the number of bytes written and any write error encountered. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b))
-func Print(a ...interface{}) (n int, err error) {
- return fmt.Print(convertArgs(a)...)
-}
-
-// Printf is a wrapper for fmt.Printf that treats each argument as if it were
-// passed with a default Formatter interface returned by NewFormatter. It
-// returns the number of bytes written and any write error encountered. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b))
-func Printf(format string, a ...interface{}) (n int, err error) {
- return fmt.Printf(format, convertArgs(a)...)
-}
-
-// Println is a wrapper for fmt.Println that treats each argument as if it were
-// passed with a default Formatter interface returned by NewFormatter. It
-// returns the number of bytes written and any write error encountered. See
-// NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b))
-func Println(a ...interface{}) (n int, err error) {
- return fmt.Println(convertArgs(a)...)
-}
-
-// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
-// passed with a default Formatter interface returned by NewFormatter. It
-// returns the resulting string. See NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
-func Sprint(a ...interface{}) string {
- return fmt.Sprint(convertArgs(a)...)
-}
-
-// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
-// passed with a default Formatter interface returned by NewFormatter. It
-// returns the resulting string. See NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
-func Sprintf(format string, a ...interface{}) string {
- return fmt.Sprintf(format, convertArgs(a)...)
-}
-
-// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
-// were passed with a default Formatter interface returned by NewFormatter. It
-// returns the resulting string. See NewFormatter for formatting details.
-//
-// This function is shorthand for the following syntax:
-//
-// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
-func Sprintln(a ...interface{}) string {
- return fmt.Sprintln(convertArgs(a)...)
-}
-
-// convertArgs accepts a slice of arguments and returns a slice of the same
-// length with each argument converted to a default spew Formatter interface.
-func convertArgs(args []interface{}) (formatters []interface{}) {
- formatters = make([]interface{}, len(args))
- for index, arg := range args {
- formatters[index] = NewFormatter(arg)
- }
- return formatters
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew_test.go
deleted file mode 100644
index dbbc08567..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew_test.go
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (c) 2013 Dave Collins <dave@davec.name>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package spew_test
-
-import (
- "bytes"
- "fmt"
- "io/ioutil"
- "os"
- "testing"
-
- "github.com/davecgh/go-spew/spew"
-)
-
-// spewFunc is used to identify which public function of the spew package or
-// ConfigState a test applies to.
-type spewFunc int
-
-const (
- fCSFdump spewFunc = iota
- fCSFprint
- fCSFprintf
- fCSFprintln
- fCSPrint
- fCSPrintln
- fCSSdump
- fCSSprint
- fCSSprintf
- fCSSprintln
- fCSErrorf
- fCSNewFormatter
- fErrorf
- fFprint
- fFprintln
- fPrint
- fPrintln
- fSdump
- fSprint
- fSprintf
- fSprintln
-)
-
-// Map of spewFunc values to names for pretty printing.
-var spewFuncStrings = map[spewFunc]string{
- fCSFdump: "ConfigState.Fdump",
- fCSFprint: "ConfigState.Fprint",
- fCSFprintf: "ConfigState.Fprintf",
- fCSFprintln: "ConfigState.Fprintln",
- fCSSdump: "ConfigState.Sdump",
- fCSPrint: "ConfigState.Print",
- fCSPrintln: "ConfigState.Println",
- fCSSprint: "ConfigState.Sprint",
- fCSSprintf: "ConfigState.Sprintf",
- fCSSprintln: "ConfigState.Sprintln",
- fCSErrorf: "ConfigState.Errorf",
- fCSNewFormatter: "ConfigState.NewFormatter",
- fErrorf: "spew.Errorf",
- fFprint: "spew.Fprint",
- fFprintln: "spew.Fprintln",
- fPrint: "spew.Print",
- fPrintln: "spew.Println",
- fSdump: "spew.Sdump",
- fSprint: "spew.Sprint",
- fSprintf: "spew.Sprintf",
- fSprintln: "spew.Sprintln",
-}
-
-func (f spewFunc) String() string {
- if s, ok := spewFuncStrings[f]; ok {
- return s
- }
- return fmt.Sprintf("Unknown spewFunc (%d)", int(f))
-}
-
-// spewTest is used to describe a test to be performed against the public
-// functions of the spew package or ConfigState.
-type spewTest struct {
- cs *spew.ConfigState
- f spewFunc
- format string
- in interface{}
- want string
-}
-
-// spewTests houses the tests to be performed against the public functions of
-// the spew package and ConfigState.
-//
-// These tests are only intended to ensure the public functions are exercised
-// and are intentionally not exhaustive of types. The exhaustive type
-// tests are handled in the dump and format tests.
-var spewTests []spewTest
-
-// redirStdout is a helper function to return the standard output from f as a
-// byte slice.
-func redirStdout(f func()) ([]byte, error) {
- tempFile, err := ioutil.TempFile("", "ss-test")
- if err != nil {
- return nil, err
- }
- fileName := tempFile.Name()
- defer os.Remove(fileName) // Ignore error
-
- origStdout := os.Stdout
- os.Stdout = tempFile
- f()
- os.Stdout = origStdout
- tempFile.Close()
-
- return ioutil.ReadFile(fileName)
-}
-
-func initSpewTests() {
- // Config states with various settings.
- scsDefault := spew.NewDefaultConfig()
- scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true}
- scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true}
- scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1}
- scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true}
-
- // Variables for tests on types which implement Stringer interface with and
- // without a pointer receiver.
- ts := stringer("test")
- tps := pstringer("test")
-
- // depthTester is used to test max depth handling for structs, array, slices
- // and maps.
- type depthTester struct {
- ic indirCir1
- arr [1]string
- slice []string
- m map[string]int
- }
- dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"},
- map[string]int{"one": 1}}
-
- // Variable for tests on types which implement error interface.
- te := customError(10)
-
- spewTests = []spewTest{
- {scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"},
- {scsDefault, fCSFprint, "", int16(32767), "32767"},
- {scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"},
- {scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"},
- {scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"},
- {scsDefault, fCSPrintln, "", uint8(255), "255\n"},
- {scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"},
- {scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"},
- {scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"},
- {scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"},
- {scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"},
- {scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"},
- {scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"},
- {scsDefault, fFprint, "", float32(3.14), "3.14"},
- {scsDefault, fFprintln, "", float64(6.28), "6.28\n"},
- {scsDefault, fPrint, "", true, "true"},
- {scsDefault, fPrintln, "", false, "false\n"},
- {scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"},
- {scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"},
- {scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"},
- {scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"},
- {scsNoMethods, fCSFprint, "", ts, "test"},
- {scsNoMethods, fCSFprint, "", &ts, "<*>test"},
- {scsNoMethods, fCSFprint, "", tps, "test"},
- {scsNoMethods, fCSFprint, "", &tps, "<*>test"},
- {scsNoPmethods, fCSFprint, "", ts, "stringer test"},
- {scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"},
- {scsNoPmethods, fCSFprint, "", tps, "test"},
- {scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"},
- {scsMaxDepth, fCSFprint, "", dt, "{{<max>} [<max>] [<max>] map[<max>]}"},
- {scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" +
- " ic: (spew_test.indirCir1) {\n <max depth reached>\n },\n" +
- " arr: ([1]string) (len=1 cap=1) {\n <max depth reached>\n },\n" +
- " slice: ([]string) (len=1 cap=1) {\n <max depth reached>\n },\n" +
- " m: (map[string]int) (len=1) {\n <max depth reached>\n }\n}\n"},
- {scsContinue, fCSFprint, "", ts, "(stringer test) test"},
- {scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " +
- "(len=4) (stringer test) \"test\"\n"},
- {scsContinue, fCSFprint, "", te, "(error: 10) 10"},
- {scsContinue, fCSFdump, "", te, "(spew_test.customError) " +
- "(error: 10) 10\n"},
- }
-}
-
-// TestSpew executes all of the tests described by spewTests.
-func TestSpew(t *testing.T) {
- initSpewTests()
-
- t.Logf("Running %d tests", len(spewTests))
- for i, test := range spewTests {
- buf := new(bytes.Buffer)
- switch test.f {
- case fCSFdump:
- test.cs.Fdump(buf, test.in)
-
- case fCSFprint:
- test.cs.Fprint(buf, test.in)
-
- case fCSFprintf:
- test.cs.Fprintf(buf, test.format, test.in)
-
- case fCSFprintln:
- test.cs.Fprintln(buf, test.in)
-
- case fCSPrint:
- b, err := redirStdout(func() { test.cs.Print(test.in) })
- if err != nil {
- t.Errorf("%v #%d %v", test.f, i, err)
- continue
- }
- buf.Write(b)
-
- case fCSPrintln:
- b, err := redirStdout(func() { test.cs.Println(test.in) })
- if err != nil {
- t.Errorf("%v #%d %v", test.f, i, err)
- continue
- }
- buf.Write(b)
-
- case fCSSdump:
- str := test.cs.Sdump(test.in)
- buf.WriteString(str)
-
- case fCSSprint:
- str := test.cs.Sprint(test.in)
- buf.WriteString(str)
-
- case fCSSprintf:
- str := test.cs.Sprintf(test.format, test.in)
- buf.WriteString(str)
-
- case fCSSprintln:
- str := test.cs.Sprintln(test.in)
- buf.WriteString(str)
-
- case fCSErrorf:
- err := test.cs.Errorf(test.format, test.in)
- buf.WriteString(err.Error())
-
- case fCSNewFormatter:
- fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in))
-
- case fErrorf:
- err := spew.Errorf(test.format, test.in)
- buf.WriteString(err.Error())
-
- case fFprint:
- spew.Fprint(buf, test.in)
-
- case fFprintln:
- spew.Fprintln(buf, test.in)
-
- case fPrint:
- b, err := redirStdout(func() { spew.Print(test.in) })
- if err != nil {
- t.Errorf("%v #%d %v", test.f, i, err)
- continue
- }
- buf.Write(b)
-
- case fPrintln:
- b, err := redirStdout(func() { spew.Println(test.in) })
- if err != nil {
- t.Errorf("%v #%d %v", test.f, i, err)
- continue
- }
- buf.Write(b)
-
- case fSdump:
- str := spew.Sdump(test.in)
- buf.WriteString(str)
-
- case fSprint:
- str := spew.Sprint(test.in)
- buf.WriteString(str)
-
- case fSprintf:
- str := spew.Sprintf(test.format, test.in)
- buf.WriteString(str)
-
- case fSprintln:
- str := spew.Sprintln(test.in)
- buf.WriteString(str)
-
- default:
- t.Errorf("%v #%d unrecognized function", test.f, i)
- continue
- }
- s := buf.String()
- if test.want != s {
- t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want)
- continue
- }
- }
-}
diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go
deleted file mode 100644
index 5c87dd456..000000000
--- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2013 Dave Collins <dave@davec.name>
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-// NOTE: Due to the following build constraints, this file will only be compiled
-// when both cgo is supported and "-tags testcgo" is added to the go test
-// command line. This code should really only be in the dumpcgo_test.go file,
-// but unfortunately Go will not allow cgo in test files, so this is a
-// workaround to allow cgo types to be tested. This configuration is used
-// because spew itself does not require cgo to run even though it does handle
-// certain cgo types specially. Rather than forcing all clients to require cgo
-// and an external C compiler just to run the tests, this scheme makes them
-// optional.
-// +build cgo,testcgo
-
-package testdata
-
-/*
-#include <stdint.h>
-typedef unsigned char custom_uchar_t;
-
-char *ncp = 0;
-char *cp = "test";
-char ca[6] = {'t', 'e', 's', 't', '2', '\0'};
-unsigned char uca[6] = {'t', 'e', 's', 't', '3', '\0'};
-signed char sca[6] = {'t', 'e', 's', 't', '4', '\0'};
-uint8_t ui8ta[6] = {'t', 'e', 's', 't', '5', '\0'};
-custom_uchar_t tuca[6] = {'t', 'e', 's', 't', '6', '\0'};
-*/
-import "C"
-
-// GetCgoNullCharPointer returns a null char pointer via cgo. This is only
-// used for tests.
-func GetCgoNullCharPointer() interface{} {
- return C.ncp
-}
-
-// GetCgoCharPointer returns a char pointer via cgo. This is only used for
-// tests.
-func GetCgoCharPointer() interface{} {
- return C.cp
-}
-
-// GetCgoCharArray returns a char array via cgo and the array's len and cap.
-// This is only used for tests.
-func GetCgoCharArray() (interface{}, int, int) {
- return C.ca, len(C.ca), cap(C.ca)
-}
-
-// GetCgoUnsignedCharArray returns an unsigned char array via cgo and the
-// array's len and cap. This is only used for tests.
-func GetCgoUnsignedCharArray() (interface{}, int, int) {
- return C.uca, len(C.uca), cap(C.uca)
-}
-
-// GetCgoSignedCharArray returns a signed char array via cgo and the array's len
-// and cap. This is only used for tests.
-func GetCgoSignedCharArray() (interface{}, int, int) {
- return C.sca, len(C.sca), cap(C.sca)
-}
-
-// GetCgoUint8tArray returns a uint8_t array via cgo and the array's len and
-// cap. This is only used for tests.
-func GetCgoUint8tArray() (interface{}, int, int) {
- return C.ui8ta, len(C.ui8ta), cap(C.ui8ta)
-}
-
-// GetCgoTypdefedUnsignedCharArray returns a typedefed unsigned char array via
-// cgo and the array's len and cap. This is only used for tests.
-func GetCgoTypdefedUnsignedCharArray() (interface{}, int, int) {
- return C.tuca, len(C.tuca), cap(C.tuca)
-}
diff --git a/Godeps/_workspace/src/github.com/go-gorp/gorp/README.md b/Godeps/_workspace/src/github.com/go-gorp/gorp/README.md
index 3f0652bc7..8b9277805 100644
--- a/Godeps/_workspace/src/github.com/go-gorp/gorp/README.md
+++ b/Godeps/_workspace/src/github.com/go-gorp/gorp/README.md
@@ -502,7 +502,10 @@ func (i *Invoice) PreUpdate(s gorp.SqlExecutor) error {
//
func (p *Person) PreDelete(s gorp.SqlExecutor) error {
query := "delete from invoice_test where PersonId=?"
- err := s.Exec(query, p.Id); if err != nil {
+
+ _, err := s.Exec(query, p.Id)
+
+ if err != nil {
return err
}
return nil
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/.gitignore b/Godeps/_workspace/src/github.com/go-ldap/ldap/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/.gitignore
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/.travis.yml b/Godeps/_workspace/src/github.com/go-ldap/ldap/.travis.yml
new file mode 100644
index 000000000..a7a38951b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/.travis.yml
@@ -0,0 +1,15 @@
+language: go
+go:
+ - 1.2
+ - 1.3
+ - 1.4
+ - 1.5
+ - tip
+go_import_path: gopkg.in/ldap.v2
+install:
+ - go get gopkg.in/asn1-ber.v1
+ - go get gopkg.in/ldap.v2
+ - go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover
+ - go build -v ./...
+script:
+ - go test -v -cover ./...
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/LICENSE b/Godeps/_workspace/src/github.com/go-ldap/ldap/LICENSE
new file mode 100644
index 000000000..744875676
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/README.md b/Godeps/_workspace/src/github.com/go-ldap/ldap/README.md
new file mode 100644
index 000000000..68121c3e2
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/README.md
@@ -0,0 +1,55 @@
+[![GoDoc](https://godoc.org/gopkg.in/ldap.v1?status.svg)](https://godoc.org/gopkg.in/ldap.v1)
+[![Build Status](https://travis-ci.org/go-ldap/ldap.svg)](https://travis-ci.org/go-ldap/ldap)
+
+# Basic LDAP v3 functionality for the GO programming language.
+
+## Install
+
+For the latest version use:
+
+ go get gopkg.in/ldap.v2
+
+Import the latest version with:
+
+ import "gopkg.in/ldap.v2"
+
+
+## Required Libraries:
+
+ - gopkg.in/asn1-ber.v1
+
+## Working:
+
+ - Connecting to LDAP server
+ - Binding to LDAP server
+ - Searching for entries
+ - Compiling string filters to LDAP filters
+ - Paging Search Results
+ - Modify Requests / Responses
+ - Add Requests / Responses
+ - Delete Requests / Responses
+ - Better Unicode support
+
+## Examples:
+
+ - search
+ - modify
+
+## Tests Implemented:
+
+ - Filter Compile / Decompile
+
+## TODO:
+
+ - [x] Add Requests / Responses
+ - [x] Delete Requests / Responses
+ - [x] Modify DN Requests / Responses
+ - [ ] Compare Requests / Responses
+ - [ ] Implement Tests / Benchmarks
+
+
+
+---
+The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
+The design is licensed under the Creative Commons 3.0 Attributions license.
+Read this article for more details: http://blog.golang.org/gopher
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/add.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/add.go
new file mode 100644
index 000000000..643ce5ffe
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/add.go
@@ -0,0 +1,104 @@
+//
+// https://tools.ietf.org/html/rfc4511
+//
+// AddRequest ::= [APPLICATION 8] SEQUENCE {
+// entry LDAPDN,
+// attributes AttributeList }
+//
+// AttributeList ::= SEQUENCE OF attribute Attribute
+
+package ldap
+
+import (
+ "errors"
+ "log"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+type Attribute struct {
+ attrType string
+ attrVals []string
+}
+
+func (a *Attribute) encode() *ber.Packet {
+ seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute")
+ seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.attrType, "Type"))
+ set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
+ for _, value := range a.attrVals {
+ set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
+ }
+ seq.AppendChild(set)
+ return seq
+}
+
+type AddRequest struct {
+ dn string
+ attributes []Attribute
+}
+
+func (a AddRequest) encode() *ber.Packet {
+ request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationAddRequest, nil, "Add Request")
+ request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.dn, "DN"))
+ attributes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
+ for _, attribute := range a.attributes {
+ attributes.AppendChild(attribute.encode())
+ }
+ request.AppendChild(attributes)
+ return request
+}
+
+func (a *AddRequest) Attribute(attrType string, attrVals []string) {
+ a.attributes = append(a.attributes, Attribute{attrType: attrType, attrVals: attrVals})
+}
+
+func NewAddRequest(dn string) *AddRequest {
+ return &AddRequest{
+ dn: dn,
+ }
+
+}
+
+func (l *Conn) Add(addRequest *AddRequest) error {
+ messageID := l.nextMessageID()
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(addRequest.encode())
+
+ l.Debug.PrintPacket(packet)
+
+ channel, err := l.sendMessage(packet)
+ if err != nil {
+ return err
+ }
+ if channel == nil {
+ return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
+ }
+ defer l.finishMessage(messageID)
+
+ l.Debug.Printf("%d: waiting for response", messageID)
+ packet = <-channel
+ l.Debug.Printf("%d: got response %p", messageID, packet)
+ if packet == nil {
+ return NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
+ }
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ return err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ if packet.Children[1].Tag == ApplicationAddResponse {
+ resultCode, resultDescription := getLDAPResultCode(packet)
+ if resultCode != 0 {
+ return NewError(resultCode, errors.New(resultDescription))
+ }
+ } else {
+ log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
+ }
+
+ l.Debug.Printf("%d: returning", messageID)
+ return nil
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/bind.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/bind.go
new file mode 100644
index 000000000..4ad4b896c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/bind.go
@@ -0,0 +1,135 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ldap
+
+import (
+ "errors"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+type SimpleBindRequest struct {
+ Username string
+ Password string
+ Controls []Control
+}
+
+type SimpleBindResult struct {
+ Controls []Control
+}
+
+func NewSimpleBindRequest(username string, password string, controls []Control) *SimpleBindRequest {
+ return &SimpleBindRequest{
+ Username: username,
+ Password: password,
+ Controls: controls,
+ }
+}
+
+func (bindRequest *SimpleBindRequest) encode() *ber.Packet {
+ request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
+ request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
+ request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, bindRequest.Username, "User Name"))
+ request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, bindRequest.Password, "Password"))
+
+ request.AppendChild(encodeControls(bindRequest.Controls))
+
+ return request
+}
+
+func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
+ messageID := l.nextMessageID()
+
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ encodedBindRequest := simpleBindRequest.encode()
+ packet.AppendChild(encodedBindRequest)
+
+ if l.Debug {
+ ber.PrintPacket(packet)
+ }
+
+ channel, err := l.sendMessage(packet)
+ if err != nil {
+ return nil, err
+ }
+ if channel == nil {
+ return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
+ }
+ defer l.finishMessage(messageID)
+
+ packet = <-channel
+ if packet == nil {
+ return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve response"))
+ }
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ return nil, err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ result := &SimpleBindResult{
+ Controls: make([]Control, 0),
+ }
+
+ if len(packet.Children) == 3 {
+ for _, child := range packet.Children[2].Children {
+ result.Controls = append(result.Controls, DecodeControl(child))
+ }
+ }
+
+ resultCode, resultDescription := getLDAPResultCode(packet)
+ if resultCode != 0 {
+ return result, NewError(resultCode, errors.New(resultDescription))
+ }
+
+ return result, nil
+}
+
+func (l *Conn) Bind(username, password string) error {
+ messageID := l.nextMessageID()
+
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ bindRequest := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
+ bindRequest.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
+ bindRequest.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, username, "User Name"))
+ bindRequest.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, password, "Password"))
+ packet.AppendChild(bindRequest)
+
+ if l.Debug {
+ ber.PrintPacket(packet)
+ }
+
+ channel, err := l.sendMessage(packet)
+ if err != nil {
+ return err
+ }
+ if channel == nil {
+ return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
+ }
+ defer l.finishMessage(messageID)
+
+ packet = <-channel
+ if packet == nil {
+ return NewError(ErrorNetwork, errors.New("ldap: could not retrieve response"))
+ }
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ return err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ resultCode, resultDescription := getLDAPResultCode(packet)
+ if resultCode != 0 {
+ return NewError(resultCode, errors.New(resultDescription))
+ }
+
+ return nil
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/client.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/client.go
new file mode 100644
index 000000000..d3401f9e6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/client.go
@@ -0,0 +1,23 @@
+package ldap
+
+import "crypto/tls"
+
+// Client knows how to interact with an LDAP server
+type Client interface {
+ Start()
+ StartTLS(config *tls.Config) error
+ Close()
+
+ Bind(username, password string) error
+ SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error)
+
+ Add(addRequest *AddRequest) error
+ Del(delRequest *DelRequest) error
+ Modify(modifyRequest *ModifyRequest) error
+
+ Compare(dn, attribute, value string) (bool, error)
+ PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error)
+
+ Search(searchRequest *SearchRequest) (*SearchResult, error)
+ SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error)
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/compare.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/compare.go
new file mode 100644
index 000000000..802e9cc93
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/compare.go
@@ -0,0 +1,85 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// File contains Compare functionality
+//
+// https://tools.ietf.org/html/rfc4511
+//
+// CompareRequest ::= [APPLICATION 14] SEQUENCE {
+// entry LDAPDN,
+// ava AttributeValueAssertion }
+//
+// AttributeValueAssertion ::= SEQUENCE {
+// attributeDesc AttributeDescription,
+// assertionValue AssertionValue }
+//
+// AttributeDescription ::= LDAPString
+// -- Constrained to <attributedescription>
+// -- [RFC4512]
+//
+// AttributeValue ::= OCTET STRING
+//
+
+package ldap
+
+import (
+ "errors"
+ "fmt"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+// Compare checks to see if the attribute of the dn matches value. Returns true if it does otherwise
+// false with any error that occurs if any.
+func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
+ messageID := l.nextMessageID()
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+
+ request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationCompareRequest, nil, "Compare Request")
+ request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, dn, "DN"))
+
+ ava := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "AttributeValueAssertion")
+ ava.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "AttributeDesc"))
+ ava.AppendChild(ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagOctetString, value, "AssertionValue"))
+ request.AppendChild(ava)
+ packet.AppendChild(request)
+
+ l.Debug.PrintPacket(packet)
+
+ channel, err := l.sendMessage(packet)
+ if err != nil {
+ return false, err
+ }
+ if channel == nil {
+ return false, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
+ }
+ defer l.finishMessage(messageID)
+
+ l.Debug.Printf("%d: waiting for response", messageID)
+ packet = <-channel
+ l.Debug.Printf("%d: got response %p", messageID, packet)
+ if packet == nil {
+ return false, NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
+ }
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ return false, err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ if packet.Children[1].Tag == ApplicationCompareResponse {
+ resultCode, resultDescription := getLDAPResultCode(packet)
+ if resultCode == LDAPResultCompareTrue {
+ return true, nil
+ } else if resultCode == LDAPResultCompareFalse {
+ return false, nil
+ } else {
+ return false, NewError(resultCode, errors.New(resultDescription))
+ }
+ }
+ return false, fmt.Errorf("Unexpected Response: %d", packet.Children[1].Tag)
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/conn.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/conn.go
new file mode 100644
index 000000000..2f16443f6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/conn.go
@@ -0,0 +1,369 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ldap
+
+import (
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "log"
+ "net"
+ "sync"
+ "time"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+const (
+ MessageQuit = 0
+ MessageRequest = 1
+ MessageResponse = 2
+ MessageFinish = 3
+)
+
+type messagePacket struct {
+ Op int
+ MessageID int64
+ Packet *ber.Packet
+ Channel chan *ber.Packet
+}
+
+type sendMessageFlags uint
+
+const (
+ startTLS sendMessageFlags = 1 << iota
+)
+
+// Conn represents an LDAP Connection
+type Conn struct {
+ conn net.Conn
+ isTLS bool
+ isClosing bool
+ isStartingTLS bool
+ Debug debugging
+ chanConfirm chan bool
+ chanResults map[int64]chan *ber.Packet
+ chanMessage chan *messagePacket
+ chanMessageID chan int64
+ wgSender sync.WaitGroup
+ wgClose sync.WaitGroup
+ once sync.Once
+ outstandingRequests uint
+ messageMutex sync.Mutex
+}
+
+var _ Client = &Conn{}
+
+// DefaultTimeout is a package-level variable that sets the timeout value
+// used for the Dial and DialTLS methods.
+//
+// WARNING: since this is a package-level variable, setting this value from
+// multiple places will probably result in undesired behaviour.
+var DefaultTimeout = 60 * time.Second
+
+// Dial connects to the given address on the given network using net.Dial
+// and then returns a new Conn for the connection.
+func Dial(network, addr string) (*Conn, error) {
+ c, err := net.DialTimeout(network, addr, DefaultTimeout)
+ if err != nil {
+ return nil, NewError(ErrorNetwork, err)
+ }
+ conn := NewConn(c, false)
+ conn.Start()
+ return conn, nil
+}
+
+// DialTLS connects to the given address on the given network using tls.Dial
+// and then returns a new Conn for the connection.
+func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
+ dc, err := net.DialTimeout(network, addr, DefaultTimeout)
+ if err != nil {
+ return nil, NewError(ErrorNetwork, err)
+ }
+ c := tls.Client(dc, config)
+ err = c.Handshake()
+ if err != nil {
+ // Handshake error, close the established connection before we return an error
+ dc.Close()
+ return nil, NewError(ErrorNetwork, err)
+ }
+ conn := NewConn(c, true)
+ conn.Start()
+ return conn, nil
+}
+
+// NewConn returns a new Conn using conn for network I/O.
+func NewConn(conn net.Conn, isTLS bool) *Conn {
+ return &Conn{
+ conn: conn,
+ chanConfirm: make(chan bool),
+ chanMessageID: make(chan int64),
+ chanMessage: make(chan *messagePacket, 10),
+ chanResults: map[int64]chan *ber.Packet{},
+ isTLS: isTLS,
+ }
+}
+
+func (l *Conn) Start() {
+ go l.reader()
+ go l.processMessages()
+ l.wgClose.Add(1)
+}
+
+// Close closes the connection.
+func (l *Conn) Close() {
+ l.once.Do(func() {
+ l.isClosing = true
+ l.wgSender.Wait()
+
+ l.Debug.Printf("Sending quit message and waiting for confirmation")
+ l.chanMessage <- &messagePacket{Op: MessageQuit}
+ <-l.chanConfirm
+ close(l.chanMessage)
+
+ l.Debug.Printf("Closing network connection")
+ if err := l.conn.Close(); err != nil {
+ log.Print(err)
+ }
+
+ l.wgClose.Done()
+ })
+ l.wgClose.Wait()
+}
+
+// Returns the next available messageID
+func (l *Conn) nextMessageID() int64 {
+ if l.chanMessageID != nil {
+ if messageID, ok := <-l.chanMessageID; ok {
+ return messageID
+ }
+ }
+ return 0
+}
+
+// StartTLS sends the command to start a TLS session and then creates a new TLS Client
+func (l *Conn) StartTLS(config *tls.Config) error {
+ messageID := l.nextMessageID()
+
+ if l.isTLS {
+ return NewError(ErrorNetwork, errors.New("ldap: already encrypted"))
+ }
+
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationExtendedRequest, nil, "Start TLS")
+ request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, "1.3.6.1.4.1.1466.20037", "TLS Extended Command"))
+ packet.AppendChild(request)
+ l.Debug.PrintPacket(packet)
+
+ channel, err := l.sendMessageWithFlags(packet, startTLS)
+ if err != nil {
+ return err
+ }
+ if channel == nil {
+ return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
+ }
+
+ l.Debug.Printf("%d: waiting for response", messageID)
+ packet = <-channel
+ l.Debug.Printf("%d: got response %p", messageID, packet)
+ l.finishMessage(messageID)
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ l.Close()
+ return err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ if resultCode, message := getLDAPResultCode(packet); resultCode == LDAPResultSuccess {
+ conn := tls.Client(l.conn, config)
+
+ if err := conn.Handshake(); err != nil {
+ l.Close()
+ return NewError(ErrorNetwork, fmt.Errorf("TLS handshake failed (%v)", err))
+ }
+
+ l.isTLS = true
+ l.conn = conn
+ } else {
+ return NewError(resultCode, fmt.Errorf("ldap: cannot StartTLS (%s)", message))
+ }
+ go l.reader()
+
+ return nil
+}
+
+func (l *Conn) sendMessage(packet *ber.Packet) (chan *ber.Packet, error) {
+ return l.sendMessageWithFlags(packet, 0)
+}
+
+func (l *Conn) sendMessageWithFlags(packet *ber.Packet, flags sendMessageFlags) (chan *ber.Packet, error) {
+ if l.isClosing {
+ return nil, NewError(ErrorNetwork, errors.New("ldap: connection closed"))
+ }
+ l.messageMutex.Lock()
+ l.Debug.Printf("flags&startTLS = %d", flags&startTLS)
+ if l.isStartingTLS {
+ l.messageMutex.Unlock()
+ return nil, NewError(ErrorNetwork, errors.New("ldap: connection is in startls phase."))
+ }
+ if flags&startTLS != 0 {
+ if l.outstandingRequests != 0 {
+ l.messageMutex.Unlock()
+ return nil, NewError(ErrorNetwork, errors.New("ldap: cannot StartTLS with outstanding requests"))
+ } else {
+ l.isStartingTLS = true
+ }
+ }
+ l.outstandingRequests++
+
+ l.messageMutex.Unlock()
+
+ out := make(chan *ber.Packet)
+ message := &messagePacket{
+ Op: MessageRequest,
+ MessageID: packet.Children[0].Value.(int64),
+ Packet: packet,
+ Channel: out,
+ }
+ l.sendProcessMessage(message)
+ return out, nil
+}
+
+func (l *Conn) finishMessage(messageID int64) {
+ if l.isClosing {
+ return
+ }
+
+ l.messageMutex.Lock()
+ l.outstandingRequests--
+ if l.isStartingTLS {
+ l.isStartingTLS = false
+ }
+ l.messageMutex.Unlock()
+
+ message := &messagePacket{
+ Op: MessageFinish,
+ MessageID: messageID,
+ }
+ l.sendProcessMessage(message)
+}
+
+func (l *Conn) sendProcessMessage(message *messagePacket) bool {
+ if l.isClosing {
+ return false
+ }
+ l.wgSender.Add(1)
+ l.chanMessage <- message
+ l.wgSender.Done()
+ return true
+}
+
+func (l *Conn) processMessages() {
+ defer func() {
+ if err := recover(); err != nil {
+ log.Printf("ldap: recovered panic in processMessages: %v", err)
+ }
+ for messageID, channel := range l.chanResults {
+ l.Debug.Printf("Closing channel for MessageID %d", messageID)
+ close(channel)
+ delete(l.chanResults, messageID)
+ }
+ close(l.chanMessageID)
+ l.chanConfirm <- true
+ close(l.chanConfirm)
+ }()
+
+ var messageID int64 = 1
+ for {
+ select {
+ case l.chanMessageID <- messageID:
+ messageID++
+ case messagePacket, ok := <-l.chanMessage:
+ if !ok {
+ l.Debug.Printf("Shutting down - message channel is closed")
+ return
+ }
+ switch messagePacket.Op {
+ case MessageQuit:
+ l.Debug.Printf("Shutting down - quit message received")
+ return
+ case MessageRequest:
+ // Add to message list and write to network
+ l.Debug.Printf("Sending message %d", messagePacket.MessageID)
+ l.chanResults[messagePacket.MessageID] = messagePacket.Channel
+ // go routine
+ buf := messagePacket.Packet.Bytes()
+
+ _, err := l.conn.Write(buf)
+ if err != nil {
+ l.Debug.Printf("Error Sending Message: %s", err.Error())
+ break
+ }
+ case MessageResponse:
+ l.Debug.Printf("Receiving message %d", messagePacket.MessageID)
+ if chanResult, ok := l.chanResults[messagePacket.MessageID]; ok {
+ chanResult <- messagePacket.Packet
+ } else {
+ log.Printf("Received unexpected message %d", messagePacket.MessageID)
+ ber.PrintPacket(messagePacket.Packet)
+ }
+ case MessageFinish:
+ // Remove from message list
+ l.Debug.Printf("Finished message %d", messagePacket.MessageID)
+ close(l.chanResults[messagePacket.MessageID])
+ delete(l.chanResults, messagePacket.MessageID)
+ }
+ }
+ }
+}
+
+func (l *Conn) reader() {
+ cleanstop := false
+ defer func() {
+ if err := recover(); err != nil {
+ log.Printf("ldap: recovered panic in reader: %v", err)
+ }
+ if !cleanstop {
+ l.Close()
+ }
+ }()
+
+ for {
+ if cleanstop {
+ l.Debug.Printf("reader clean stopping (without closing the connection)")
+ return
+ }
+ packet, err := ber.ReadPacket(l.conn)
+ if err != nil {
+ // A read error is expected here if we are closing the connection...
+ if !l.isClosing {
+ l.Debug.Printf("reader error: %s", err.Error())
+ }
+ return
+ }
+ addLDAPDescriptions(packet)
+ if len(packet.Children) == 0 {
+ l.Debug.Printf("Received bad ldap packet")
+ continue
+ }
+ l.messageMutex.Lock()
+ if l.isStartingTLS {
+ cleanstop = true
+ }
+ l.messageMutex.Unlock()
+ message := &messagePacket{
+ Op: MessageResponse,
+ MessageID: packet.Children[0].Value.(int64),
+ Packet: packet,
+ }
+ if !l.sendProcessMessage(message) {
+ return
+ }
+
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/control.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/control.go
new file mode 100644
index 000000000..4d8298093
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/control.go
@@ -0,0 +1,332 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ldap
+
+import (
+ "fmt"
+ "strconv"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+const (
+ ControlTypePaging = "1.2.840.113556.1.4.319"
+ ControlTypeBeheraPasswordPolicy = "1.3.6.1.4.1.42.2.27.8.5.1"
+ ControlTypeVChuPasswordMustChange = "2.16.840.1.113730.3.4.4"
+ ControlTypeVChuPasswordWarning = "2.16.840.1.113730.3.4.5"
+ ControlTypeManageDsaIT = "2.16.840.1.113730.3.4.2"
+)
+
+var ControlTypeMap = map[string]string{
+ ControlTypePaging: "Paging",
+ ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
+ ControlTypeManageDsaIT: "Manage DSA IT",
+}
+
+type Control interface {
+ GetControlType() string
+ Encode() *ber.Packet
+ String() string
+}
+
+type ControlString struct {
+ ControlType string
+ Criticality bool
+ ControlValue string
+}
+
+func (c *ControlString) GetControlType() string {
+ return c.ControlType
+}
+
+func (c *ControlString) Encode() *ber.Packet {
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
+ packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, c.ControlType, "Control Type ("+ControlTypeMap[c.ControlType]+")"))
+ if c.Criticality {
+ packet.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.Criticality, "Criticality"))
+ }
+ packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, string(c.ControlValue), "Control Value"))
+ return packet
+}
+
+func (c *ControlString) String() string {
+ return fmt.Sprintf("Control Type: %s (%q) Criticality: %t Control Value: %s", ControlTypeMap[c.ControlType], c.ControlType, c.Criticality, c.ControlValue)
+}
+
+type ControlPaging struct {
+ PagingSize uint32
+ Cookie []byte
+}
+
+func (c *ControlPaging) GetControlType() string {
+ return ControlTypePaging
+}
+
+func (c *ControlPaging) Encode() *ber.Packet {
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
+ packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypePaging, "Control Type ("+ControlTypeMap[ControlTypePaging]+")"))
+
+ p2 := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value (Paging)")
+ seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Search Control Value")
+ seq.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(c.PagingSize), "Paging Size"))
+ cookie := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Cookie")
+ cookie.Value = c.Cookie
+ cookie.Data.Write(c.Cookie)
+ seq.AppendChild(cookie)
+ p2.AppendChild(seq)
+
+ packet.AppendChild(p2)
+ return packet
+}
+
+func (c *ControlPaging) String() string {
+ return fmt.Sprintf(
+ "Control Type: %s (%q) Criticality: %t PagingSize: %d Cookie: %q",
+ ControlTypeMap[ControlTypePaging],
+ ControlTypePaging,
+ false,
+ c.PagingSize,
+ c.Cookie)
+}
+
+func (c *ControlPaging) SetCookie(cookie []byte) {
+ c.Cookie = cookie
+}
+
+type ControlBeheraPasswordPolicy struct {
+ Expire int64
+ Grace int64
+ Error int8
+ ErrorString string
+}
+
+func (c *ControlBeheraPasswordPolicy) GetControlType() string {
+ return ControlTypeBeheraPasswordPolicy
+}
+
+func (c *ControlBeheraPasswordPolicy) Encode() *ber.Packet {
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
+ packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeBeheraPasswordPolicy, "Control Type ("+ControlTypeMap[ControlTypeBeheraPasswordPolicy]+")"))
+
+ return packet
+}
+
+func (c *ControlBeheraPasswordPolicy) String() string {
+ return fmt.Sprintf(
+ "Control Type: %s (%q) Criticality: %t Expire: %d Grace: %d Error: %d, ErrorString: %s",
+ ControlTypeMap[ControlTypeBeheraPasswordPolicy],
+ ControlTypeBeheraPasswordPolicy,
+ false,
+ c.Expire,
+ c.Grace,
+ c.Error,
+ c.ErrorString)
+}
+
+type ControlVChuPasswordMustChange struct {
+ MustChange bool
+}
+
+func (c *ControlVChuPasswordMustChange) GetControlType() string {
+ return ControlTypeVChuPasswordMustChange
+}
+
+func (c *ControlVChuPasswordMustChange) Encode() *ber.Packet {
+ return nil
+}
+
+func (c *ControlVChuPasswordMustChange) String() string {
+ return fmt.Sprintf(
+ "Control Type: %s (%q) Criticality: %t MustChange: %b",
+ ControlTypeMap[ControlTypeVChuPasswordMustChange],
+ ControlTypeVChuPasswordMustChange,
+ false,
+ c.MustChange)
+}
+
+type ControlVChuPasswordWarning struct {
+ Expire int64
+}
+
+func (c *ControlVChuPasswordWarning) GetControlType() string {
+ return ControlTypeVChuPasswordWarning
+}
+
+func (c *ControlVChuPasswordWarning) Encode() *ber.Packet {
+ return nil
+}
+
+func (c *ControlVChuPasswordWarning) String() string {
+ return fmt.Sprintf(
+ "Control Type: %s (%q) Criticality: %t Expire: %b",
+ ControlTypeMap[ControlTypeVChuPasswordWarning],
+ ControlTypeVChuPasswordWarning,
+ false,
+ c.Expire)
+}
+
+type ControlManageDsaIT struct {
+ Criticality bool
+}
+
+func (c *ControlManageDsaIT) GetControlType() string {
+ return ControlTypeManageDsaIT
+}
+
+func (c *ControlManageDsaIT) Encode() *ber.Packet {
+ //FIXME
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
+ packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeManageDsaIT, "Control Type ("+ControlTypeMap[ControlTypeManageDsaIT]+")"))
+ if c.Criticality {
+ packet.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.Criticality, "Criticality"))
+ }
+ return packet
+}
+
+func (c *ControlManageDsaIT) String() string {
+ return fmt.Sprintf(
+ "Control Type: %s (%q) Criticality: %t",
+ ControlTypeMap[ControlTypeManageDsaIT],
+ ControlTypeManageDsaIT,
+ c.Criticality)
+}
+
+func NewControlManageDsaIT(Criticality bool) *ControlManageDsaIT {
+ return &ControlManageDsaIT{Criticality: Criticality}
+}
+
+func FindControl(controls []Control, controlType string) Control {
+ for _, c := range controls {
+ if c.GetControlType() == controlType {
+ return c
+ }
+ }
+ return nil
+}
+
+func DecodeControl(packet *ber.Packet) Control {
+ ControlType := packet.Children[0].Value.(string)
+ Criticality := false
+
+ packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
+ value := packet.Children[1]
+ if len(packet.Children) == 3 {
+ value = packet.Children[2]
+ packet.Children[1].Description = "Criticality"
+ Criticality = packet.Children[1].Value.(bool)
+ }
+
+ value.Description = "Control Value"
+ switch ControlType {
+ case ControlTypePaging:
+ value.Description += " (Paging)"
+ c := new(ControlPaging)
+ if value.Value != nil {
+ valueChildren := ber.DecodePacket(value.Data.Bytes())
+ value.Data.Truncate(0)
+ value.Value = nil
+ value.AppendChild(valueChildren)
+ }
+ value = value.Children[0]
+ value.Description = "Search Control Value"
+ value.Children[0].Description = "Paging Size"
+ value.Children[1].Description = "Cookie"
+ c.PagingSize = uint32(value.Children[0].Value.(int64))
+ c.Cookie = value.Children[1].Data.Bytes()
+ value.Children[1].Value = c.Cookie
+ return c
+ case ControlTypeBeheraPasswordPolicy:
+ value.Description += " (Password Policy - Behera)"
+ c := NewControlBeheraPasswordPolicy()
+ if value.Value != nil {
+ valueChildren := ber.DecodePacket(value.Data.Bytes())
+ value.Data.Truncate(0)
+ value.Value = nil
+ value.AppendChild(valueChildren)
+ }
+
+ sequence := value.Children[0]
+
+ for _, child := range sequence.Children {
+ if child.Tag == 0 {
+ //Warning
+ child := child.Children[0]
+ packet := ber.DecodePacket(child.Data.Bytes())
+ val, ok := packet.Value.(int64)
+ if ok {
+ if child.Tag == 0 {
+ //timeBeforeExpiration
+ c.Expire = val
+ child.Value = c.Expire
+ } else if child.Tag == 1 {
+ //graceAuthNsRemaining
+ c.Grace = val
+ child.Value = c.Grace
+ }
+ }
+ } else if child.Tag == 1 {
+ // Error
+ packet := ber.DecodePacket(child.Data.Bytes())
+ val, ok := packet.Value.(int8)
+ if !ok {
+ // what to do?
+ val = -1
+ }
+ c.Error = val
+ child.Value = c.Error
+ c.ErrorString = BeheraPasswordPolicyErrorMap[c.Error]
+ }
+ }
+ return c
+ case ControlTypeVChuPasswordMustChange:
+ c := &ControlVChuPasswordMustChange{MustChange: true}
+ return c
+ case ControlTypeVChuPasswordWarning:
+ c := &ControlVChuPasswordWarning{Expire: -1}
+ expireStr := ber.DecodeString(value.Data.Bytes())
+
+ expire, err := strconv.ParseInt(expireStr, 10, 64)
+ if err != nil {
+ return nil
+ }
+ c.Expire = expire
+ value.Value = c.Expire
+
+ return c
+ }
+ c := new(ControlString)
+ c.ControlType = ControlType
+ c.Criticality = Criticality
+ c.ControlValue = value.Value.(string)
+ return c
+}
+
+func NewControlString(controlType string, criticality bool, controlValue string) *ControlString {
+ return &ControlString{
+ ControlType: controlType,
+ Criticality: criticality,
+ ControlValue: controlValue,
+ }
+}
+
+func NewControlPaging(pagingSize uint32) *ControlPaging {
+ return &ControlPaging{PagingSize: pagingSize}
+}
+
+func NewControlBeheraPasswordPolicy() *ControlBeheraPasswordPolicy {
+ return &ControlBeheraPasswordPolicy{
+ Expire: -1,
+ Grace: -1,
+ Error: -1,
+ }
+}
+
+func encodeControls(controls []Control) *ber.Packet {
+ packet := ber.Encode(ber.ClassContext, ber.TypeConstructed, 0, nil, "Controls")
+ for _, control := range controls {
+ packet.AppendChild(control.Encode())
+ }
+ return packet
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/debug.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/debug.go
new file mode 100644
index 000000000..b8a7ecbff
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/debug.go
@@ -0,0 +1,24 @@
+package ldap
+
+import (
+ "log"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+// debbuging type
+// - has a Printf method to write the debug output
+type debugging bool
+
+// write debug output
+func (debug debugging) Printf(format string, args ...interface{}) {
+ if debug {
+ log.Printf(format, args...)
+ }
+}
+
+func (debug debugging) PrintPacket(packet *ber.Packet) {
+ if debug {
+ ber.PrintPacket(packet)
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/del.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/del.go
new file mode 100644
index 000000000..2f0eae1cd
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/del.go
@@ -0,0 +1,79 @@
+//
+// https://tools.ietf.org/html/rfc4511
+//
+// DelRequest ::= [APPLICATION 10] LDAPDN
+
+package ldap
+
+import (
+ "errors"
+ "log"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+type DelRequest struct {
+ DN string
+ Controls []Control
+}
+
+func (d DelRequest) encode() *ber.Packet {
+ request := ber.Encode(ber.ClassApplication, ber.TypePrimitive, ApplicationDelRequest, d.DN, "Del Request")
+ request.Data.Write([]byte(d.DN))
+ return request
+}
+
+func NewDelRequest(DN string,
+ Controls []Control) *DelRequest {
+ return &DelRequest{
+ DN: DN,
+ Controls: Controls,
+ }
+}
+
+func (l *Conn) Del(delRequest *DelRequest) error {
+ messageID := l.nextMessageID()
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(delRequest.encode())
+ if delRequest.Controls != nil {
+ packet.AppendChild(encodeControls(delRequest.Controls))
+ }
+
+ l.Debug.PrintPacket(packet)
+
+ channel, err := l.sendMessage(packet)
+ if err != nil {
+ return err
+ }
+ if channel == nil {
+ return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
+ }
+ defer l.finishMessage(messageID)
+
+ l.Debug.Printf("%d: waiting for response", messageID)
+ packet = <-channel
+ l.Debug.Printf("%d: got response %p", messageID, packet)
+ if packet == nil {
+ return NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
+ }
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ return err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ if packet.Children[1].Tag == ApplicationDelResponse {
+ resultCode, resultDescription := getLDAPResultCode(packet)
+ if resultCode != 0 {
+ return NewError(resultCode, errors.New(resultDescription))
+ }
+ } else {
+ log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
+ }
+
+ l.Debug.Printf("%d: returning", messageID)
+ return nil
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/dn.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/dn.go
new file mode 100644
index 000000000..5d83c5e9a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/dn.go
@@ -0,0 +1,155 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// File contains DN parsing functionallity
+//
+// https://tools.ietf.org/html/rfc4514
+//
+// distinguishedName = [ relativeDistinguishedName
+// *( COMMA relativeDistinguishedName ) ]
+// relativeDistinguishedName = attributeTypeAndValue
+// *( PLUS attributeTypeAndValue )
+// attributeTypeAndValue = attributeType EQUALS attributeValue
+// attributeType = descr / numericoid
+// attributeValue = string / hexstring
+//
+// ; The following characters are to be escaped when they appear
+// ; in the value to be encoded: ESC, one of <escaped>, leading
+// ; SHARP or SPACE, trailing SPACE, and NULL.
+// string = [ ( leadchar / pair ) [ *( stringchar / pair )
+// ( trailchar / pair ) ] ]
+//
+// leadchar = LUTF1 / UTFMB
+// LUTF1 = %x01-1F / %x21 / %x24-2A / %x2D-3A /
+// %x3D / %x3F-5B / %x5D-7F
+//
+// trailchar = TUTF1 / UTFMB
+// TUTF1 = %x01-1F / %x21 / %x23-2A / %x2D-3A /
+// %x3D / %x3F-5B / %x5D-7F
+//
+// stringchar = SUTF1 / UTFMB
+// SUTF1 = %x01-21 / %x23-2A / %x2D-3A /
+// %x3D / %x3F-5B / %x5D-7F
+//
+// pair = ESC ( ESC / special / hexpair )
+// special = escaped / SPACE / SHARP / EQUALS
+// escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE
+// hexstring = SHARP 1*hexpair
+// hexpair = HEX HEX
+//
+// where the productions <descr>, <numericoid>, <COMMA>, <DQUOTE>,
+// <EQUALS>, <ESC>, <HEX>, <LANGLE>, <NULL>, <PLUS>, <RANGLE>, <SEMI>,
+// <SPACE>, <SHARP>, and <UTFMB> are defined in [RFC4512].
+//
+
+package ldap
+
+import (
+ "bytes"
+ enchex "encoding/hex"
+ "errors"
+ "fmt"
+ "strings"
+
+ ber "gopkg.in/asn1-ber.v1"
+)
+
+type AttributeTypeAndValue struct {
+ Type string
+ Value string
+}
+
+type RelativeDN struct {
+ Attributes []*AttributeTypeAndValue
+}
+
+type DN struct {
+ RDNs []*RelativeDN
+}
+
+func ParseDN(str string) (*DN, error) {
+ dn := new(DN)
+ dn.RDNs = make([]*RelativeDN, 0)
+ rdn := new(RelativeDN)
+ rdn.Attributes = make([]*AttributeTypeAndValue, 0)
+ buffer := bytes.Buffer{}
+ attribute := new(AttributeTypeAndValue)
+ escaping := false
+
+ for i := 0; i < len(str); i++ {
+ char := str[i]
+ if escaping {
+ escaping = false
+ switch char {
+ case ' ', '"', '#', '+', ',', ';', '<', '=', '>', '\\':
+ buffer.WriteByte(char)
+ continue
+ }
+ // Not a special character, assume hex encoded octet
+ if len(str) == i+1 {
+ return nil, errors.New("Got corrupted escaped character")
+ }
+
+ dst := []byte{0}
+ n, err := enchex.Decode([]byte(dst), []byte(str[i:i+2]))
+ if err != nil {
+ return nil, errors.New(
+ fmt.Sprintf("Failed to decode escaped character: %s", err))
+ } else if n != 1 {
+ return nil, errors.New(
+ fmt.Sprintf("Expected 1 byte when un-escaping, got %d", n))
+ }
+ buffer.WriteByte(dst[0])
+ i++
+ } else if char == '\\' {
+ escaping = true
+ } else if char == '=' {
+ attribute.Type = buffer.String()
+ buffer.Reset()
+ // Special case: If the first character in the value is # the
+ // following data is BER encoded so we can just fast forward
+ // and decode.
+ if len(str) > i+1 && str[i+1] == '#' {
+ i += 2
+ index := strings.IndexAny(str[i:], ",+")
+ data := str
+ if index > 0 {
+ data = str[i : i+index]
+ } else {
+ data = str[i:]
+ }
+ raw_ber, err := enchex.DecodeString(data)
+ if err != nil {
+ return nil, errors.New(
+ fmt.Sprintf("Failed to decode BER encoding: %s", err))
+ }
+ packet := ber.DecodePacket(raw_ber)
+ buffer.WriteString(packet.Data.String())
+ i += len(data) - 1
+ }
+ } else if char == ',' || char == '+' {
+ // We're done with this RDN or value, push it
+ attribute.Value = buffer.String()
+ rdn.Attributes = append(rdn.Attributes, attribute)
+ attribute = new(AttributeTypeAndValue)
+ if char == ',' {
+ dn.RDNs = append(dn.RDNs, rdn)
+ rdn = new(RelativeDN)
+ rdn.Attributes = make([]*AttributeTypeAndValue, 0)
+ }
+ buffer.Reset()
+ } else {
+ buffer.WriteByte(char)
+ }
+ }
+ if buffer.Len() > 0 {
+ if len(attribute.Type) == 0 {
+ return nil, errors.New("DN ended with incomplete type, value pair")
+ }
+ attribute.Value = buffer.String()
+ rdn.Attributes = append(rdn.Attributes, attribute)
+ dn.RDNs = append(dn.RDNs, rdn)
+ }
+ return dn, nil
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/dn_test.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/dn_test.go
new file mode 100644
index 000000000..39817c427
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/dn_test.go
@@ -0,0 +1,70 @@
+package ldap_test
+
+import (
+ "reflect"
+ "testing"
+
+ "gopkg.in/ldap.v2"
+)
+
+func TestSuccessfulDNParsing(t *testing.T) {
+ testcases := map[string]ldap.DN{
+ "": ldap.DN{[]*ldap.RelativeDN{}},
+ "cn=Jim\\2C \\22Hasse Hö\\22 Hansson!,dc=dummy,dc=com": ldap.DN{[]*ldap.RelativeDN{
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"cn", "Jim, \"Hasse Hö\" Hansson!"}}},
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"dc", "dummy"}}},
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"dc", "com"}}}}},
+ "UID=jsmith,DC=example,DC=net": ldap.DN{[]*ldap.RelativeDN{
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"UID", "jsmith"}}},
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "example"}}},
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}},
+ "OU=Sales+CN=J. Smith,DC=example,DC=net": ldap.DN{[]*ldap.RelativeDN{
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{
+ &ldap.AttributeTypeAndValue{"OU", "Sales"},
+ &ldap.AttributeTypeAndValue{"CN", "J. Smith"}}},
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "example"}}},
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}},
+ "1.3.6.1.4.1.1466.0=#04024869": ldap.DN{[]*ldap.RelativeDN{
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"1.3.6.1.4.1.1466.0", "Hi"}}}}},
+ "1.3.6.1.4.1.1466.0=#04024869,DC=net": ldap.DN{[]*ldap.RelativeDN{
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"1.3.6.1.4.1.1466.0", "Hi"}}},
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}},
+ "CN=Lu\\C4\\8Di\\C4\\87": ldap.DN{[]*ldap.RelativeDN{
+ &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"CN", "LuÄić"}}}}},
+ }
+
+ for test, answer := range testcases {
+ dn, err := ldap.ParseDN(test)
+ if err != nil {
+ t.Errorf(err.Error())
+ continue
+ }
+ if !reflect.DeepEqual(dn, &answer) {
+ t.Errorf("Parsed DN %s is not equal to the expected structure", test)
+ for _, rdn := range dn.RDNs {
+ for _, attribs := range rdn.Attributes {
+ t.Logf("#%v\n", attribs)
+ }
+ }
+ }
+ }
+}
+
+func TestErrorDNParsing(t *testing.T) {
+ testcases := map[string]string{
+ "*": "DN ended with incomplete type, value pair",
+ "cn=Jim\\0Test": "Failed to decode escaped character: encoding/hex: invalid byte: U+0054 'T'",
+ "cn=Jim\\0": "Got corrupted escaped character",
+ "DC=example,=net": "DN ended with incomplete type, value pair",
+ "1=#0402486": "Failed to decode BER encoding: encoding/hex: odd length hex string",
+ }
+
+ for test, answer := range testcases {
+ _, err := ldap.ParseDN(test)
+ if err == nil {
+ t.Errorf("Expected %s to fail parsing but succeeded\n", test)
+ } else if err.Error() != answer {
+ t.Errorf("Unexpected error on %s:\n%s\nvs.\n%s\n", test, answer, err.Error())
+ }
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/doc.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/doc.go
new file mode 100644
index 000000000..f20d39bc9
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/doc.go
@@ -0,0 +1,4 @@
+/*
+Package ldap provides basic LDAP v3 functionality.
+*/
+package ldap
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/error.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/error.go
new file mode 100644
index 000000000..2dbc30ac0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/error.go
@@ -0,0 +1,137 @@
+package ldap
+
+import (
+ "fmt"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+// LDAP Result Codes
+const (
+ LDAPResultSuccess = 0
+ LDAPResultOperationsError = 1
+ LDAPResultProtocolError = 2
+ LDAPResultTimeLimitExceeded = 3
+ LDAPResultSizeLimitExceeded = 4
+ LDAPResultCompareFalse = 5
+ LDAPResultCompareTrue = 6
+ LDAPResultAuthMethodNotSupported = 7
+ LDAPResultStrongAuthRequired = 8
+ LDAPResultReferral = 10
+ LDAPResultAdminLimitExceeded = 11
+ LDAPResultUnavailableCriticalExtension = 12
+ LDAPResultConfidentialityRequired = 13
+ LDAPResultSaslBindInProgress = 14
+ LDAPResultNoSuchAttribute = 16
+ LDAPResultUndefinedAttributeType = 17
+ LDAPResultInappropriateMatching = 18
+ LDAPResultConstraintViolation = 19
+ LDAPResultAttributeOrValueExists = 20
+ LDAPResultInvalidAttributeSyntax = 21
+ LDAPResultNoSuchObject = 32
+ LDAPResultAliasProblem = 33
+ LDAPResultInvalidDNSyntax = 34
+ LDAPResultAliasDereferencingProblem = 36
+ LDAPResultInappropriateAuthentication = 48
+ LDAPResultInvalidCredentials = 49
+ LDAPResultInsufficientAccessRights = 50
+ LDAPResultBusy = 51
+ LDAPResultUnavailable = 52
+ LDAPResultUnwillingToPerform = 53
+ LDAPResultLoopDetect = 54
+ LDAPResultNamingViolation = 64
+ LDAPResultObjectClassViolation = 65
+ LDAPResultNotAllowedOnNonLeaf = 66
+ LDAPResultNotAllowedOnRDN = 67
+ LDAPResultEntryAlreadyExists = 68
+ LDAPResultObjectClassModsProhibited = 69
+ LDAPResultAffectsMultipleDSAs = 71
+ LDAPResultOther = 80
+
+ ErrorNetwork = 200
+ ErrorFilterCompile = 201
+ ErrorFilterDecompile = 202
+ ErrorDebugging = 203
+ ErrorUnexpectedMessage = 204
+ ErrorUnexpectedResponse = 205
+)
+
+var LDAPResultCodeMap = map[uint8]string{
+ LDAPResultSuccess: "Success",
+ LDAPResultOperationsError: "Operations Error",
+ LDAPResultProtocolError: "Protocol Error",
+ LDAPResultTimeLimitExceeded: "Time Limit Exceeded",
+ LDAPResultSizeLimitExceeded: "Size Limit Exceeded",
+ LDAPResultCompareFalse: "Compare False",
+ LDAPResultCompareTrue: "Compare True",
+ LDAPResultAuthMethodNotSupported: "Auth Method Not Supported",
+ LDAPResultStrongAuthRequired: "Strong Auth Required",
+ LDAPResultReferral: "Referral",
+ LDAPResultAdminLimitExceeded: "Admin Limit Exceeded",
+ LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension",
+ LDAPResultConfidentialityRequired: "Confidentiality Required",
+ LDAPResultSaslBindInProgress: "Sasl Bind In Progress",
+ LDAPResultNoSuchAttribute: "No Such Attribute",
+ LDAPResultUndefinedAttributeType: "Undefined Attribute Type",
+ LDAPResultInappropriateMatching: "Inappropriate Matching",
+ LDAPResultConstraintViolation: "Constraint Violation",
+ LDAPResultAttributeOrValueExists: "Attribute Or Value Exists",
+ LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax",
+ LDAPResultNoSuchObject: "No Such Object",
+ LDAPResultAliasProblem: "Alias Problem",
+ LDAPResultInvalidDNSyntax: "Invalid DN Syntax",
+ LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem",
+ LDAPResultInappropriateAuthentication: "Inappropriate Authentication",
+ LDAPResultInvalidCredentials: "Invalid Credentials",
+ LDAPResultInsufficientAccessRights: "Insufficient Access Rights",
+ LDAPResultBusy: "Busy",
+ LDAPResultUnavailable: "Unavailable",
+ LDAPResultUnwillingToPerform: "Unwilling To Perform",
+ LDAPResultLoopDetect: "Loop Detect",
+ LDAPResultNamingViolation: "Naming Violation",
+ LDAPResultObjectClassViolation: "Object Class Violation",
+ LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf",
+ LDAPResultNotAllowedOnRDN: "Not Allowed On RDN",
+ LDAPResultEntryAlreadyExists: "Entry Already Exists",
+ LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
+ LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
+ LDAPResultOther: "Other",
+}
+
+func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
+ if len(packet.Children) >= 2 {
+ response := packet.Children[1]
+ if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
+ // Children[1].Children[2] is the diagnosticMessage which is guaranteed to exist as seen here: https://tools.ietf.org/html/rfc4511#section-4.1.9
+ return uint8(response.Children[0].Value.(int64)), response.Children[2].Value.(string)
+ }
+ }
+
+ return ErrorNetwork, "Invalid packet format"
+}
+
+type Error struct {
+ Err error
+ ResultCode uint8
+}
+
+func (e *Error) Error() string {
+ return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
+}
+
+func NewError(resultCode uint8, err error) error {
+ return &Error{ResultCode: resultCode, Err: err}
+}
+
+func IsErrorWithCode(err error, desiredResultCode uint8) bool {
+ if err == nil {
+ return false
+ }
+
+ serverError, ok := err.(*Error)
+ if !ok {
+ return false
+ }
+
+ return serverError.ResultCode == desiredResultCode
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/example_test.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/example_test.go
new file mode 100644
index 000000000..b018a9664
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/example_test.go
@@ -0,0 +1,305 @@
+package ldap_test
+
+import (
+ "crypto/tls"
+ "fmt"
+ "log"
+
+ "gopkg.in/ldap.v2"
+)
+
+// ExampleConn_Bind demonstrates how to bind a connection to an ldap user
+// allowing access to restricted attrabutes that user has access to
+func ExampleConn_Bind() {
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+
+ err = l.Bind("cn=read-only-admin,dc=example,dc=com", "password")
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+// ExampleConn_Search demonstrates how to use the search interface
+func ExampleConn_Search() {
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+
+ searchRequest := ldap.NewSearchRequest(
+ "dc=example,dc=com", // The base dn to search
+ ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
+ "(&(objectClass=organizationalPerson))", // The filter to apply
+ []string{"dn", "cn"}, // A list attributes to retrieve
+ nil,
+ )
+
+ sr, err := l.Search(searchRequest)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ for _, entry := range sr.Entries {
+ fmt.Printf("%s: %v\n", entry.DN, entry.GetAttributeValue("cn"))
+ }
+}
+
+// ExampleStartTLS demonstrates how to start a TLS connection
+func ExampleConn_StartTLS() {
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+
+ // Reconnect with TLS
+ err = l.StartTLS(&tls.Config{InsecureSkipVerify: true})
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Opertations via l are now encrypted
+}
+
+// ExampleConn_Compare demonstrates how to comapre an attribute with a value
+func ExampleConn_Compare() {
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+
+ matched, err := l.Compare("cn=user,dc=example,dc=com", "uid", "someuserid")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println(matched)
+}
+
+func ExampleConn_PasswordModify_admin() {
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+
+ err = l.Bind("cn=admin,dc=example,dc=com", "password")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ passwordModifyRequest := ldap.NewPasswordModifyRequest("cn=user,dc=example,dc=com", "", "NewPassword")
+ _, err = l.PasswordModify(passwordModifyRequest)
+
+ if err != nil {
+ log.Fatalf("Password could not be changed: %s", err.Error())
+ }
+}
+
+func ExampleConn_PasswordModify_generatedPassword() {
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+
+ err = l.Bind("cn=user,dc=example,dc=com", "password")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ passwordModifyRequest := ldap.NewPasswordModifyRequest("", "OldPassword", "")
+ passwordModifyResponse, err := l.PasswordModify(passwordModifyRequest)
+ if err != nil {
+ log.Fatalf("Password could not be changed: %s", err.Error())
+ }
+
+ generatedPassword := passwordModifyResponse.GeneratedPassword
+ log.Printf("Generated password: %s\n", generatedPassword)
+}
+
+func ExampleConn_PasswordModify_setNewPassword() {
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+
+ err = l.Bind("cn=user,dc=example,dc=com", "password")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ passwordModifyRequest := ldap.NewPasswordModifyRequest("", "OldPassword", "NewPassword")
+ _, err = l.PasswordModify(passwordModifyRequest)
+
+ if err != nil {
+ log.Fatalf("Password could not be changed: %s", err.Error())
+ }
+}
+
+func ExampleConn_Modify() {
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+
+ // Add a description, and replace the mail attributes
+ modify := ldap.NewModifyRequest("cn=user,dc=example,dc=com")
+ modify.Add("description", []string{"An example user"})
+ modify.Replace("mail", []string{"user@example.org"})
+
+ err = l.Modify(modify)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+// Example User Authentication shows how a typical application can verify a login attempt
+func Example_userAuthentication() {
+ // The username and password we want to check
+ username := "someuser"
+ password := "userpassword"
+
+ bindusername := "readonly"
+ bindpassword := "password"
+
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+
+ // Reconnect with TLS
+ err = l.StartTLS(&tls.Config{InsecureSkipVerify: true})
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // First bind with a read only user
+ err = l.Bind(bindusername, bindpassword)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Search for the given username
+ searchRequest := ldap.NewSearchRequest(
+ "dc=example,dc=com",
+ ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
+ fmt.Sprintf("(&(objectClass=organizationalPerson)&(uid=%s))", username),
+ []string{"dn"},
+ nil,
+ )
+
+ sr, err := l.Search(searchRequest)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if len(sr.Entries) != 1 {
+ log.Fatal("User does not exist or too many entries returned")
+ }
+
+ userdn := sr.Entries[0].DN
+
+ // Bind as the user to verify their password
+ err = l.Bind(userdn, password)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Rebind as the read only user for any futher queries
+ err = l.Bind(bindusername, bindpassword)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func Example_beherappolicy() {
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+
+ controls := []ldap.Control{}
+ controls = append(controls, ldap.NewControlBeheraPasswordPolicy())
+ bindRequest := ldap.NewSimpleBindRequest("cn=admin,dc=example,dc=com", "password", controls)
+
+ r, err := l.SimpleBind(bindRequest)
+ ppolicyControl := ldap.FindControl(r.Controls, ldap.ControlTypeBeheraPasswordPolicy)
+
+ var ppolicy *ldap.ControlBeheraPasswordPolicy
+ if ppolicyControl != nil {
+ ppolicy = ppolicyControl.(*ldap.ControlBeheraPasswordPolicy)
+ } else {
+ log.Printf("ppolicyControl response not avaliable.\n")
+ }
+ if err != nil {
+ errStr := "ERROR: Cannot bind: " + err.Error()
+ if ppolicy != nil && ppolicy.Error >= 0 {
+ errStr += ":" + ppolicy.ErrorString
+ }
+ log.Print(errStr)
+ } else {
+ logStr := "Login Ok"
+ if ppolicy != nil {
+ if ppolicy.Expire >= 0 {
+ logStr += fmt.Sprintf(". Password expires in %d seconds\n", ppolicy.Expire)
+ } else if ppolicy.Grace >= 0 {
+ logStr += fmt.Sprintf(". Password expired, %d grace logins remain\n", ppolicy.Grace)
+ }
+ }
+ log.Print(logStr)
+ }
+}
+
+func Example_vchuppolicy() {
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+ l.Debug = true
+
+ bindRequest := ldap.NewSimpleBindRequest("cn=admin,dc=example,dc=com", "password", nil)
+
+ r, err := l.SimpleBind(bindRequest)
+
+ passwordMustChangeControl := ldap.FindControl(r.Controls, ldap.ControlTypeVChuPasswordMustChange)
+ var passwordMustChange *ldap.ControlVChuPasswordMustChange
+ if passwordMustChangeControl != nil {
+ passwordMustChange = passwordMustChangeControl.(*ldap.ControlVChuPasswordMustChange)
+ }
+
+ if passwordMustChange != nil && passwordMustChange.MustChange {
+ log.Printf("Password Must be changed.\n")
+ }
+
+ passwordWarningControl := ldap.FindControl(r.Controls, ldap.ControlTypeVChuPasswordWarning)
+
+ var passwordWarning *ldap.ControlVChuPasswordWarning
+ if passwordWarningControl != nil {
+ passwordWarning = passwordWarningControl.(*ldap.ControlVChuPasswordWarning)
+ } else {
+ log.Printf("ppolicyControl response not available.\n")
+ }
+ if err != nil {
+ log.Print("ERROR: Cannot bind: " + err.Error())
+ } else {
+ logStr := "Login Ok"
+ if passwordWarning != nil {
+ if passwordWarning.Expire >= 0 {
+ logStr += fmt.Sprintf(". Password expires in %d seconds\n", passwordWarning.Expire)
+ }
+ }
+ log.Print(logStr)
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/filter.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/filter.go
new file mode 100644
index 000000000..63bcec1e3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/filter.go
@@ -0,0 +1,456 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ldap
+
+import (
+ "bytes"
+ hexpac "encoding/hex"
+ "errors"
+ "fmt"
+ "strings"
+ "unicode/utf8"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+const (
+ FilterAnd = 0
+ FilterOr = 1
+ FilterNot = 2
+ FilterEqualityMatch = 3
+ FilterSubstrings = 4
+ FilterGreaterOrEqual = 5
+ FilterLessOrEqual = 6
+ FilterPresent = 7
+ FilterApproxMatch = 8
+ FilterExtensibleMatch = 9
+)
+
+var FilterMap = map[uint64]string{
+ FilterAnd: "And",
+ FilterOr: "Or",
+ FilterNot: "Not",
+ FilterEqualityMatch: "Equality Match",
+ FilterSubstrings: "Substrings",
+ FilterGreaterOrEqual: "Greater Or Equal",
+ FilterLessOrEqual: "Less Or Equal",
+ FilterPresent: "Present",
+ FilterApproxMatch: "Approx Match",
+ FilterExtensibleMatch: "Extensible Match",
+}
+
+const (
+ FilterSubstringsInitial = 0
+ FilterSubstringsAny = 1
+ FilterSubstringsFinal = 2
+)
+
+var FilterSubstringsMap = map[uint64]string{
+ FilterSubstringsInitial: "Substrings Initial",
+ FilterSubstringsAny: "Substrings Any",
+ FilterSubstringsFinal: "Substrings Final",
+}
+
+const (
+ MatchingRuleAssertionMatchingRule = 1
+ MatchingRuleAssertionType = 2
+ MatchingRuleAssertionMatchValue = 3
+ MatchingRuleAssertionDNAttributes = 4
+)
+
+var MatchingRuleAssertionMap = map[uint64]string{
+ MatchingRuleAssertionMatchingRule: "Matching Rule Assertion Matching Rule",
+ MatchingRuleAssertionType: "Matching Rule Assertion Type",
+ MatchingRuleAssertionMatchValue: "Matching Rule Assertion Match Value",
+ MatchingRuleAssertionDNAttributes: "Matching Rule Assertion DN Attributes",
+}
+
+func CompileFilter(filter string) (*ber.Packet, error) {
+ if len(filter) == 0 || filter[0] != '(' {
+ return nil, NewError(ErrorFilterCompile, errors.New("ldap: filter does not start with an '('"))
+ }
+ packet, pos, err := compileFilter(filter, 1)
+ if err != nil {
+ return nil, err
+ }
+ if pos != len(filter) {
+ return nil, NewError(ErrorFilterCompile, errors.New("ldap: finished compiling filter with extra at end: "+fmt.Sprint(filter[pos:])))
+ }
+ return packet, nil
+}
+
+func DecompileFilter(packet *ber.Packet) (ret string, err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = NewError(ErrorFilterDecompile, errors.New("ldap: error decompiling filter"))
+ }
+ }()
+ ret = "("
+ err = nil
+ childStr := ""
+
+ switch packet.Tag {
+ case FilterAnd:
+ ret += "&"
+ for _, child := range packet.Children {
+ childStr, err = DecompileFilter(child)
+ if err != nil {
+ return
+ }
+ ret += childStr
+ }
+ case FilterOr:
+ ret += "|"
+ for _, child := range packet.Children {
+ childStr, err = DecompileFilter(child)
+ if err != nil {
+ return
+ }
+ ret += childStr
+ }
+ case FilterNot:
+ ret += "!"
+ childStr, err = DecompileFilter(packet.Children[0])
+ if err != nil {
+ return
+ }
+ ret += childStr
+
+ case FilterSubstrings:
+ ret += ber.DecodeString(packet.Children[0].Data.Bytes())
+ ret += "="
+ for i, child := range packet.Children[1].Children {
+ if i == 0 && child.Tag != FilterSubstringsInitial {
+ ret += "*"
+ }
+ ret += EscapeFilter(ber.DecodeString(child.Data.Bytes()))
+ if child.Tag != FilterSubstringsFinal {
+ ret += "*"
+ }
+ }
+ case FilterEqualityMatch:
+ ret += ber.DecodeString(packet.Children[0].Data.Bytes())
+ ret += "="
+ ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
+ case FilterGreaterOrEqual:
+ ret += ber.DecodeString(packet.Children[0].Data.Bytes())
+ ret += ">="
+ ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
+ case FilterLessOrEqual:
+ ret += ber.DecodeString(packet.Children[0].Data.Bytes())
+ ret += "<="
+ ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
+ case FilterPresent:
+ ret += ber.DecodeString(packet.Data.Bytes())
+ ret += "=*"
+ case FilterApproxMatch:
+ ret += ber.DecodeString(packet.Children[0].Data.Bytes())
+ ret += "~="
+ ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
+ case FilterExtensibleMatch:
+ attr := ""
+ dnAttributes := false
+ matchingRule := ""
+ value := ""
+
+ for _, child := range packet.Children {
+ switch child.Tag {
+ case MatchingRuleAssertionMatchingRule:
+ matchingRule = ber.DecodeString(child.Data.Bytes())
+ case MatchingRuleAssertionType:
+ attr = ber.DecodeString(child.Data.Bytes())
+ case MatchingRuleAssertionMatchValue:
+ value = ber.DecodeString(child.Data.Bytes())
+ case MatchingRuleAssertionDNAttributes:
+ dnAttributes = child.Value.(bool)
+ }
+ }
+
+ if len(attr) > 0 {
+ ret += attr
+ }
+ if dnAttributes {
+ ret += ":dn"
+ }
+ if len(matchingRule) > 0 {
+ ret += ":"
+ ret += matchingRule
+ }
+ ret += ":="
+ ret += EscapeFilter(value)
+ }
+
+ ret += ")"
+ return
+}
+
+func compileFilterSet(filter string, pos int, parent *ber.Packet) (int, error) {
+ for pos < len(filter) && filter[pos] == '(' {
+ child, newPos, err := compileFilter(filter, pos+1)
+ if err != nil {
+ return pos, err
+ }
+ pos = newPos
+ parent.AppendChild(child)
+ }
+ if pos == len(filter) {
+ return pos, NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter"))
+ }
+
+ return pos + 1, nil
+}
+
+func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
+ var (
+ packet *ber.Packet
+ err error
+ )
+
+ defer func() {
+ if r := recover(); r != nil {
+ err = NewError(ErrorFilterCompile, errors.New("ldap: error compiling filter"))
+ }
+ }()
+ newPos := pos
+
+ currentRune, currentWidth := utf8.DecodeRuneInString(filter[newPos:])
+
+ switch currentRune {
+ case utf8.RuneError:
+ return nil, 0, NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", newPos))
+ case '(':
+ packet, newPos, err = compileFilter(filter, pos+currentWidth)
+ newPos++
+ return packet, newPos, err
+ case '&':
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterAnd, nil, FilterMap[FilterAnd])
+ newPos, err = compileFilterSet(filter, pos+currentWidth, packet)
+ return packet, newPos, err
+ case '|':
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterOr, nil, FilterMap[FilterOr])
+ newPos, err = compileFilterSet(filter, pos+currentWidth, packet)
+ return packet, newPos, err
+ case '!':
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterNot, nil, FilterMap[FilterNot])
+ var child *ber.Packet
+ child, newPos, err = compileFilter(filter, pos+currentWidth)
+ packet.AppendChild(child)
+ return packet, newPos, err
+ default:
+ READING_ATTR := 0
+ READING_EXTENSIBLE_MATCHING_RULE := 1
+ READING_CONDITION := 2
+
+ state := READING_ATTR
+
+ attribute := ""
+ extensibleDNAttributes := false
+ extensibleMatchingRule := ""
+ condition := ""
+
+ for newPos < len(filter) {
+ remainingFilter := filter[newPos:]
+ currentRune, currentWidth = utf8.DecodeRuneInString(remainingFilter)
+ if currentRune == ')' {
+ break
+ }
+ if currentRune == utf8.RuneError {
+ return packet, newPos, NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", newPos))
+ }
+
+ switch state {
+ case READING_ATTR:
+ switch {
+ // Extensible rule, with only DN-matching
+ case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:="):
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
+ extensibleDNAttributes = true
+ state = READING_CONDITION
+ newPos += 5
+
+ // Extensible rule, with DN-matching and a matching OID
+ case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:"):
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
+ extensibleDNAttributes = true
+ state = READING_EXTENSIBLE_MATCHING_RULE
+ newPos += 4
+
+ // Extensible rule, with attr only
+ case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
+ state = READING_CONDITION
+ newPos += 2
+
+ // Extensible rule, with no DN attribute matching
+ case currentRune == ':':
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
+ state = READING_EXTENSIBLE_MATCHING_RULE
+ newPos += 1
+
+ // Equality condition
+ case currentRune == '=':
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
+ state = READING_CONDITION
+ newPos += 1
+
+ // Greater-than or equal
+ case currentRune == '>' && strings.HasPrefix(remainingFilter, ">="):
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
+ state = READING_CONDITION
+ newPos += 2
+
+ // Less-than or equal
+ case currentRune == '<' && strings.HasPrefix(remainingFilter, "<="):
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
+ state = READING_CONDITION
+ newPos += 2
+
+ // Approx
+ case currentRune == '~' && strings.HasPrefix(remainingFilter, "~="):
+ packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterApproxMatch])
+ state = READING_CONDITION
+ newPos += 2
+
+ // Still reading the attribute name
+ default:
+ attribute += fmt.Sprintf("%c", currentRune)
+ newPos += currentWidth
+ }
+
+ case READING_EXTENSIBLE_MATCHING_RULE:
+ switch {
+
+ // Matching rule OID is done
+ case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
+ state = READING_CONDITION
+ newPos += 2
+
+ // Still reading the matching rule oid
+ default:
+ extensibleMatchingRule += fmt.Sprintf("%c", currentRune)
+ newPos += currentWidth
+ }
+
+ case READING_CONDITION:
+ // append to the condition
+ condition += fmt.Sprintf("%c", currentRune)
+ newPos += currentWidth
+ }
+ }
+
+ if newPos == len(filter) {
+ err = NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter"))
+ return packet, newPos, err
+ }
+ if packet == nil {
+ err = NewError(ErrorFilterCompile, errors.New("ldap: error parsing filter"))
+ return packet, newPos, err
+ }
+
+ switch {
+ case packet.Tag == FilterExtensibleMatch:
+ // MatchingRuleAssertion ::= SEQUENCE {
+ // matchingRule [1] MatchingRuleID OPTIONAL,
+ // type [2] AttributeDescription OPTIONAL,
+ // matchValue [3] AssertionValue,
+ // dnAttributes [4] BOOLEAN DEFAULT FALSE
+ // }
+
+ // Include the matching rule oid, if specified
+ if len(extensibleMatchingRule) > 0 {
+ packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchingRule, extensibleMatchingRule, MatchingRuleAssertionMap[MatchingRuleAssertionMatchingRule]))
+ }
+
+ // Include the attribute, if specified
+ if len(attribute) > 0 {
+ packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionType, attribute, MatchingRuleAssertionMap[MatchingRuleAssertionType]))
+ }
+
+ // Add the value (only required child)
+ encodedString, err := escapedStringToEncodedBytes(condition)
+ if err != nil {
+ return packet, newPos, err
+ }
+ packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchValue, encodedString, MatchingRuleAssertionMap[MatchingRuleAssertionMatchValue]))
+
+ // Defaults to false, so only include in the sequence if true
+ if extensibleDNAttributes {
+ packet.AppendChild(ber.NewBoolean(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionDNAttributes, extensibleDNAttributes, MatchingRuleAssertionMap[MatchingRuleAssertionDNAttributes]))
+ }
+
+ case packet.Tag == FilterEqualityMatch && condition == "*":
+ packet = ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterPresent, attribute, FilterMap[FilterPresent])
+ case packet.Tag == FilterEqualityMatch && strings.Contains(condition, "*"):
+ packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
+ packet.Tag = FilterSubstrings
+ packet.Description = FilterMap[uint64(packet.Tag)]
+ seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Substrings")
+ parts := strings.Split(condition, "*")
+ for i, part := range parts {
+ if part == "" {
+ continue
+ }
+ var tag ber.Tag
+ switch i {
+ case 0:
+ tag = FilterSubstringsInitial
+ case len(parts) - 1:
+ tag = FilterSubstringsFinal
+ default:
+ tag = FilterSubstringsAny
+ }
+ encodedString, err := escapedStringToEncodedBytes(part)
+ if err != nil {
+ return packet, newPos, err
+ }
+ seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, tag, encodedString, FilterSubstringsMap[uint64(tag)]))
+ }
+ packet.AppendChild(seq)
+ default:
+ encodedString, err := escapedStringToEncodedBytes(condition)
+ if err != nil {
+ return packet, newPos, err
+ }
+ packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
+ packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, encodedString, "Condition"))
+ }
+
+ newPos += currentWidth
+ return packet, newPos, err
+ }
+}
+
+// Convert from "ABC\xx\xx\xx" form to literal bytes for transport
+func escapedStringToEncodedBytes(escapedString string) (string, error) {
+ var buffer bytes.Buffer
+ i := 0
+ for i < len(escapedString) {
+ currentRune, currentWidth := utf8.DecodeRuneInString(escapedString[i:])
+ if currentRune == utf8.RuneError {
+ return "", NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", i))
+ }
+
+ // Check for escaped hex characters and convert them to their literal value for transport.
+ if currentRune == '\\' {
+ // http://tools.ietf.org/search/rfc4515
+ // \ (%x5C) is not a valid character unless it is followed by two HEX characters due to not
+ // being a member of UTF1SUBSET.
+ if i+2 > len(escapedString) {
+ return "", NewError(ErrorFilterCompile, errors.New("ldap: missing characters for escape in filter"))
+ }
+ if escByte, decodeErr := hexpac.DecodeString(escapedString[i+1 : i+3]); decodeErr != nil {
+ return "", NewError(ErrorFilterCompile, errors.New("ldap: invalid characters for escape in filter"))
+ } else {
+ buffer.WriteByte(escByte[0])
+ i += 2 // +1 from end of loop, so 3 total for \xx.
+ }
+ } else {
+ buffer.WriteRune(currentRune)
+ }
+
+ i += currentWidth
+ }
+ return buffer.String(), nil
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/filter_test.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/filter_test.go
new file mode 100644
index 000000000..ae1b79b0c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/filter_test.go
@@ -0,0 +1,248 @@
+package ldap_test
+
+import (
+ "strings"
+ "testing"
+
+ "gopkg.in/asn1-ber.v1"
+ "gopkg.in/ldap.v2"
+)
+
+type compileTest struct {
+ filterStr string
+
+ expectedFilter string
+ expectedType int
+ expectedErr string
+}
+
+var testFilters = []compileTest{
+ compileTest{
+ filterStr: "(&(sn=Miller)(givenName=Bob))",
+ expectedFilter: "(&(sn=Miller)(givenName=Bob))",
+ expectedType: ldap.FilterAnd,
+ },
+ compileTest{
+ filterStr: "(|(sn=Miller)(givenName=Bob))",
+ expectedFilter: "(|(sn=Miller)(givenName=Bob))",
+ expectedType: ldap.FilterOr,
+ },
+ compileTest{
+ filterStr: "(!(sn=Miller))",
+ expectedFilter: "(!(sn=Miller))",
+ expectedType: ldap.FilterNot,
+ },
+ compileTest{
+ filterStr: "(sn=Miller)",
+ expectedFilter: "(sn=Miller)",
+ expectedType: ldap.FilterEqualityMatch,
+ },
+ compileTest{
+ filterStr: "(sn=Mill*)",
+ expectedFilter: "(sn=Mill*)",
+ expectedType: ldap.FilterSubstrings,
+ },
+ compileTest{
+ filterStr: "(sn=*Mill)",
+ expectedFilter: "(sn=*Mill)",
+ expectedType: ldap.FilterSubstrings,
+ },
+ compileTest{
+ filterStr: "(sn=*Mill*)",
+ expectedFilter: "(sn=*Mill*)",
+ expectedType: ldap.FilterSubstrings,
+ },
+ compileTest{
+ filterStr: "(sn=*i*le*)",
+ expectedFilter: "(sn=*i*le*)",
+ expectedType: ldap.FilterSubstrings,
+ },
+ compileTest{
+ filterStr: "(sn=Mi*l*r)",
+ expectedFilter: "(sn=Mi*l*r)",
+ expectedType: ldap.FilterSubstrings,
+ },
+ // substring filters escape properly
+ compileTest{
+ filterStr: `(sn=Mi*함*r)`,
+ expectedFilter: `(sn=Mi*\ed\95\a8*r)`,
+ expectedType: ldap.FilterSubstrings,
+ },
+ // already escaped substring filters don't get double-escaped
+ compileTest{
+ filterStr: `(sn=Mi*\ed\95\a8*r)`,
+ expectedFilter: `(sn=Mi*\ed\95\a8*r)`,
+ expectedType: ldap.FilterSubstrings,
+ },
+ compileTest{
+ filterStr: "(sn=Mi*le*)",
+ expectedFilter: "(sn=Mi*le*)",
+ expectedType: ldap.FilterSubstrings,
+ },
+ compileTest{
+ filterStr: "(sn=*i*ler)",
+ expectedFilter: "(sn=*i*ler)",
+ expectedType: ldap.FilterSubstrings,
+ },
+ compileTest{
+ filterStr: "(sn>=Miller)",
+ expectedFilter: "(sn>=Miller)",
+ expectedType: ldap.FilterGreaterOrEqual,
+ },
+ compileTest{
+ filterStr: "(sn<=Miller)",
+ expectedFilter: "(sn<=Miller)",
+ expectedType: ldap.FilterLessOrEqual,
+ },
+ compileTest{
+ filterStr: "(sn=*)",
+ expectedFilter: "(sn=*)",
+ expectedType: ldap.FilterPresent,
+ },
+ compileTest{
+ filterStr: "(sn~=Miller)",
+ expectedFilter: "(sn~=Miller)",
+ expectedType: ldap.FilterApproxMatch,
+ },
+ compileTest{
+ filterStr: `(objectGUID='\fc\fe\a3\ab\f9\90N\aaGm\d5I~\d12)`,
+ expectedFilter: `(objectGUID='\fc\fe\a3\ab\f9\90N\aaGm\d5I~\d12)`,
+ expectedType: ldap.FilterEqualityMatch,
+ },
+ compileTest{
+ filterStr: `(objectGUID=абвгдеёжзийклмнопрÑтуфхцчшщъыьÑÑŽÑ)`,
+ expectedFilter: `(objectGUID=\d0\b0\d0\b1\d0\b2\d0\b3\d0\b4\d0\b5\d1\91\d0\b6\d0\b7\d0\b8\d0\b9\d0\ba\d0\bb\d0\bc\d0\bd\d0\be\d0\bf\d1\80\d1\81\d1\82\d1\83\d1\84\d1\85\d1\86\d1\87\d1\88\d1\89\d1\8a\d1\8b\d1\8c\d1\8d\d1\8e\d1\8f)`,
+ expectedType: ldap.FilterEqualityMatch,
+ },
+ compileTest{
+ filterStr: `(objectGUID=함수목ë¡)`,
+ expectedFilter: `(objectGUID=\ed\95\a8\ec\88\98\eb\aa\a9\eb\a1\9d)`,
+ expectedType: ldap.FilterEqualityMatch,
+ },
+ compileTest{
+ filterStr: `(objectGUID=`,
+ expectedFilter: ``,
+ expectedType: 0,
+ expectedErr: "unexpected end of filter",
+ },
+ compileTest{
+ filterStr: `(objectGUID=함수목ë¡`,
+ expectedFilter: ``,
+ expectedType: 0,
+ expectedErr: "unexpected end of filter",
+ },
+ compileTest{
+ filterStr: `(&(objectclass=inetorgperson)(cn=中文))`,
+ expectedFilter: `(&(objectclass=inetorgperson)(cn=\e4\b8\ad\e6\96\87))`,
+ expectedType: 0,
+ },
+ // attr extension
+ compileTest{
+ filterStr: `(memberOf:=foo)`,
+ expectedFilter: `(memberOf:=foo)`,
+ expectedType: ldap.FilterExtensibleMatch,
+ },
+ // attr+named matching rule extension
+ compileTest{
+ filterStr: `(memberOf:test:=foo)`,
+ expectedFilter: `(memberOf:test:=foo)`,
+ expectedType: ldap.FilterExtensibleMatch,
+ },
+ // attr+oid matching rule extension
+ compileTest{
+ filterStr: `(cn:1.2.3.4.5:=Fred Flintstone)`,
+ expectedFilter: `(cn:1.2.3.4.5:=Fred Flintstone)`,
+ expectedType: ldap.FilterExtensibleMatch,
+ },
+ // attr+dn+oid matching rule extension
+ compileTest{
+ filterStr: `(sn:dn:2.4.6.8.10:=Barney Rubble)`,
+ expectedFilter: `(sn:dn:2.4.6.8.10:=Barney Rubble)`,
+ expectedType: ldap.FilterExtensibleMatch,
+ },
+ // attr+dn extension
+ compileTest{
+ filterStr: `(o:dn:=Ace Industry)`,
+ expectedFilter: `(o:dn:=Ace Industry)`,
+ expectedType: ldap.FilterExtensibleMatch,
+ },
+ // dn extension
+ compileTest{
+ filterStr: `(:dn:2.4.6.8.10:=Dino)`,
+ expectedFilter: `(:dn:2.4.6.8.10:=Dino)`,
+ expectedType: ldap.FilterExtensibleMatch,
+ },
+ compileTest{
+ filterStr: `(memberOf:1.2.840.113556.1.4.1941:=CN=User1,OU=blah,DC=mydomain,DC=net)`,
+ expectedFilter: `(memberOf:1.2.840.113556.1.4.1941:=CN=User1,OU=blah,DC=mydomain,DC=net)`,
+ expectedType: ldap.FilterExtensibleMatch,
+ },
+
+ // compileTest{ filterStr: "()", filterType: FilterExtensibleMatch },
+}
+
+var testInvalidFilters = []string{
+ `(objectGUID=\zz)`,
+ `(objectGUID=\a)`,
+}
+
+func TestFilter(t *testing.T) {
+ // Test Compiler and Decompiler
+ for _, i := range testFilters {
+ filter, err := ldap.CompileFilter(i.filterStr)
+ if err != nil {
+ if i.expectedErr == "" || !strings.Contains(err.Error(), i.expectedErr) {
+ t.Errorf("Problem compiling '%s' - '%v' (expected error to contain '%v')", i.filterStr, err, i.expectedErr)
+ }
+ } else if filter.Tag != ber.Tag(i.expectedType) {
+ t.Errorf("%q Expected %q got %q", i.filterStr, ldap.FilterMap[uint64(i.expectedType)], ldap.FilterMap[uint64(filter.Tag)])
+ } else {
+ o, err := ldap.DecompileFilter(filter)
+ if err != nil {
+ t.Errorf("Problem compiling %s - %s", i.filterStr, err.Error())
+ } else if i.expectedFilter != o {
+ t.Errorf("%q expected, got %q", i.expectedFilter, o)
+ }
+ }
+ }
+}
+
+func TestInvalidFilter(t *testing.T) {
+ for _, filterStr := range testInvalidFilters {
+ if _, err := ldap.CompileFilter(filterStr); err == nil {
+ t.Errorf("Problem compiling %s - expected err", filterStr)
+ }
+ }
+}
+
+func BenchmarkFilterCompile(b *testing.B) {
+ b.StopTimer()
+ filters := make([]string, len(testFilters))
+
+ // Test Compiler and Decompiler
+ for idx, i := range testFilters {
+ filters[idx] = i.filterStr
+ }
+
+ maxIdx := len(filters)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ ldap.CompileFilter(filters[i%maxIdx])
+ }
+}
+
+func BenchmarkFilterDecompile(b *testing.B) {
+ b.StopTimer()
+ filters := make([]*ber.Packet, len(testFilters))
+
+ // Test Compiler and Decompiler
+ for idx, i := range testFilters {
+ filters[idx], _ = ldap.CompileFilter(i.filterStr)
+ }
+
+ maxIdx := len(filters)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ ldap.DecompileFilter(filters[i%maxIdx])
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/ldap.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/ldap.go
new file mode 100644
index 000000000..1620aaea6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/ldap.go
@@ -0,0 +1,286 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ldap
+
+import (
+ "errors"
+ "io/ioutil"
+ "os"
+
+ ber "gopkg.in/asn1-ber.v1"
+)
+
+// LDAP Application Codes
+const (
+ ApplicationBindRequest = 0
+ ApplicationBindResponse = 1
+ ApplicationUnbindRequest = 2
+ ApplicationSearchRequest = 3
+ ApplicationSearchResultEntry = 4
+ ApplicationSearchResultDone = 5
+ ApplicationModifyRequest = 6
+ ApplicationModifyResponse = 7
+ ApplicationAddRequest = 8
+ ApplicationAddResponse = 9
+ ApplicationDelRequest = 10
+ ApplicationDelResponse = 11
+ ApplicationModifyDNRequest = 12
+ ApplicationModifyDNResponse = 13
+ ApplicationCompareRequest = 14
+ ApplicationCompareResponse = 15
+ ApplicationAbandonRequest = 16
+ ApplicationSearchResultReference = 19
+ ApplicationExtendedRequest = 23
+ ApplicationExtendedResponse = 24
+)
+
+var ApplicationMap = map[uint8]string{
+ ApplicationBindRequest: "Bind Request",
+ ApplicationBindResponse: "Bind Response",
+ ApplicationUnbindRequest: "Unbind Request",
+ ApplicationSearchRequest: "Search Request",
+ ApplicationSearchResultEntry: "Search Result Entry",
+ ApplicationSearchResultDone: "Search Result Done",
+ ApplicationModifyRequest: "Modify Request",
+ ApplicationModifyResponse: "Modify Response",
+ ApplicationAddRequest: "Add Request",
+ ApplicationAddResponse: "Add Response",
+ ApplicationDelRequest: "Del Request",
+ ApplicationDelResponse: "Del Response",
+ ApplicationModifyDNRequest: "Modify DN Request",
+ ApplicationModifyDNResponse: "Modify DN Response",
+ ApplicationCompareRequest: "Compare Request",
+ ApplicationCompareResponse: "Compare Response",
+ ApplicationAbandonRequest: "Abandon Request",
+ ApplicationSearchResultReference: "Search Result Reference",
+ ApplicationExtendedRequest: "Extended Request",
+ ApplicationExtendedResponse: "Extended Response",
+}
+
+// Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10)
+const (
+ BeheraPasswordExpired = 0
+ BeheraAccountLocked = 1
+ BeheraChangeAfterReset = 2
+ BeheraPasswordModNotAllowed = 3
+ BeheraMustSupplyOldPassword = 4
+ BeheraInsufficientPasswordQuality = 5
+ BeheraPasswordTooShort = 6
+ BeheraPasswordTooYoung = 7
+ BeheraPasswordInHistory = 8
+)
+
+var BeheraPasswordPolicyErrorMap = map[int8]string{
+ BeheraPasswordExpired: "Password expired",
+ BeheraAccountLocked: "Account locked",
+ BeheraChangeAfterReset: "Password must be changed",
+ BeheraPasswordModNotAllowed: "Policy prevents password modification",
+ BeheraMustSupplyOldPassword: "Policy requires old password in order to change password",
+ BeheraInsufficientPasswordQuality: "Password fails quality checks",
+ BeheraPasswordTooShort: "Password is too short for policy",
+ BeheraPasswordTooYoung: "Password has been changed too recently",
+ BeheraPasswordInHistory: "New password is in list of old passwords",
+}
+
+// Adds descriptions to an LDAP Response packet for debugging
+func addLDAPDescriptions(packet *ber.Packet) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = NewError(ErrorDebugging, errors.New("ldap: cannot process packet to add descriptions"))
+ }
+ }()
+ packet.Description = "LDAP Response"
+ packet.Children[0].Description = "Message ID"
+
+ application := uint8(packet.Children[1].Tag)
+ packet.Children[1].Description = ApplicationMap[application]
+
+ switch application {
+ case ApplicationBindRequest:
+ addRequestDescriptions(packet)
+ case ApplicationBindResponse:
+ addDefaultLDAPResponseDescriptions(packet)
+ case ApplicationUnbindRequest:
+ addRequestDescriptions(packet)
+ case ApplicationSearchRequest:
+ addRequestDescriptions(packet)
+ case ApplicationSearchResultEntry:
+ packet.Children[1].Children[0].Description = "Object Name"
+ packet.Children[1].Children[1].Description = "Attributes"
+ for _, child := range packet.Children[1].Children[1].Children {
+ child.Description = "Attribute"
+ child.Children[0].Description = "Attribute Name"
+ child.Children[1].Description = "Attribute Values"
+ for _, grandchild := range child.Children[1].Children {
+ grandchild.Description = "Attribute Value"
+ }
+ }
+ if len(packet.Children) == 3 {
+ addControlDescriptions(packet.Children[2])
+ }
+ case ApplicationSearchResultDone:
+ addDefaultLDAPResponseDescriptions(packet)
+ case ApplicationModifyRequest:
+ addRequestDescriptions(packet)
+ case ApplicationModifyResponse:
+ case ApplicationAddRequest:
+ addRequestDescriptions(packet)
+ case ApplicationAddResponse:
+ case ApplicationDelRequest:
+ addRequestDescriptions(packet)
+ case ApplicationDelResponse:
+ case ApplicationModifyDNRequest:
+ addRequestDescriptions(packet)
+ case ApplicationModifyDNResponse:
+ case ApplicationCompareRequest:
+ addRequestDescriptions(packet)
+ case ApplicationCompareResponse:
+ case ApplicationAbandonRequest:
+ addRequestDescriptions(packet)
+ case ApplicationSearchResultReference:
+ case ApplicationExtendedRequest:
+ addRequestDescriptions(packet)
+ case ApplicationExtendedResponse:
+ }
+
+ return nil
+}
+
+func addControlDescriptions(packet *ber.Packet) {
+ packet.Description = "Controls"
+ for _, child := range packet.Children {
+ child.Description = "Control"
+ child.Children[0].Description = "Control Type (" + ControlTypeMap[child.Children[0].Value.(string)] + ")"
+ value := child.Children[1]
+ if len(child.Children) == 3 {
+ child.Children[1].Description = "Criticality"
+ value = child.Children[2]
+ }
+ value.Description = "Control Value"
+
+ switch child.Children[0].Value.(string) {
+ case ControlTypePaging:
+ value.Description += " (Paging)"
+ if value.Value != nil {
+ valueChildren := ber.DecodePacket(value.Data.Bytes())
+ value.Data.Truncate(0)
+ value.Value = nil
+ valueChildren.Children[1].Value = valueChildren.Children[1].Data.Bytes()
+ value.AppendChild(valueChildren)
+ }
+ value.Children[0].Description = "Real Search Control Value"
+ value.Children[0].Children[0].Description = "Paging Size"
+ value.Children[0].Children[1].Description = "Cookie"
+
+ case ControlTypeBeheraPasswordPolicy:
+ value.Description += " (Password Policy - Behera Draft)"
+ if value.Value != nil {
+ valueChildren := ber.DecodePacket(value.Data.Bytes())
+ value.Data.Truncate(0)
+ value.Value = nil
+ value.AppendChild(valueChildren)
+ }
+ sequence := value.Children[0]
+ for _, child := range sequence.Children {
+ if child.Tag == 0 {
+ //Warning
+ child := child.Children[0]
+ packet := ber.DecodePacket(child.Data.Bytes())
+ val, ok := packet.Value.(int64)
+ if ok {
+ if child.Tag == 0 {
+ //timeBeforeExpiration
+ value.Description += " (TimeBeforeExpiration)"
+ child.Value = val
+ } else if child.Tag == 1 {
+ //graceAuthNsRemaining
+ value.Description += " (GraceAuthNsRemaining)"
+ child.Value = val
+ }
+ }
+ } else if child.Tag == 1 {
+ // Error
+ packet := ber.DecodePacket(child.Data.Bytes())
+ val, ok := packet.Value.(int8)
+ if !ok {
+ val = -1
+ }
+ child.Description = "Error"
+ child.Value = val
+ }
+ }
+ }
+ }
+}
+
+func addRequestDescriptions(packet *ber.Packet) {
+ packet.Description = "LDAP Request"
+ packet.Children[0].Description = "Message ID"
+ packet.Children[1].Description = ApplicationMap[uint8(packet.Children[1].Tag)]
+ if len(packet.Children) == 3 {
+ addControlDescriptions(packet.Children[2])
+ }
+}
+
+func addDefaultLDAPResponseDescriptions(packet *ber.Packet) {
+ resultCode, _ := getLDAPResultCode(packet)
+ packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[resultCode] + ")"
+ packet.Children[1].Children[1].Description = "Matched DN"
+ packet.Children[1].Children[2].Description = "Error Message"
+ if len(packet.Children[1].Children) > 3 {
+ packet.Children[1].Children[3].Description = "Referral"
+ }
+ if len(packet.Children) == 3 {
+ addControlDescriptions(packet.Children[2])
+ }
+}
+
+func DebugBinaryFile(fileName string) error {
+ file, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ return NewError(ErrorDebugging, err)
+ }
+ ber.PrintBytes(os.Stdout, file, "")
+ packet := ber.DecodePacket(file)
+ addLDAPDescriptions(packet)
+ ber.PrintPacket(packet)
+
+ return nil
+}
+
+var hex = "0123456789abcdef"
+
+func mustEscape(c byte) bool {
+ return c > 0x7f || c == '(' || c == ')' || c == '\\' || c == '*' || c == 0
+}
+
+// EscapeFilter escapes from the provided LDAP filter string the special
+// characters in the set `()*\` and those out of the range 0 < c < 0x80,
+// as defined in RFC4515.
+func EscapeFilter(filter string) string {
+ escape := 0
+ for i := 0; i < len(filter); i++ {
+ if mustEscape(filter[i]) {
+ escape++
+ }
+ }
+ if escape == 0 {
+ return filter
+ }
+ buf := make([]byte, len(filter)+escape*2)
+ for i, j := 0, 0; i < len(filter); i++ {
+ c := filter[i]
+ if mustEscape(c) {
+ buf[j+0] = '\\'
+ buf[j+1] = hex[c>>4]
+ buf[j+2] = hex[c&0xf]
+ j += 3
+ } else {
+ buf[j] = c
+ j++
+ }
+ }
+ return string(buf)
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/ldap_test.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/ldap_test.go
new file mode 100644
index 000000000..63292747f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/ldap_test.go
@@ -0,0 +1,249 @@
+package ldap_test
+
+import (
+ "crypto/tls"
+ "fmt"
+ "testing"
+
+ "gopkg.in/ldap.v2"
+)
+
+var ldapServer = "ldap.itd.umich.edu"
+var ldapPort = uint16(389)
+var ldapTLSPort = uint16(636)
+var baseDN = "dc=umich,dc=edu"
+var filter = []string{
+ "(cn=cis-fac)",
+ "(&(owner=*)(cn=cis-fac))",
+ "(&(objectclass=rfc822mailgroup)(cn=*Computer*))",
+ "(&(objectclass=rfc822mailgroup)(cn=*Mathematics*))"}
+var attributes = []string{
+ "cn",
+ "description"}
+
+func TestDial(t *testing.T) {
+ fmt.Printf("TestDial: starting...\n")
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+ defer l.Close()
+ fmt.Printf("TestDial: finished...\n")
+}
+
+func TestDialTLS(t *testing.T) {
+ fmt.Printf("TestDialTLS: starting...\n")
+ l, err := ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapTLSPort), &tls.Config{InsecureSkipVerify: true})
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+ defer l.Close()
+ fmt.Printf("TestDialTLS: finished...\n")
+}
+
+func TestStartTLS(t *testing.T) {
+ fmt.Printf("TestStartTLS: starting...\n")
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+ err = l.StartTLS(&tls.Config{InsecureSkipVerify: true})
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+ fmt.Printf("TestStartTLS: finished...\n")
+}
+
+func TestSearch(t *testing.T) {
+ fmt.Printf("TestSearch: starting...\n")
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+ defer l.Close()
+
+ searchRequest := ldap.NewSearchRequest(
+ baseDN,
+ ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
+ filter[0],
+ attributes,
+ nil)
+
+ sr, err := l.Search(searchRequest)
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+
+ fmt.Printf("TestSearch: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries))
+}
+
+func TestSearchStartTLS(t *testing.T) {
+ fmt.Printf("TestSearchStartTLS: starting...\n")
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+ defer l.Close()
+
+ searchRequest := ldap.NewSearchRequest(
+ baseDN,
+ ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
+ filter[0],
+ attributes,
+ nil)
+
+ sr, err := l.Search(searchRequest)
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+
+ fmt.Printf("TestSearchStartTLS: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries))
+
+ fmt.Printf("TestSearchStartTLS: upgrading with startTLS\n")
+ err = l.StartTLS(&tls.Config{InsecureSkipVerify: true})
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+
+ sr, err = l.Search(searchRequest)
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+
+ fmt.Printf("TestSearchStartTLS: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries))
+}
+
+func TestSearchWithPaging(t *testing.T) {
+ fmt.Printf("TestSearchWithPaging: starting...\n")
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+ defer l.Close()
+
+ err = l.Bind("", "")
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+
+ searchRequest := ldap.NewSearchRequest(
+ baseDN,
+ ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
+ filter[2],
+ attributes,
+ nil)
+ sr, err := l.SearchWithPaging(searchRequest, 5)
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+
+ fmt.Printf("TestSearchWithPaging: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries))
+}
+
+func searchGoroutine(t *testing.T, l *ldap.Conn, results chan *ldap.SearchResult, i int) {
+ searchRequest := ldap.NewSearchRequest(
+ baseDN,
+ ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
+ filter[i],
+ attributes,
+ nil)
+ sr, err := l.Search(searchRequest)
+ if err != nil {
+ t.Errorf(err.Error())
+ results <- nil
+ return
+ }
+ results <- sr
+}
+
+func testMultiGoroutineSearch(t *testing.T, TLS bool, startTLS bool) {
+ fmt.Printf("TestMultiGoroutineSearch: starting...\n")
+ var l *ldap.Conn
+ var err error
+ if TLS {
+ l, err = ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapTLSPort), &tls.Config{InsecureSkipVerify: true})
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+ defer l.Close()
+ } else {
+ l, err = ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+ if startTLS {
+ fmt.Printf("TestMultiGoroutineSearch: using StartTLS...\n")
+ err := l.StartTLS(&tls.Config{InsecureSkipVerify: true})
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+
+ }
+ }
+
+ results := make([]chan *ldap.SearchResult, len(filter))
+ for i := range filter {
+ results[i] = make(chan *ldap.SearchResult)
+ go searchGoroutine(t, l, results[i], i)
+ }
+ for i := range filter {
+ sr := <-results[i]
+ if sr == nil {
+ t.Errorf("Did not receive results from goroutine for %q", filter[i])
+ } else {
+ fmt.Printf("TestMultiGoroutineSearch(%d): %s -> num of entries = %d\n", i, filter[i], len(sr.Entries))
+ }
+ }
+}
+
+func TestMultiGoroutineSearch(t *testing.T) {
+ testMultiGoroutineSearch(t, false, false)
+ testMultiGoroutineSearch(t, true, true)
+ testMultiGoroutineSearch(t, false, true)
+}
+
+func TestEscapeFilter(t *testing.T) {
+ if got, want := ldap.EscapeFilter("a\x00b(c)d*e\\f"), `a\00b\28c\29d\2ae\5cf`; got != want {
+ t.Errorf("Got %s, expected %s", want, got)
+ }
+ if got, want := ldap.EscapeFilter("LuÄić"), `Lu\c4\8di\c4\87`; got != want {
+ t.Errorf("Got %s, expected %s", want, got)
+ }
+}
+
+func TestCompare(t *testing.T) {
+ fmt.Printf("TestCompare: starting...\n")
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+ defer l.Close()
+
+ dn := "cn=math mich,ou=User Groups,ou=Groups,dc=umich,dc=edu"
+ attribute := "cn"
+ value := "math mich"
+
+ sr, err := l.Compare(dn, attribute, value)
+ if err != nil {
+ t.Errorf(err.Error())
+ return
+ }
+
+ fmt.Printf("TestCompare: -> %v\n", sr)
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/modify.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/modify.go
new file mode 100644
index 000000000..4372a19dc
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/modify.go
@@ -0,0 +1,156 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// File contains Modify functionality
+//
+// https://tools.ietf.org/html/rfc4511
+//
+// ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+// object LDAPDN,
+// changes SEQUENCE OF change SEQUENCE {
+// operation ENUMERATED {
+// add (0),
+// delete (1),
+// replace (2),
+// ... },
+// modification PartialAttribute } }
+//
+// PartialAttribute ::= SEQUENCE {
+// type AttributeDescription,
+// vals SET OF value AttributeValue }
+//
+// AttributeDescription ::= LDAPString
+// -- Constrained to <attributedescription>
+// -- [RFC4512]
+//
+// AttributeValue ::= OCTET STRING
+//
+
+package ldap
+
+import (
+ "errors"
+ "log"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+const (
+ AddAttribute = 0
+ DeleteAttribute = 1
+ ReplaceAttribute = 2
+)
+
+type PartialAttribute struct {
+ attrType string
+ attrVals []string
+}
+
+func (p *PartialAttribute) encode() *ber.Packet {
+ seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "PartialAttribute")
+ seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, p.attrType, "Type"))
+ set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
+ for _, value := range p.attrVals {
+ set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
+ }
+ seq.AppendChild(set)
+ return seq
+}
+
+type ModifyRequest struct {
+ dn string
+ addAttributes []PartialAttribute
+ deleteAttributes []PartialAttribute
+ replaceAttributes []PartialAttribute
+}
+
+func (m *ModifyRequest) Add(attrType string, attrVals []string) {
+ m.addAttributes = append(m.addAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
+}
+
+func (m *ModifyRequest) Delete(attrType string, attrVals []string) {
+ m.deleteAttributes = append(m.deleteAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
+}
+
+func (m *ModifyRequest) Replace(attrType string, attrVals []string) {
+ m.replaceAttributes = append(m.replaceAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
+}
+
+func (m ModifyRequest) encode() *ber.Packet {
+ request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyRequest, nil, "Modify Request")
+ request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.dn, "DN"))
+ changes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Changes")
+ for _, attribute := range m.addAttributes {
+ change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
+ change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(AddAttribute), "Operation"))
+ change.AppendChild(attribute.encode())
+ changes.AppendChild(change)
+ }
+ for _, attribute := range m.deleteAttributes {
+ change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
+ change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(DeleteAttribute), "Operation"))
+ change.AppendChild(attribute.encode())
+ changes.AppendChild(change)
+ }
+ for _, attribute := range m.replaceAttributes {
+ change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
+ change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(ReplaceAttribute), "Operation"))
+ change.AppendChild(attribute.encode())
+ changes.AppendChild(change)
+ }
+ request.AppendChild(changes)
+ return request
+}
+
+func NewModifyRequest(
+ dn string,
+) *ModifyRequest {
+ return &ModifyRequest{
+ dn: dn,
+ }
+}
+
+func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
+ messageID := l.nextMessageID()
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(modifyRequest.encode())
+
+ l.Debug.PrintPacket(packet)
+
+ channel, err := l.sendMessage(packet)
+ if err != nil {
+ return err
+ }
+ if channel == nil {
+ return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
+ }
+ defer l.finishMessage(messageID)
+
+ l.Debug.Printf("%d: waiting for response", messageID)
+ packet = <-channel
+ l.Debug.Printf("%d: got response %p", messageID, packet)
+ if packet == nil {
+ return NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
+ }
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ return err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ if packet.Children[1].Tag == ApplicationModifyResponse {
+ resultCode, resultDescription := getLDAPResultCode(packet)
+ if resultCode != 0 {
+ return NewError(resultCode, errors.New(resultDescription))
+ }
+ } else {
+ log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
+ }
+
+ l.Debug.Printf("%d: returning", messageID)
+ return nil
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/passwdmodify.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/passwdmodify.go
new file mode 100644
index 000000000..508b11ed7
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/passwdmodify.go
@@ -0,0 +1,137 @@
+// This file contains the password modify extended operation as specified in rfc 3062
+//
+// https://tools.ietf.org/html/rfc3062
+//
+
+package ldap
+
+import (
+ "errors"
+ "fmt"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+const (
+ passwordModifyOID = "1.3.6.1.4.1.4203.1.11.1"
+)
+
+type PasswordModifyRequest struct {
+ UserIdentity string
+ OldPassword string
+ NewPassword string
+}
+
+type PasswordModifyResult struct {
+ GeneratedPassword string
+}
+
+func (r *PasswordModifyRequest) encode() (*ber.Packet, error) {
+ request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationExtendedRequest, nil, "Password Modify Extended Operation")
+ request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, passwordModifyOID, "Extended Request Name: Password Modify OID"))
+ extendedRequestValue := ber.Encode(ber.ClassContext, ber.TypePrimitive, 1, nil, "Extended Request Value: Password Modify Request")
+ passwordModifyRequestValue := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Password Modify Request")
+ if r.UserIdentity != "" {
+ passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, r.UserIdentity, "User Identity"))
+ }
+ if r.OldPassword != "" {
+ passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 1, r.OldPassword, "Old Password"))
+ }
+ if r.NewPassword != "" {
+ passwordModifyRequestValue.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 2, r.NewPassword, "New Password"))
+ }
+
+ extendedRequestValue.AppendChild(passwordModifyRequestValue)
+ request.AppendChild(extendedRequestValue)
+
+ return request, nil
+}
+
+// Create a new PasswordModifyRequest
+//
+// According to the RFC 3602:
+// userIdentity is a string representing the user associated with the request.
+// This string may or may not be an LDAPDN (RFC 2253).
+// If userIdentity is empty then the operation will act on the user associated
+// with the session.
+//
+// oldPassword is the current user's password, it can be empty or it can be
+// needed depending on the session user access rights (usually an administrator
+// can change a user's password without knowing the current one) and the
+// password policy (see pwdSafeModify password policy's attribute)
+//
+// newPassword is the desired user's password. If empty the server can return
+// an error or generate a new password that will be available in the
+// PasswordModifyResult.GeneratedPassword
+//
+func NewPasswordModifyRequest(userIdentity string, oldPassword string, newPassword string) *PasswordModifyRequest {
+ return &PasswordModifyRequest{
+ UserIdentity: userIdentity,
+ OldPassword: oldPassword,
+ NewPassword: newPassword,
+ }
+}
+
+func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error) {
+ messageID := l.nextMessageID()
+
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+
+ encodedPasswordModifyRequest, err := passwordModifyRequest.encode()
+ if err != nil {
+ return nil, err
+ }
+ packet.AppendChild(encodedPasswordModifyRequest)
+
+ l.Debug.PrintPacket(packet)
+
+ channel, err := l.sendMessage(packet)
+ if err != nil {
+ return nil, err
+ }
+ if channel == nil {
+ return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
+ }
+ defer l.finishMessage(messageID)
+
+ result := &PasswordModifyResult{}
+
+ l.Debug.Printf("%d: waiting for response", messageID)
+ packet = <-channel
+ l.Debug.Printf("%d: got response %p", messageID, packet)
+
+ if packet == nil {
+ return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
+ }
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ return nil, err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ if packet.Children[1].Tag == ApplicationExtendedResponse {
+ resultCode, resultDescription := getLDAPResultCode(packet)
+ if resultCode != 0 {
+ return nil, NewError(resultCode, errors.New(resultDescription))
+ }
+ } else {
+ return nil, NewError(ErrorUnexpectedResponse, fmt.Errorf("Unexpected Response: %d", packet.Children[1].Tag))
+ }
+
+ extendedResponse := packet.Children[1]
+ for _, child := range extendedResponse.Children {
+ if child.Tag == 11 {
+ passwordModifyReponseValue := ber.DecodePacket(child.Data.Bytes())
+ if len(passwordModifyReponseValue.Children) == 1 {
+ if passwordModifyReponseValue.Children[0].Tag == 0 {
+ result.GeneratedPassword = ber.DecodeString(passwordModifyReponseValue.Children[0].Data.Bytes())
+ }
+ }
+ }
+ }
+
+ return result, nil
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/search.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/search.go
new file mode 100644
index 000000000..f63c9fb02
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/search.go
@@ -0,0 +1,403 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// File contains Search functionality
+//
+// https://tools.ietf.org/html/rfc4511
+//
+// SearchRequest ::= [APPLICATION 3] SEQUENCE {
+// baseObject LDAPDN,
+// scope ENUMERATED {
+// baseObject (0),
+// singleLevel (1),
+// wholeSubtree (2),
+// ... },
+// derefAliases ENUMERATED {
+// neverDerefAliases (0),
+// derefInSearching (1),
+// derefFindingBaseObj (2),
+// derefAlways (3) },
+// sizeLimit INTEGER (0 .. maxInt),
+// timeLimit INTEGER (0 .. maxInt),
+// typesOnly BOOLEAN,
+// filter Filter,
+// attributes AttributeSelection }
+//
+// AttributeSelection ::= SEQUENCE OF selector LDAPString
+// -- The LDAPString is constrained to
+// -- <attributeSelector> in Section 4.5.1.8
+//
+// Filter ::= CHOICE {
+// and [0] SET SIZE (1..MAX) OF filter Filter,
+// or [1] SET SIZE (1..MAX) OF filter Filter,
+// not [2] Filter,
+// equalityMatch [3] AttributeValueAssertion,
+// substrings [4] SubstringFilter,
+// greaterOrEqual [5] AttributeValueAssertion,
+// lessOrEqual [6] AttributeValueAssertion,
+// present [7] AttributeDescription,
+// approxMatch [8] AttributeValueAssertion,
+// extensibleMatch [9] MatchingRuleAssertion,
+// ... }
+//
+// SubstringFilter ::= SEQUENCE {
+// type AttributeDescription,
+// substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE {
+// initial [0] AssertionValue, -- can occur at most once
+// any [1] AssertionValue,
+// final [2] AssertionValue } -- can occur at most once
+// }
+//
+// MatchingRuleAssertion ::= SEQUENCE {
+// matchingRule [1] MatchingRuleId OPTIONAL,
+// type [2] AttributeDescription OPTIONAL,
+// matchValue [3] AssertionValue,
+// dnAttributes [4] BOOLEAN DEFAULT FALSE }
+//
+//
+
+package ldap
+
+import (
+ "errors"
+ "fmt"
+ "sort"
+ "strings"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+const (
+ ScopeBaseObject = 0
+ ScopeSingleLevel = 1
+ ScopeWholeSubtree = 2
+)
+
+var ScopeMap = map[int]string{
+ ScopeBaseObject: "Base Object",
+ ScopeSingleLevel: "Single Level",
+ ScopeWholeSubtree: "Whole Subtree",
+}
+
+const (
+ NeverDerefAliases = 0
+ DerefInSearching = 1
+ DerefFindingBaseObj = 2
+ DerefAlways = 3
+)
+
+var DerefMap = map[int]string{
+ NeverDerefAliases: "NeverDerefAliases",
+ DerefInSearching: "DerefInSearching",
+ DerefFindingBaseObj: "DerefFindingBaseObj",
+ DerefAlways: "DerefAlways",
+}
+
+// NewEntry returns an Entry object with the specified distinguished name and attribute key-value pairs.
+// The map of attributes is accessed in alphabetical order of the keys in order to ensure that, for the
+// same input map of attributes, the output entry will contain the same order of attributes
+func NewEntry(dn string, attributes map[string][]string) *Entry {
+ var attributeNames []string
+ for attributeName := range attributes {
+ attributeNames = append(attributeNames, attributeName)
+ }
+ sort.Strings(attributeNames)
+
+ var encodedAttributes []*EntryAttribute
+ for _, attributeName := range attributeNames {
+ encodedAttributes = append(encodedAttributes, NewEntryAttribute(attributeName, attributes[attributeName]))
+ }
+ return &Entry{
+ DN: dn,
+ Attributes: encodedAttributes,
+ }
+}
+
+type Entry struct {
+ DN string
+ Attributes []*EntryAttribute
+}
+
+func (e *Entry) GetAttributeValues(attribute string) []string {
+ for _, attr := range e.Attributes {
+ if attr.Name == attribute {
+ return attr.Values
+ }
+ }
+ return []string{}
+}
+
+func (e *Entry) GetRawAttributeValues(attribute string) [][]byte {
+ for _, attr := range e.Attributes {
+ if attr.Name == attribute {
+ return attr.ByteValues
+ }
+ }
+ return [][]byte{}
+}
+
+func (e *Entry) GetAttributeValue(attribute string) string {
+ values := e.GetAttributeValues(attribute)
+ if len(values) == 0 {
+ return ""
+ }
+ return values[0]
+}
+
+func (e *Entry) GetRawAttributeValue(attribute string) []byte {
+ values := e.GetRawAttributeValues(attribute)
+ if len(values) == 0 {
+ return []byte{}
+ }
+ return values[0]
+}
+
+func (e *Entry) Print() {
+ fmt.Printf("DN: %s\n", e.DN)
+ for _, attr := range e.Attributes {
+ attr.Print()
+ }
+}
+
+func (e *Entry) PrettyPrint(indent int) {
+ fmt.Printf("%sDN: %s\n", strings.Repeat(" ", indent), e.DN)
+ for _, attr := range e.Attributes {
+ attr.PrettyPrint(indent + 2)
+ }
+}
+
+// NewEntryAttribute returns a new EntryAttribute with the desired key-value pair
+func NewEntryAttribute(name string, values []string) *EntryAttribute {
+ var bytes [][]byte
+ for _, value := range values {
+ bytes = append(bytes, []byte(value))
+ }
+ return &EntryAttribute{
+ Name: name,
+ Values: values,
+ ByteValues: bytes,
+ }
+}
+
+type EntryAttribute struct {
+ Name string
+ Values []string
+ ByteValues [][]byte
+}
+
+func (e *EntryAttribute) Print() {
+ fmt.Printf("%s: %s\n", e.Name, e.Values)
+}
+
+func (e *EntryAttribute) PrettyPrint(indent int) {
+ fmt.Printf("%s%s: %s\n", strings.Repeat(" ", indent), e.Name, e.Values)
+}
+
+type SearchResult struct {
+ Entries []*Entry
+ Referrals []string
+ Controls []Control
+}
+
+func (s *SearchResult) Print() {
+ for _, entry := range s.Entries {
+ entry.Print()
+ }
+}
+
+func (s *SearchResult) PrettyPrint(indent int) {
+ for _, entry := range s.Entries {
+ entry.PrettyPrint(indent)
+ }
+}
+
+type SearchRequest struct {
+ BaseDN string
+ Scope int
+ DerefAliases int
+ SizeLimit int
+ TimeLimit int
+ TypesOnly bool
+ Filter string
+ Attributes []string
+ Controls []Control
+}
+
+func (s *SearchRequest) encode() (*ber.Packet, error) {
+ request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationSearchRequest, nil, "Search Request")
+ request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, s.BaseDN, "Base DN"))
+ request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(s.Scope), "Scope"))
+ request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(s.DerefAliases), "Deref Aliases"))
+ request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(s.SizeLimit), "Size Limit"))
+ request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(s.TimeLimit), "Time Limit"))
+ request.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, s.TypesOnly, "Types Only"))
+ // compile and encode filter
+ filterPacket, err := CompileFilter(s.Filter)
+ if err != nil {
+ return nil, err
+ }
+ request.AppendChild(filterPacket)
+ // encode attributes
+ attributesPacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
+ for _, attribute := range s.Attributes {
+ attributesPacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
+ }
+ request.AppendChild(attributesPacket)
+ return request, nil
+}
+
+func NewSearchRequest(
+ BaseDN string,
+ Scope, DerefAliases, SizeLimit, TimeLimit int,
+ TypesOnly bool,
+ Filter string,
+ Attributes []string,
+ Controls []Control,
+) *SearchRequest {
+ return &SearchRequest{
+ BaseDN: BaseDN,
+ Scope: Scope,
+ DerefAliases: DerefAliases,
+ SizeLimit: SizeLimit,
+ TimeLimit: TimeLimit,
+ TypesOnly: TypesOnly,
+ Filter: Filter,
+ Attributes: Attributes,
+ Controls: Controls,
+ }
+}
+
+func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error) {
+ if searchRequest.Controls == nil {
+ searchRequest.Controls = make([]Control, 0)
+ }
+
+ pagingControl := NewControlPaging(pagingSize)
+ searchRequest.Controls = append(searchRequest.Controls, pagingControl)
+ searchResult := new(SearchResult)
+ for {
+ result, err := l.Search(searchRequest)
+ l.Debug.Printf("Looking for Paging Control...")
+ if err != nil {
+ return searchResult, err
+ }
+ if result == nil {
+ return searchResult, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
+ }
+
+ for _, entry := range result.Entries {
+ searchResult.Entries = append(searchResult.Entries, entry)
+ }
+ for _, referral := range result.Referrals {
+ searchResult.Referrals = append(searchResult.Referrals, referral)
+ }
+ for _, control := range result.Controls {
+ searchResult.Controls = append(searchResult.Controls, control)
+ }
+
+ l.Debug.Printf("Looking for Paging Control...")
+ pagingResult := FindControl(result.Controls, ControlTypePaging)
+ if pagingResult == nil {
+ pagingControl = nil
+ l.Debug.Printf("Could not find paging control. Breaking...")
+ break
+ }
+
+ cookie := pagingResult.(*ControlPaging).Cookie
+ if len(cookie) == 0 {
+ pagingControl = nil
+ l.Debug.Printf("Could not find cookie. Breaking...")
+ break
+ }
+ pagingControl.SetCookie(cookie)
+ }
+
+ if pagingControl != nil {
+ l.Debug.Printf("Abandoning Paging...")
+ pagingControl.PagingSize = 0
+ l.Search(searchRequest)
+ }
+
+ return searchResult, nil
+}
+
+func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
+ messageID := l.nextMessageID()
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ // encode search request
+ encodedSearchRequest, err := searchRequest.encode()
+ if err != nil {
+ return nil, err
+ }
+ packet.AppendChild(encodedSearchRequest)
+ // encode search controls
+ if searchRequest.Controls != nil {
+ packet.AppendChild(encodeControls(searchRequest.Controls))
+ }
+
+ l.Debug.PrintPacket(packet)
+
+ channel, err := l.sendMessage(packet)
+ if err != nil {
+ return nil, err
+ }
+ if channel == nil {
+ return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
+ }
+ defer l.finishMessage(messageID)
+
+ result := &SearchResult{
+ Entries: make([]*Entry, 0),
+ Referrals: make([]string, 0),
+ Controls: make([]Control, 0)}
+
+ foundSearchResultDone := false
+ for !foundSearchResultDone {
+ l.Debug.Printf("%d: waiting for response", messageID)
+ packet = <-channel
+ l.Debug.Printf("%d: got response %p", messageID, packet)
+ if packet == nil {
+ return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
+ }
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ return nil, err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ switch packet.Children[1].Tag {
+ case 4:
+ entry := new(Entry)
+ entry.DN = packet.Children[1].Children[0].Value.(string)
+ for _, child := range packet.Children[1].Children[1].Children {
+ attr := new(EntryAttribute)
+ attr.Name = child.Children[0].Value.(string)
+ for _, value := range child.Children[1].Children {
+ attr.Values = append(attr.Values, value.Value.(string))
+ attr.ByteValues = append(attr.ByteValues, value.ByteValue)
+ }
+ entry.Attributes = append(entry.Attributes, attr)
+ }
+ result.Entries = append(result.Entries, entry)
+ case 5:
+ resultCode, resultDescription := getLDAPResultCode(packet)
+ if resultCode != 0 {
+ return result, NewError(resultCode, errors.New(resultDescription))
+ }
+ if len(packet.Children) == 3 {
+ for _, child := range packet.Children[2].Children {
+ result.Controls = append(result.Controls, DecodeControl(child))
+ }
+ }
+ foundSearchResultDone = true
+ case 19:
+ result.Referrals = append(result.Referrals, packet.Children[1].Children[0].Value.(string))
+ }
+ }
+ l.Debug.Printf("%d: returning", messageID)
+ return result, nil
+}
diff --git a/Godeps/_workspace/src/github.com/go-ldap/ldap/search_test.go b/Godeps/_workspace/src/github.com/go-ldap/ldap/search_test.go
new file mode 100644
index 000000000..efb8147d1
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/go-ldap/ldap/search_test.go
@@ -0,0 +1,31 @@
+package ldap
+
+import (
+ "reflect"
+ "testing"
+)
+
+// TestNewEntry tests that repeated calls to NewEntry return the same value with the same input
+func TestNewEntry(t *testing.T) {
+ dn := "testDN"
+ attributes := map[string][]string{
+ "alpha": {"value"},
+ "beta": {"value"},
+ "gamma": {"value"},
+ "delta": {"value"},
+ "epsilon": {"value"},
+ }
+ exectedEntry := NewEntry(dn, attributes)
+
+ iteration := 0
+ for {
+ if iteration == 100 {
+ break
+ }
+ testEntry := NewEntry(dn, attributes)
+ if !reflect.DeepEqual(exectedEntry, testEntry) {
+ t.Fatalf("consequent calls to NewEntry did not yield the same result:\n\texpected:\n\t%s\n\tgot:\n\t%s\n", exectedEntry, testEntry)
+ }
+ iteration = iteration + 1
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/client.go b/Godeps/_workspace/src/github.com/gorilla/websocket/client.go
index 3bf9b2e84..613890603 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/client.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/client.go
@@ -95,13 +95,20 @@ func parseURL(s string) (*url.URL, error) {
return nil, errMalformedURL
}
- u.Host = s
- u.Opaque = "/"
+ if i := strings.Index(s, "?"); i >= 0 {
+ u.RawQuery = s[i+1:]
+ s = s[:i]
+ }
+
if i := strings.Index(s, "/"); i >= 0 {
- u.Host = s[:i]
u.Opaque = s[i:]
+ s = s[:i]
+ } else {
+ u.Opaque = "/"
}
+ u.Host = s
+
if strings.Contains(u.Host, "@") {
// Don't bother parsing user information because user information is
// not allowed in websocket URIs.
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go b/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go
index 05a7888fe..c67550e92 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go
@@ -41,9 +41,16 @@ type cstServer struct {
URL string
}
+const (
+ cstPath = "/a/b"
+ cstRawQuery = "x=y"
+ cstRequestURI = cstPath + "?" + cstRawQuery
+)
+
func newServer(t *testing.T) *cstServer {
var s cstServer
s.Server = httptest.NewServer(cstHandler{t})
+ s.Server.URL += cstRequestURI
s.URL = makeWsProto(s.Server.URL)
return &s
}
@@ -51,11 +58,22 @@ func newServer(t *testing.T) *cstServer {
func newTLSServer(t *testing.T) *cstServer {
var s cstServer
s.Server = httptest.NewTLSServer(cstHandler{t})
+ s.Server.URL += cstRequestURI
s.URL = makeWsProto(s.Server.URL)
return &s
}
func (t cstHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path != cstPath {
+ t.Logf("path=%v, want %v", r.URL.Path, cstPath)
+ http.Error(w, "bad path", 400)
+ return
+ }
+ if r.URL.RawQuery != cstRawQuery {
+ t.Logf("query=%v, want %v", r.URL.RawQuery, cstRawQuery)
+ http.Error(w, "bad path", 400)
+ return
+ }
subprotos := Subprotocols(r)
if !reflect.DeepEqual(subprotos, cstDialer.Subprotocols) {
t.Logf("subprotols=%v, want %v", subprotos, cstDialer.Subprotocols)
@@ -188,7 +206,7 @@ func TestDialTLS(t *testing.T) {
d := cstDialer
d.NetDial = func(network, addr string) (net.Conn, error) { return net.Dial(network, u.Host) }
d.TLSClientConfig = &tls.Config{RootCAs: certs}
- ws, _, err := d.Dial("wss://example.com/", nil)
+ ws, _, err := d.Dial("wss://example.com"+cstRequestURI, nil)
if err != nil {
t.Fatalf("Dial: %v", err)
}
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go b/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go
index 07a9cb453..7d2b0844f 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go
@@ -11,16 +11,19 @@ import (
)
var parseURLTests = []struct {
- s string
- u *url.URL
+ s string
+ u *url.URL
+ rui string
}{
- {"ws://example.com/", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}},
- {"ws://example.com", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}},
- {"ws://example.com:7777/", &url.URL{Scheme: "ws", Host: "example.com:7777", Opaque: "/"}},
- {"wss://example.com/", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/"}},
- {"wss://example.com/a/b", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b"}},
- {"ss://example.com/a/b", nil},
- {"ws://webmaster@example.com/", nil},
+ {"ws://example.com/", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"},
+ {"ws://example.com", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"},
+ {"ws://example.com:7777/", &url.URL{Scheme: "ws", Host: "example.com:7777", Opaque: "/"}, "/"},
+ {"wss://example.com/", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/"}, "/"},
+ {"wss://example.com/a/b", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b"}, "/a/b"},
+ {"ss://example.com/a/b", nil, ""},
+ {"ws://webmaster@example.com/", nil, ""},
+ {"wss://example.com/a/b?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b", RawQuery: "x=y"}, "/a/b?x=y"},
+ {"wss://example.com?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/", RawQuery: "x=y"}, "/?x=y"},
}
func TestParseURL(t *testing.T) {
@@ -30,14 +33,19 @@ func TestParseURL(t *testing.T) {
t.Errorf("parseURL(%q) returned error %v", tt.s, err)
continue
}
- if tt.u == nil && err == nil {
- t.Errorf("parseURL(%q) did not return error", tt.s)
+ if tt.u == nil {
+ if err == nil {
+ t.Errorf("parseURL(%q) did not return error", tt.s)
+ }
continue
}
if !reflect.DeepEqual(u, tt.u) {
- t.Errorf("parseURL(%q) returned %v, want %v", tt.s, u, tt.u)
+ t.Errorf("parseURL(%q) = %v, want %v", tt.s, u, tt.u)
continue
}
+ if u.RequestURI() != tt.rui {
+ t.Errorf("parseURL(%q).RequestURI() = %v, want %v", tt.s, u.RequestURI(), tt.rui)
+ }
}
}
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/echo/client.go b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/echo/client.go
index 45a023175..6578094e7 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/echo/client.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/echo/client.go
@@ -10,6 +10,8 @@ import (
"flag"
"log"
"net/url"
+ "os"
+ "os/signal"
"time"
"github.com/gorilla/websocket"
@@ -21,6 +23,9 @@ func main() {
flag.Parse()
log.SetFlags(0)
+ interrupt := make(chan os.Signal, 1)
+ signal.Notify(interrupt, os.Interrupt)
+
u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo"}
log.Printf("connecting to %s", u.String())
@@ -30,13 +35,16 @@ func main() {
}
defer c.Close()
+ done := make(chan struct{})
+
go func() {
defer c.Close()
+ defer close(done)
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Println("read:", err)
- break
+ return
}
log.Printf("recv: %s", message)
}
@@ -45,11 +53,29 @@ func main() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
- for t := range ticker.C {
- err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
- if err != nil {
- log.Println("write:", err)
- break
+ for {
+ select {
+ case t := <-ticker.C:
+ err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
+ if err != nil {
+ log.Println("write:", err)
+ return
+ }
+ case <-interrupt:
+ log.Println("interrupt")
+ // To cleanly close a connection, a client should send a close
+ // frame and wait for the server to close the connection.
+ err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+ if err != nil {
+ log.Println("write close:", err)
+ return
+ }
+ select {
+ case <-done:
+ case <-time.After(time.Second):
+ }
+ c.Close()
+ return
}
}
}
diff --git a/Godeps/_workspace/src/github.com/lib/pq/conn.go b/Godeps/_workspace/src/github.com/lib/pq/conn.go
index ce661d66e..4af880fb5 100644
--- a/Godeps/_workspace/src/github.com/lib/pq/conn.go
+++ b/Godeps/_workspace/src/github.com/lib/pq/conn.go
@@ -557,13 +557,15 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
cn.bad = true
errorf("unexpected message %q in simple query execution", t)
}
- res = &rows{
- cn: cn,
- colNames: st.colNames,
- colTyps: st.colTyps,
- colFmts: st.colFmts,
- done: true,
+ if res == nil {
+ res = &rows{
+ cn: cn,
+ colNames: st.colNames,
+ colTyps: st.colTyps,
+ colFmts: st.colFmts,
+ }
}
+ res.done = true
case 'Z':
cn.processReadyForQuery(r)
// done
diff --git a/Godeps/_workspace/src/github.com/lib/pq/conn_test.go b/Godeps/_workspace/src/github.com/lib/pq/conn_test.go
index af07e5596..5cb8095a3 100644
--- a/Godeps/_workspace/src/github.com/lib/pq/conn_test.go
+++ b/Godeps/_workspace/src/github.com/lib/pq/conn_test.go
@@ -345,6 +345,59 @@ func TestEmptyQuery(t *testing.T) {
}
}
+// Test that rows.Columns() is correct even if there are no result rows.
+func TestEmptyResultSetColumns(t *testing.T) {
+ db := openTestConn(t)
+ defer db.Close()
+
+ rows, err := db.Query("SELECT 1 AS a, text 'bar' AS bar WHERE FALSE")
+ if err != nil {
+ t.Fatal(err)
+ }
+ cols, err := rows.Columns()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(cols) != 2 {
+ t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols))
+ }
+ if rows.Next() {
+ t.Fatal("unexpected row")
+ }
+ if rows.Err() != nil {
+ t.Fatal(rows.Err())
+ }
+ if cols[0] != "a" || cols[1] != "bar" {
+ t.Fatalf("unexpected Columns result %v", cols)
+ }
+
+ stmt, err := db.Prepare("SELECT $1::int AS a, text 'bar' AS bar WHERE FALSE")
+ if err != nil {
+ t.Fatal(err)
+ }
+ rows, err = stmt.Query(1)
+ if err != nil {
+ t.Fatal(err)
+ }
+ cols, err = rows.Columns()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(cols) != 2 {
+ t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols))
+ }
+ if rows.Next() {
+ t.Fatal("unexpected row")
+ }
+ if rows.Err() != nil {
+ t.Fatal(rows.Err())
+ }
+ if cols[0] != "a" || cols[1] != "bar" {
+ t.Fatalf("unexpected Columns result %v", cols)
+ }
+
+}
+
func TestEncodeDecode(t *testing.T) {
db := openTestConn(t)
defer db.Close()
diff --git a/Godeps/_workspace/src/github.com/pborman/uuid/sql.go b/Godeps/_workspace/src/github.com/pborman/uuid/sql.go
index 2d7679e2a..98b23aa15 100644
--- a/Godeps/_workspace/src/github.com/pborman/uuid/sql.go
+++ b/Godeps/_workspace/src/github.com/pborman/uuid/sql.go
@@ -24,14 +24,22 @@ func (uuid *UUID) Scan(src interface{}) error {
*uuid = parsed
case []byte:
- // assumes a simple slice of bytes, just check validity and store
- u := UUID(src.([]byte))
+ b := src.([]byte)
- if u.Variant() == Invalid {
- return errors.New("Scan: invalid UUID format")
+ // assumes a simple slice of bytes if 16 bytes
+ // otherwise attempts to parse
+ if len(b) == 16 {
+ *uuid = UUID(b)
+ } else {
+ u := Parse(string(b))
+
+ if u == nil {
+ return errors.New("Scan: invalid UUID format")
+ }
+
+ *uuid = u
}
- *uuid = u
default:
return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
}
diff --git a/Godeps/_workspace/src/github.com/pborman/uuid/sql_test.go b/Godeps/_workspace/src/github.com/pborman/uuid/sql_test.go
index d643567ee..83bac8cac 100644
--- a/Godeps/_workspace/src/github.com/pborman/uuid/sql_test.go
+++ b/Godeps/_workspace/src/github.com/pborman/uuid/sql_test.go
@@ -22,6 +22,11 @@ func TestScan(t *testing.T) {
t.Fatal(err)
}
+ err = (&uuid).Scan([]byte(stringTest))
+ if err != nil {
+ t.Fatal(err)
+ }
+
err = (&uuid).Scan(byteTest)
if err != nil {
t.Fatal(err)
diff --git a/Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib.go b/Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib.go
deleted file mode 100644
index 64cc40fe1..000000000
--- a/Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib.go
+++ /dev/null
@@ -1,758 +0,0 @@
-// Package difflib is a partial port of Python difflib module.
-//
-// It provides tools to compare sequences of strings and generate textual diffs.
-//
-// The following class and functions have been ported:
-//
-// - SequenceMatcher
-//
-// - unified_diff
-//
-// - context_diff
-//
-// Getting unified diffs was the main goal of the port. Keep in mind this code
-// is mostly suitable to output text differences in a human friendly way, there
-// are no guarantees generated diffs are consumable by patch(1).
-package difflib
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "io"
- "strings"
-)
-
-func min(a, b int) int {
- if a < b {
- return a
- }
- return b
-}
-
-func max(a, b int) int {
- if a > b {
- return a
- }
- return b
-}
-
-func calculateRatio(matches, length int) float64 {
- if length > 0 {
- return 2.0 * float64(matches) / float64(length)
- }
- return 1.0
-}
-
-type Match struct {
- A int
- B int
- Size int
-}
-
-type OpCode struct {
- Tag byte
- I1 int
- I2 int
- J1 int
- J2 int
-}
-
-// SequenceMatcher compares sequence of strings. The basic
-// algorithm predates, and is a little fancier than, an algorithm
-// published in the late 1980's by Ratcliff and Obershelp under the
-// hyperbolic name "gestalt pattern matching". The basic idea is to find
-// the longest contiguous matching subsequence that contains no "junk"
-// elements (R-O doesn't address junk). The same idea is then applied
-// recursively to the pieces of the sequences to the left and to the right
-// of the matching subsequence. This does not yield minimal edit
-// sequences, but does tend to yield matches that "look right" to people.
-//
-// SequenceMatcher tries to compute a "human-friendly diff" between two
-// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the
-// longest *contiguous* & junk-free matching subsequence. That's what
-// catches peoples' eyes. The Windows(tm) windiff has another interesting
-// notion, pairing up elements that appear uniquely in each sequence.
-// That, and the method here, appear to yield more intuitive difference
-// reports than does diff. This method appears to be the least vulnerable
-// to synching up on blocks of "junk lines", though (like blank lines in
-// ordinary text files, or maybe "<P>" lines in HTML files). That may be
-// because this is the only method of the 3 that has a *concept* of
-// "junk" <wink>.
-//
-// Timing: Basic R-O is cubic time worst case and quadratic time expected
-// case. SequenceMatcher is quadratic time for the worst case and has
-// expected-case behavior dependent in a complicated way on how many
-// elements the sequences have in common; best case time is linear.
-type SequenceMatcher struct {
- a []string
- b []string
- b2j map[string][]int
- IsJunk func(string) bool
- autoJunk bool
- bJunk map[string]struct{}
- matchingBlocks []Match
- fullBCount map[string]int
- bPopular map[string]struct{}
- opCodes []OpCode
-}
-
-func NewMatcher(a, b []string) *SequenceMatcher {
- m := SequenceMatcher{autoJunk: true}
- m.SetSeqs(a, b)
- return &m
-}
-
-func NewMatcherWithJunk(a, b []string, autoJunk bool,
- isJunk func(string) bool) *SequenceMatcher {
-
- m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk}
- m.SetSeqs(a, b)
- return &m
-}
-
-// Set two sequences to be compared.
-func (m *SequenceMatcher) SetSeqs(a, b []string) {
- m.SetSeq1(a)
- m.SetSeq2(b)
-}
-
-// Set the first sequence to be compared. The second sequence to be compared is
-// not changed.
-//
-// SequenceMatcher computes and caches detailed information about the second
-// sequence, so if you want to compare one sequence S against many sequences,
-// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other
-// sequences.
-//
-// See also SetSeqs() and SetSeq2().
-func (m *SequenceMatcher) SetSeq1(a []string) {
- if &a == &m.a {
- return
- }
- m.a = a
- m.matchingBlocks = nil
- m.opCodes = nil
-}
-
-// Set the second sequence to be compared. The first sequence to be compared is
-// not changed.
-func (m *SequenceMatcher) SetSeq2(b []string) {
- if &b == &m.b {
- return
- }
- m.b = b
- m.matchingBlocks = nil
- m.opCodes = nil
- m.fullBCount = nil
- m.chainB()
-}
-
-func (m *SequenceMatcher) chainB() {
- // Populate line -> index mapping
- b2j := map[string][]int{}
- for i, s := range m.b {
- indices := b2j[s]
- indices = append(indices, i)
- b2j[s] = indices
- }
-
- // Purge junk elements
- m.bJunk = map[string]struct{}{}
- if m.IsJunk != nil {
- junk := m.bJunk
- for s, _ := range b2j {
- if m.IsJunk(s) {
- junk[s] = struct{}{}
- }
- }
- for s, _ := range junk {
- delete(b2j, s)
- }
- }
-
- // Purge remaining popular elements
- popular := map[string]struct{}{}
- n := len(m.b)
- if m.autoJunk && n >= 200 {
- ntest := n/100 + 1
- for s, indices := range b2j {
- if len(indices) > ntest {
- popular[s] = struct{}{}
- }
- }
- for s, _ := range popular {
- delete(b2j, s)
- }
- }
- m.bPopular = popular
- m.b2j = b2j
-}
-
-func (m *SequenceMatcher) isBJunk(s string) bool {
- _, ok := m.bJunk[s]
- return ok
-}
-
-// Find longest matching block in a[alo:ahi] and b[blo:bhi].
-//
-// If IsJunk is not defined:
-//
-// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
-// alo <= i <= i+k <= ahi
-// blo <= j <= j+k <= bhi
-// and for all (i',j',k') meeting those conditions,
-// k >= k'
-// i <= i'
-// and if i == i', j <= j'
-//
-// In other words, of all maximal matching blocks, return one that
-// starts earliest in a, and of all those maximal matching blocks that
-// start earliest in a, return the one that starts earliest in b.
-//
-// If IsJunk is defined, first the longest matching block is
-// determined as above, but with the additional restriction that no
-// junk element appears in the block. Then that block is extended as
-// far as possible by matching (only) junk elements on both sides. So
-// the resulting block never matches on junk except as identical junk
-// happens to be adjacent to an "interesting" match.
-//
-// If no blocks match, return (alo, blo, 0).
-func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match {
- // CAUTION: stripping common prefix or suffix would be incorrect.
- // E.g.,
- // ab
- // acab
- // Longest matching block is "ab", but if common prefix is
- // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so
- // strip, so ends up claiming that ab is changed to acab by
- // inserting "ca" in the middle. That's minimal but unintuitive:
- // "it's obvious" that someone inserted "ac" at the front.
- // Windiff ends up at the same place as diff, but by pairing up
- // the unique 'b's and then matching the first two 'a's.
- besti, bestj, bestsize := alo, blo, 0
-
- // find longest junk-free match
- // during an iteration of the loop, j2len[j] = length of longest
- // junk-free match ending with a[i-1] and b[j]
- j2len := map[int]int{}
- for i := alo; i != ahi; i++ {
- // look at all instances of a[i] in b; note that because
- // b2j has no junk keys, the loop is skipped if a[i] is junk
- newj2len := map[int]int{}
- for _, j := range m.b2j[m.a[i]] {
- // a[i] matches b[j]
- if j < blo {
- continue
- }
- if j >= bhi {
- break
- }
- k := j2len[j-1] + 1
- newj2len[j] = k
- if k > bestsize {
- besti, bestj, bestsize = i-k+1, j-k+1, k
- }
- }
- j2len = newj2len
- }
-
- // Extend the best by non-junk elements on each end. In particular,
- // "popular" non-junk elements aren't in b2j, which greatly speeds
- // the inner loop above, but also means "the best" match so far
- // doesn't contain any junk *or* popular non-junk elements.
- for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) &&
- m.a[besti-1] == m.b[bestj-1] {
- besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
- }
- for besti+bestsize < ahi && bestj+bestsize < bhi &&
- !m.isBJunk(m.b[bestj+bestsize]) &&
- m.a[besti+bestsize] == m.b[bestj+bestsize] {
- bestsize += 1
- }
-
- // Now that we have a wholly interesting match (albeit possibly
- // empty!), we may as well suck up the matching junk on each
- // side of it too. Can't think of a good reason not to, and it
- // saves post-processing the (possibly considerable) expense of
- // figuring out what to do with it. In the case of an empty
- // interesting match, this is clearly the right thing to do,
- // because no other kind of match is possible in the regions.
- for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) &&
- m.a[besti-1] == m.b[bestj-1] {
- besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
- }
- for besti+bestsize < ahi && bestj+bestsize < bhi &&
- m.isBJunk(m.b[bestj+bestsize]) &&
- m.a[besti+bestsize] == m.b[bestj+bestsize] {
- bestsize += 1
- }
-
- return Match{A: besti, B: bestj, Size: bestsize}
-}
-
-// Return list of triples describing matching subsequences.
-//
-// Each triple is of the form (i, j, n), and means that
-// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in
-// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are
-// adjacent triples in the list, and the second is not the last triple in the
-// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe
-// adjacent equal blocks.
-//
-// The last triple is a dummy, (len(a), len(b), 0), and is the only
-// triple with n==0.
-func (m *SequenceMatcher) GetMatchingBlocks() []Match {
- if m.matchingBlocks != nil {
- return m.matchingBlocks
- }
-
- var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match
- matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match {
- match := m.findLongestMatch(alo, ahi, blo, bhi)
- i, j, k := match.A, match.B, match.Size
- if match.Size > 0 {
- if alo < i && blo < j {
- matched = matchBlocks(alo, i, blo, j, matched)
- }
- matched = append(matched, match)
- if i+k < ahi && j+k < bhi {
- matched = matchBlocks(i+k, ahi, j+k, bhi, matched)
- }
- }
- return matched
- }
- matched := matchBlocks(0, len(m.a), 0, len(m.b), nil)
-
- // It's possible that we have adjacent equal blocks in the
- // matching_blocks list now.
- nonAdjacent := []Match{}
- i1, j1, k1 := 0, 0, 0
- for _, b := range matched {
- // Is this block adjacent to i1, j1, k1?
- i2, j2, k2 := b.A, b.B, b.Size
- if i1+k1 == i2 && j1+k1 == j2 {
- // Yes, so collapse them -- this just increases the length of
- // the first block by the length of the second, and the first
- // block so lengthened remains the block to compare against.
- k1 += k2
- } else {
- // Not adjacent. Remember the first block (k1==0 means it's
- // the dummy we started with), and make the second block the
- // new block to compare against.
- if k1 > 0 {
- nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
- }
- i1, j1, k1 = i2, j2, k2
- }
- }
- if k1 > 0 {
- nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
- }
-
- nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0})
- m.matchingBlocks = nonAdjacent
- return m.matchingBlocks
-}
-
-// Return list of 5-tuples describing how to turn a into b.
-//
-// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple
-// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the
-// tuple preceding it, and likewise for j1 == the previous j2.
-//
-// The tags are characters, with these meanings:
-//
-// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2]
-//
-// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case.
-//
-// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case.
-//
-// 'e' (equal): a[i1:i2] == b[j1:j2]
-func (m *SequenceMatcher) GetOpCodes() []OpCode {
- if m.opCodes != nil {
- return m.opCodes
- }
- i, j := 0, 0
- matching := m.GetMatchingBlocks()
- opCodes := make([]OpCode, 0, len(matching))
- for _, m := range matching {
- // invariant: we've pumped out correct diffs to change
- // a[:i] into b[:j], and the next matching block is
- // a[ai:ai+size] == b[bj:bj+size]. So we need to pump
- // out a diff to change a[i:ai] into b[j:bj], pump out
- // the matching block, and move (i,j) beyond the match
- ai, bj, size := m.A, m.B, m.Size
- tag := byte(0)
- if i < ai && j < bj {
- tag = 'r'
- } else if i < ai {
- tag = 'd'
- } else if j < bj {
- tag = 'i'
- }
- if tag > 0 {
- opCodes = append(opCodes, OpCode{tag, i, ai, j, bj})
- }
- i, j = ai+size, bj+size
- // the list of matching blocks is terminated by a
- // sentinel with size 0
- if size > 0 {
- opCodes = append(opCodes, OpCode{'e', ai, i, bj, j})
- }
- }
- m.opCodes = opCodes
- return m.opCodes
-}
-
-// Isolate change clusters by eliminating ranges with no changes.
-//
-// Return a generator of groups with up to n lines of context.
-// Each group is in the same format as returned by GetOpCodes().
-func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
- if n < 0 {
- n = 3
- }
- codes := m.GetOpCodes()
- if len(codes) == 0 {
- codes = []OpCode{OpCode{'e', 0, 1, 0, 1}}
- }
- // Fixup leading and trailing groups if they show no changes.
- if codes[0].Tag == 'e' {
- c := codes[0]
- i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
- codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2}
- }
- if codes[len(codes)-1].Tag == 'e' {
- c := codes[len(codes)-1]
- i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
- codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}
- }
- nn := n + n
- groups := [][]OpCode{}
- group := []OpCode{}
- for _, c := range codes {
- i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
- // End the current group and start a new one whenever
- // there is a large range with no changes.
- if c.Tag == 'e' && i2-i1 > nn {
- group = append(group, OpCode{c.Tag, i1, min(i2, i1+n),
- j1, min(j2, j1+n)})
- groups = append(groups, group)
- group = []OpCode{}
- i1, j1 = max(i1, i2-n), max(j1, j2-n)
- }
- group = append(group, OpCode{c.Tag, i1, i2, j1, j2})
- }
- if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') {
- groups = append(groups, group)
- }
- return groups
-}
-
-// Return a measure of the sequences' similarity (float in [0,1]).
-//
-// Where T is the total number of elements in both sequences, and
-// M is the number of matches, this is 2.0*M / T.
-// Note that this is 1 if the sequences are identical, and 0 if
-// they have nothing in common.
-//
-// .Ratio() is expensive to compute if you haven't already computed
-// .GetMatchingBlocks() or .GetOpCodes(), in which case you may
-// want to try .QuickRatio() or .RealQuickRation() first to get an
-// upper bound.
-func (m *SequenceMatcher) Ratio() float64 {
- matches := 0
- for _, m := range m.GetMatchingBlocks() {
- matches += m.Size
- }
- return calculateRatio(matches, len(m.a)+len(m.b))
-}
-
-// Return an upper bound on ratio() relatively quickly.
-//
-// This isn't defined beyond that it is an upper bound on .Ratio(), and
-// is faster to compute.
-func (m *SequenceMatcher) QuickRatio() float64 {
- // viewing a and b as multisets, set matches to the cardinality
- // of their intersection; this counts the number of matches
- // without regard to order, so is clearly an upper bound
- if m.fullBCount == nil {
- m.fullBCount = map[string]int{}
- for _, s := range m.b {
- m.fullBCount[s] = m.fullBCount[s] + 1
- }
- }
-
- // avail[x] is the number of times x appears in 'b' less the
- // number of times we've seen it in 'a' so far ... kinda
- avail := map[string]int{}
- matches := 0
- for _, s := range m.a {
- n, ok := avail[s]
- if !ok {
- n = m.fullBCount[s]
- }
- avail[s] = n - 1
- if n > 0 {
- matches += 1
- }
- }
- return calculateRatio(matches, len(m.a)+len(m.b))
-}
-
-// Return an upper bound on ratio() very quickly.
-//
-// This isn't defined beyond that it is an upper bound on .Ratio(), and
-// is faster to compute than either .Ratio() or .QuickRatio().
-func (m *SequenceMatcher) RealQuickRatio() float64 {
- la, lb := len(m.a), len(m.b)
- return calculateRatio(min(la, lb), la+lb)
-}
-
-// Convert range to the "ed" format
-func formatRangeUnified(start, stop int) string {
- // Per the diff spec at http://www.unix.org/single_unix_specification/
- beginning := start + 1 // lines start numbering with one
- length := stop - start
- if length == 1 {
- return fmt.Sprintf("%d", beginning)
- }
- if length == 0 {
- beginning -= 1 // empty ranges begin at line just before the range
- }
- return fmt.Sprintf("%d,%d", beginning, length)
-}
-
-// Unified diff parameters
-type UnifiedDiff struct {
- A []string // First sequence lines
- FromFile string // First file name
- FromDate string // First file time
- B []string // Second sequence lines
- ToFile string // Second file name
- ToDate string // Second file time
- Eol string // Headers end of line, defaults to LF
- Context int // Number of context lines
-}
-
-// Compare two sequences of lines; generate the delta as a unified diff.
-//
-// Unified diffs are a compact way of showing line changes and a few
-// lines of context. The number of context lines is set by 'n' which
-// defaults to three.
-//
-// By default, the diff control lines (those with ---, +++, or @@) are
-// created with a trailing newline. This is helpful so that inputs
-// created from file.readlines() result in diffs that are suitable for
-// file.writelines() since both the inputs and outputs have trailing
-// newlines.
-//
-// For inputs that do not have trailing newlines, set the lineterm
-// argument to "" so that the output will be uniformly newline free.
-//
-// The unidiff format normally has a header for filenames and modification
-// times. Any or all of these may be specified using strings for
-// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
-// The modification times are normally expressed in the ISO 8601 format.
-func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error {
- buf := bufio.NewWriter(writer)
- defer buf.Flush()
- w := func(format string, args ...interface{}) error {
- _, err := buf.WriteString(fmt.Sprintf(format, args...))
- return err
- }
-
- if len(diff.Eol) == 0 {
- diff.Eol = "\n"
- }
-
- started := false
- m := NewMatcher(diff.A, diff.B)
- for _, g := range m.GetGroupedOpCodes(diff.Context) {
- if !started {
- started = true
- fromDate := ""
- if len(diff.FromDate) > 0 {
- fromDate = "\t" + diff.FromDate
- }
- toDate := ""
- if len(diff.ToDate) > 0 {
- toDate = "\t" + diff.ToDate
- }
- err := w("--- %s%s%s", diff.FromFile, fromDate, diff.Eol)
- if err != nil {
- return err
- }
- err = w("+++ %s%s%s", diff.ToFile, toDate, diff.Eol)
- if err != nil {
- return err
- }
- }
- first, last := g[0], g[len(g)-1]
- range1 := formatRangeUnified(first.I1, last.I2)
- range2 := formatRangeUnified(first.J1, last.J2)
- if err := w("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil {
- return err
- }
- for _, c := range g {
- i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
- if c.Tag == 'e' {
- for _, line := range diff.A[i1:i2] {
- if err := w(" " + line); err != nil {
- return err
- }
- }
- continue
- }
- if c.Tag == 'r' || c.Tag == 'd' {
- for _, line := range diff.A[i1:i2] {
- if err := w("-" + line); err != nil {
- return err
- }
- }
- }
- if c.Tag == 'r' || c.Tag == 'i' {
- for _, line := range diff.B[j1:j2] {
- if err := w("+" + line); err != nil {
- return err
- }
- }
- }
- }
- }
- return nil
-}
-
-// Like WriteUnifiedDiff but returns the diff a string.
-func GetUnifiedDiffString(diff UnifiedDiff) (string, error) {
- w := &bytes.Buffer{}
- err := WriteUnifiedDiff(w, diff)
- return string(w.Bytes()), err
-}
-
-// Convert range to the "ed" format.
-func formatRangeContext(start, stop int) string {
- // Per the diff spec at http://www.unix.org/single_unix_specification/
- beginning := start + 1 // lines start numbering with one
- length := stop - start
- if length == 0 {
- beginning -= 1 // empty ranges begin at line just before the range
- }
- if length <= 1 {
- return fmt.Sprintf("%d", beginning)
- }
- return fmt.Sprintf("%d,%d", beginning, beginning+length-1)
-}
-
-type ContextDiff UnifiedDiff
-
-// Compare two sequences of lines; generate the delta as a context diff.
-//
-// Context diffs are a compact way of showing line changes and a few
-// lines of context. The number of context lines is set by diff.Context
-// which defaults to three.
-//
-// By default, the diff control lines (those with *** or ---) are
-// created with a trailing newline.
-//
-// For inputs that do not have trailing newlines, set the diff.Eol
-// argument to "" so that the output will be uniformly newline free.
-//
-// The context diff format normally has a header for filenames and
-// modification times. Any or all of these may be specified using
-// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate.
-// The modification times are normally expressed in the ISO 8601 format.
-// If not specified, the strings default to blanks.
-func WriteContextDiff(writer io.Writer, diff ContextDiff) error {
- buf := bufio.NewWriter(writer)
- defer buf.Flush()
- var diffErr error
- w := func(format string, args ...interface{}) {
- _, err := buf.WriteString(fmt.Sprintf(format, args...))
- if diffErr == nil && err != nil {
- diffErr = err
- }
- }
-
- if len(diff.Eol) == 0 {
- diff.Eol = "\n"
- }
-
- prefix := map[byte]string{
- 'i': "+ ",
- 'd': "- ",
- 'r': "! ",
- 'e': " ",
- }
-
- started := false
- m := NewMatcher(diff.A, diff.B)
- for _, g := range m.GetGroupedOpCodes(diff.Context) {
- if !started {
- started = true
- fromDate := ""
- if len(diff.FromDate) > 0 {
- fromDate = "\t" + diff.FromDate
- }
- toDate := ""
- if len(diff.ToDate) > 0 {
- toDate = "\t" + diff.ToDate
- }
- w("*** %s%s%s", diff.FromFile, fromDate, diff.Eol)
- w("--- %s%s%s", diff.ToFile, toDate, diff.Eol)
- }
-
- first, last := g[0], g[len(g)-1]
- w("***************" + diff.Eol)
-
- range1 := formatRangeContext(first.I1, last.I2)
- w("*** %s ****%s", range1, diff.Eol)
- for _, c := range g {
- if c.Tag == 'r' || c.Tag == 'd' {
- for _, cc := range g {
- if cc.Tag == 'i' {
- continue
- }
- for _, line := range diff.A[cc.I1:cc.I2] {
- w(prefix[cc.Tag] + line)
- }
- }
- break
- }
- }
-
- range2 := formatRangeContext(first.J1, last.J2)
- w("--- %s ----%s", range2, diff.Eol)
- for _, c := range g {
- if c.Tag == 'r' || c.Tag == 'i' {
- for _, cc := range g {
- if cc.Tag == 'd' {
- continue
- }
- for _, line := range diff.B[cc.J1:cc.J2] {
- w(prefix[cc.Tag] + line)
- }
- }
- break
- }
- }
- }
- return diffErr
-}
-
-// Like WriteContextDiff but returns the diff a string.
-func GetContextDiffString(diff ContextDiff) (string, error) {
- w := &bytes.Buffer{}
- err := WriteContextDiff(w, diff)
- return string(w.Bytes()), err
-}
-
-// Split a string on "\n" while preserving them. The output can be used
-// as input for UnifiedDiff and ContextDiff structures.
-func SplitLines(s string) []string {
- lines := strings.SplitAfter(s, "\n")
- lines[len(lines)-1] += "\n"
- return lines
-}
diff --git a/Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib_test.go b/Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib_test.go
deleted file mode 100644
index 94670bea3..000000000
--- a/Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib_test.go
+++ /dev/null
@@ -1,352 +0,0 @@
-package difflib
-
-import (
- "bytes"
- "fmt"
- "math"
- "reflect"
- "strings"
- "testing"
-)
-
-func assertAlmostEqual(t *testing.T, a, b float64, places int) {
- if math.Abs(a-b) > math.Pow10(-places) {
- t.Errorf("%.7f != %.7f", a, b)
- }
-}
-
-func assertEqual(t *testing.T, a, b interface{}) {
- if !reflect.DeepEqual(a, b) {
- t.Errorf("%v != %v", a, b)
- }
-}
-
-func splitChars(s string) []string {
- chars := make([]string, 0, len(s))
- // Assume ASCII inputs
- for i := 0; i != len(s); i++ {
- chars = append(chars, string(s[i]))
- }
- return chars
-}
-
-func TestSequenceMatcherRatio(t *testing.T) {
- s := NewMatcher(splitChars("abcd"), splitChars("bcde"))
- assertEqual(t, s.Ratio(), 0.75)
- assertEqual(t, s.QuickRatio(), 0.75)
- assertEqual(t, s.RealQuickRatio(), 1.0)
-}
-
-func TestGetOptCodes(t *testing.T) {
- a := "qabxcd"
- b := "abycdf"
- s := NewMatcher(splitChars(a), splitChars(b))
- w := &bytes.Buffer{}
- for _, op := range s.GetOpCodes() {
- fmt.Fprintf(w, "%s a[%d:%d], (%s) b[%d:%d] (%s)\n", string(op.Tag),
- op.I1, op.I2, a[op.I1:op.I2], op.J1, op.J2, b[op.J1:op.J2])
- }
- result := string(w.Bytes())
- expected := `d a[0:1], (q) b[0:0] ()
-e a[1:3], (ab) b[0:2] (ab)
-r a[3:4], (x) b[2:3] (y)
-e a[4:6], (cd) b[3:5] (cd)
-i a[6:6], () b[5:6] (f)
-`
- if expected != result {
- t.Errorf("unexpected op codes: \n%s", result)
- }
-}
-
-func TestGroupedOpCodes(t *testing.T) {
- a := []string{}
- for i := 0; i != 39; i++ {
- a = append(a, fmt.Sprintf("%02d", i))
- }
- b := []string{}
- b = append(b, a[:8]...)
- b = append(b, " i")
- b = append(b, a[8:19]...)
- b = append(b, " x")
- b = append(b, a[20:22]...)
- b = append(b, a[27:34]...)
- b = append(b, " y")
- b = append(b, a[35:]...)
- s := NewMatcher(a, b)
- w := &bytes.Buffer{}
- for _, g := range s.GetGroupedOpCodes(-1) {
- fmt.Fprintf(w, "group\n")
- for _, op := range g {
- fmt.Fprintf(w, " %s, %d, %d, %d, %d\n", string(op.Tag),
- op.I1, op.I2, op.J1, op.J2)
- }
- }
- result := string(w.Bytes())
- expected := `group
- e, 5, 8, 5, 8
- i, 8, 8, 8, 9
- e, 8, 11, 9, 12
-group
- e, 16, 19, 17, 20
- r, 19, 20, 20, 21
- e, 20, 22, 21, 23
- d, 22, 27, 23, 23
- e, 27, 30, 23, 26
-group
- e, 31, 34, 27, 30
- r, 34, 35, 30, 31
- e, 35, 38, 31, 34
-`
- if expected != result {
- t.Errorf("unexpected op codes: \n%s", result)
- }
-}
-
-func ExampleGetUnifiedDiffString() {
- a := `one
-two
-three
-four`
- b := `zero
-one
-three
-four`
- diff := UnifiedDiff{
- A: SplitLines(a),
- B: SplitLines(b),
- FromFile: "Original",
- FromDate: "2005-01-26 23:30:50",
- ToFile: "Current",
- ToDate: "2010-04-02 10:20:52",
- Context: 3,
- }
- result, _ := GetUnifiedDiffString(diff)
- fmt.Printf(strings.Replace(result, "\t", " ", -1))
- // Output:
- // --- Original 2005-01-26 23:30:50
- // +++ Current 2010-04-02 10:20:52
- // @@ -1,4 +1,4 @@
- // +zero
- // one
- // -two
- // three
- // four
-}
-
-func ExampleGetContextDiffString() {
- a := `one
-two
-three
-four`
- b := `zero
-one
-tree
-four`
- diff := ContextDiff{
- A: SplitLines(a),
- B: SplitLines(b),
- FromFile: "Original",
- ToFile: "Current",
- Context: 3,
- Eol: "\n",
- }
- result, _ := GetContextDiffString(diff)
- fmt.Printf(strings.Replace(result, "\t", " ", -1))
- // Output:
- // *** Original
- // --- Current
- // ***************
- // *** 1,4 ****
- // one
- // ! two
- // ! three
- // four
- // --- 1,4 ----
- // + zero
- // one
- // ! tree
- // four
-}
-
-func rep(s string, count int) string {
- return strings.Repeat(s, count)
-}
-
-func TestWithAsciiOneInsert(t *testing.T) {
- sm := NewMatcher(splitChars(rep("b", 100)),
- splitChars("a"+rep("b", 100)))
- assertAlmostEqual(t, sm.Ratio(), 0.995, 3)
- assertEqual(t, sm.GetOpCodes(),
- []OpCode{{'i', 0, 0, 0, 1}, {'e', 0, 100, 1, 101}})
- assertEqual(t, len(sm.bPopular), 0)
-
- sm = NewMatcher(splitChars(rep("b", 100)),
- splitChars(rep("b", 50)+"a"+rep("b", 50)))
- assertAlmostEqual(t, sm.Ratio(), 0.995, 3)
- assertEqual(t, sm.GetOpCodes(),
- []OpCode{{'e', 0, 50, 0, 50}, {'i', 50, 50, 50, 51}, {'e', 50, 100, 51, 101}})
- assertEqual(t, len(sm.bPopular), 0)
-}
-
-func TestWithAsciiOnDelete(t *testing.T) {
- sm := NewMatcher(splitChars(rep("a", 40)+"c"+rep("b", 40)),
- splitChars(rep("a", 40)+rep("b", 40)))
- assertAlmostEqual(t, sm.Ratio(), 0.994, 3)
- assertEqual(t, sm.GetOpCodes(),
- []OpCode{{'e', 0, 40, 0, 40}, {'d', 40, 41, 40, 40}, {'e', 41, 81, 40, 80}})
-}
-
-func TestWithAsciiBJunk(t *testing.T) {
- isJunk := func(s string) bool {
- return s == " "
- }
- sm := NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)),
- splitChars(rep("a", 44)+rep("b", 40)), true, isJunk)
- assertEqual(t, sm.bJunk, map[string]struct{}{})
-
- sm = NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)),
- splitChars(rep("a", 44)+rep("b", 40)+rep(" ", 20)), false, isJunk)
- assertEqual(t, sm.bJunk, map[string]struct{}{" ": struct{}{}})
-
- isJunk = func(s string) bool {
- return s == " " || s == "b"
- }
- sm = NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)),
- splitChars(rep("a", 44)+rep("b", 40)+rep(" ", 20)), false, isJunk)
- assertEqual(t, sm.bJunk, map[string]struct{}{" ": struct{}{}, "b": struct{}{}})
-}
-
-func TestSFBugsRatioForNullSeqn(t *testing.T) {
- sm := NewMatcher(nil, nil)
- assertEqual(t, sm.Ratio(), 1.0)
- assertEqual(t, sm.QuickRatio(), 1.0)
- assertEqual(t, sm.RealQuickRatio(), 1.0)
-}
-
-func TestSFBugsComparingEmptyLists(t *testing.T) {
- groups := NewMatcher(nil, nil).GetGroupedOpCodes(-1)
- assertEqual(t, len(groups), 0)
- diff := UnifiedDiff{
- FromFile: "Original",
- ToFile: "Current",
- Context: 3,
- }
- result, err := GetUnifiedDiffString(diff)
- assertEqual(t, err, nil)
- assertEqual(t, result, "")
-}
-
-func TestOutputFormatRangeFormatUnified(t *testing.T) {
- // Per the diff spec at http://www.unix.org/single_unix_specification/
- //
- // Each <range> field shall be of the form:
- // %1d", <beginning line number> if the range contains exactly one line,
- // and:
- // "%1d,%1d", <beginning line number>, <number of lines> otherwise.
- // If a range is empty, its beginning line number shall be the number of
- // the line just before the range, or 0 if the empty range starts the file.
- fm := formatRangeUnified
- assertEqual(t, fm(3, 3), "3,0")
- assertEqual(t, fm(3, 4), "4")
- assertEqual(t, fm(3, 5), "4,2")
- assertEqual(t, fm(3, 6), "4,3")
- assertEqual(t, fm(0, 0), "0,0")
-}
-
-func TestOutputFormatRangeFormatContext(t *testing.T) {
- // Per the diff spec at http://www.unix.org/single_unix_specification/
- //
- // The range of lines in file1 shall be written in the following format
- // if the range contains two or more lines:
- // "*** %d,%d ****\n", <beginning line number>, <ending line number>
- // and the following format otherwise:
- // "*** %d ****\n", <ending line number>
- // The ending line number of an empty range shall be the number of the preceding line,
- // or 0 if the range is at the start of the file.
- //
- // Next, the range of lines in file2 shall be written in the following format
- // if the range contains two or more lines:
- // "--- %d,%d ----\n", <beginning line number>, <ending line number>
- // and the following format otherwise:
- // "--- %d ----\n", <ending line number>
- fm := formatRangeContext
- assertEqual(t, fm(3, 3), "3")
- assertEqual(t, fm(3, 4), "4")
- assertEqual(t, fm(3, 5), "4,5")
- assertEqual(t, fm(3, 6), "4,6")
- assertEqual(t, fm(0, 0), "0")
-}
-
-func TestOutputFormatTabDelimiter(t *testing.T) {
- diff := UnifiedDiff{
- A: splitChars("one"),
- B: splitChars("two"),
- FromFile: "Original",
- FromDate: "2005-01-26 23:30:50",
- ToFile: "Current",
- ToDate: "2010-04-12 10:20:52",
- Eol: "\n",
- }
- ud, err := GetUnifiedDiffString(diff)
- assertEqual(t, err, nil)
- assertEqual(t, SplitLines(ud)[:2], []string{
- "--- Original\t2005-01-26 23:30:50\n",
- "+++ Current\t2010-04-12 10:20:52\n",
- })
- cd, err := GetContextDiffString(ContextDiff(diff))
- assertEqual(t, err, nil)
- assertEqual(t, SplitLines(cd)[:2], []string{
- "*** Original\t2005-01-26 23:30:50\n",
- "--- Current\t2010-04-12 10:20:52\n",
- })
-}
-
-func TestOutputFormatNoTrailingTabOnEmptyFiledate(t *testing.T) {
- diff := UnifiedDiff{
- A: splitChars("one"),
- B: splitChars("two"),
- FromFile: "Original",
- ToFile: "Current",
- Eol: "\n",
- }
- ud, err := GetUnifiedDiffString(diff)
- assertEqual(t, err, nil)
- assertEqual(t, SplitLines(ud)[:2], []string{"--- Original\n", "+++ Current\n"})
-
- cd, err := GetContextDiffString(ContextDiff(diff))
- assertEqual(t, err, nil)
- assertEqual(t, SplitLines(cd)[:2], []string{"*** Original\n", "--- Current\n"})
-}
-
-func TestSplitLines(t *testing.T) {
- allTests := []struct {
- input string
- want []string
- }{
- {"foo", []string{"foo\n"}},
- {"foo\nbar", []string{"foo\n", "bar\n"}},
- {"foo\nbar\n", []string{"foo\n", "bar\n", "\n"}},
- }
- for _, test := range allTests {
- assertEqual(t, SplitLines(test.input), test.want)
- }
-}
-
-func benchmarkSplitLines(b *testing.B, count int) {
- str := strings.Repeat("foo\n", count)
-
- b.ResetTimer()
-
- n := 0
- for i := 0; i < b.N; i++ {
- n += len(SplitLines(str))
- }
-}
-
-func BenchmarkSplitLines100(b *testing.B) {
- benchmarkSplitLines(b, 100)
-}
-
-func BenchmarkSplitLines10000(b *testing.B) {
- benchmarkSplitLines(b, 10000)
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/.gitignore b/Godeps/_workspace/src/github.com/stretchr/objx/.gitignore
deleted file mode 100644
index 00268614f..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/.gitignore
+++ /dev/null
@@ -1,22 +0,0 @@
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
-*.o
-*.a
-*.so
-
-# Folders
-_obj
-_test
-
-# Architecture specific extensions/prefixes
-*.[568vq]
-[568vq].out
-
-*.cgo1.go
-*.cgo2.c
-_cgo_defun.c
-_cgo_gotypes.go
-_cgo_export.*
-
-_testmain.go
-
-*.exe
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/LICENSE.md b/Godeps/_workspace/src/github.com/stretchr/objx/LICENSE.md
deleted file mode 100644
index 219994581..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/LICENSE.md
+++ /dev/null
@@ -1,23 +0,0 @@
-objx - by Mat Ryer and Tyler Bunnell
-
-The MIT License (MIT)
-
-Copyright (c) 2014 Stretchr, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/README.md b/Godeps/_workspace/src/github.com/stretchr/objx/README.md
deleted file mode 100644
index 4aa180687..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# objx
-
- * Jump into the [API Documentation](http://godoc.org/github.com/stretchr/objx)
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/accessors.go b/Godeps/_workspace/src/github.com/stretchr/objx/accessors.go
deleted file mode 100644
index 721bcac79..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/accessors.go
+++ /dev/null
@@ -1,179 +0,0 @@
-package objx
-
-import (
- "fmt"
- "regexp"
- "strconv"
- "strings"
-)
-
-// arrayAccesRegexString is the regex used to extract the array number
-// from the access path
-const arrayAccesRegexString = `^(.+)\[([0-9]+)\]$`
-
-// arrayAccesRegex is the compiled arrayAccesRegexString
-var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString)
-
-// Get gets the value using the specified selector and
-// returns it inside a new Obj object.
-//
-// If it cannot find the value, Get will return a nil
-// value inside an instance of Obj.
-//
-// Get can only operate directly on map[string]interface{} and []interface.
-//
-// Example
-//
-// To access the title of the third chapter of the second book, do:
-//
-// o.Get("books[1].chapters[2].title")
-func (m Map) Get(selector string) *Value {
- rawObj := access(m, selector, nil, false, false)
- return &Value{data: rawObj}
-}
-
-// Set sets the value using the specified selector and
-// returns the object on which Set was called.
-//
-// Set can only operate directly on map[string]interface{} and []interface
-//
-// Example
-//
-// To set the title of the third chapter of the second book, do:
-//
-// o.Set("books[1].chapters[2].title","Time to Go")
-func (m Map) Set(selector string, value interface{}) Map {
- access(m, selector, value, true, false)
- return m
-}
-
-// access accesses the object using the selector and performs the
-// appropriate action.
-func access(current, selector, value interface{}, isSet, panics bool) interface{} {
-
- switch selector.(type) {
- case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
-
- if array, ok := current.([]interface{}); ok {
- index := intFromInterface(selector)
-
- if index >= len(array) {
- if panics {
- panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array)))
- }
- return nil
- }
-
- return array[index]
- }
-
- return nil
-
- case string:
-
- selStr := selector.(string)
- selSegs := strings.SplitN(selStr, PathSeparator, 2)
- thisSel := selSegs[0]
- index := -1
- var err error
-
- // https://github.com/stretchr/objx/issues/12
- if strings.Contains(thisSel, "[") {
-
- arrayMatches := arrayAccesRegex.FindStringSubmatch(thisSel)
-
- if len(arrayMatches) > 0 {
-
- // Get the key into the map
- thisSel = arrayMatches[1]
-
- // Get the index into the array at the key
- index, err = strconv.Atoi(arrayMatches[2])
-
- if err != nil {
- // This should never happen. If it does, something has gone
- // seriously wrong. Panic.
- panic("objx: Array index is not an integer. Must use array[int].")
- }
-
- }
- }
-
- if curMap, ok := current.(Map); ok {
- current = map[string]interface{}(curMap)
- }
-
- // get the object in question
- switch current.(type) {
- case map[string]interface{}:
- curMSI := current.(map[string]interface{})
- if len(selSegs) <= 1 && isSet {
- curMSI[thisSel] = value
- return nil
- } else {
- current = curMSI[thisSel]
- }
- default:
- current = nil
- }
-
- if current == nil && panics {
- panic(fmt.Sprintf("objx: '%v' invalid on object.", selector))
- }
-
- // do we need to access the item of an array?
- if index > -1 {
- if array, ok := current.([]interface{}); ok {
- if index < len(array) {
- current = array[index]
- } else {
- if panics {
- panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array)))
- }
- current = nil
- }
- }
- }
-
- if len(selSegs) > 1 {
- current = access(current, selSegs[1], value, isSet, panics)
- }
-
- }
-
- return current
-
-}
-
-// intFromInterface converts an interface object to the largest
-// representation of an unsigned integer using a type switch and
-// assertions
-func intFromInterface(selector interface{}) int {
- var value int
- switch selector.(type) {
- case int:
- value = selector.(int)
- case int8:
- value = int(selector.(int8))
- case int16:
- value = int(selector.(int16))
- case int32:
- value = int(selector.(int32))
- case int64:
- value = int(selector.(int64))
- case uint:
- value = int(selector.(uint))
- case uint8:
- value = int(selector.(uint8))
- case uint16:
- value = int(selector.(uint16))
- case uint32:
- value = int(selector.(uint32))
- case uint64:
- value = int(selector.(uint64))
- default:
- panic("objx: array access argument is not an integer type (this should never happen)")
- }
-
- return value
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/accessors_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/accessors_test.go
deleted file mode 100644
index ce5d8e4aa..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/accessors_test.go
+++ /dev/null
@@ -1,145 +0,0 @@
-package objx
-
-import (
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-func TestAccessorsAccessGetSingleField(t *testing.T) {
-
- current := map[string]interface{}{"name": "Tyler"}
- assert.Equal(t, "Tyler", access(current, "name", nil, false, true))
-
-}
-func TestAccessorsAccessGetDeep(t *testing.T) {
-
- current := map[string]interface{}{"name": map[string]interface{}{"first": "Tyler", "last": "Bunnell"}}
- assert.Equal(t, "Tyler", access(current, "name.first", nil, false, true))
- assert.Equal(t, "Bunnell", access(current, "name.last", nil, false, true))
-
-}
-func TestAccessorsAccessGetDeepDeep(t *testing.T) {
-
- current := map[string]interface{}{"one": map[string]interface{}{"two": map[string]interface{}{"three": map[string]interface{}{"four": 4}}}}
- assert.Equal(t, 4, access(current, "one.two.three.four", nil, false, true))
-
-}
-func TestAccessorsAccessGetInsideArray(t *testing.T) {
-
- current := map[string]interface{}{"names": []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}}}
- assert.Equal(t, "Tyler", access(current, "names[0].first", nil, false, true))
- assert.Equal(t, "Bunnell", access(current, "names[0].last", nil, false, true))
- assert.Equal(t, "Capitol", access(current, "names[1].first", nil, false, true))
- assert.Equal(t, "Bollocks", access(current, "names[1].last", nil, false, true))
-
- assert.Panics(t, func() {
- access(current, "names[2]", nil, false, true)
- })
- assert.Nil(t, access(current, "names[2]", nil, false, false))
-
-}
-
-func TestAccessorsAccessGetFromArrayWithInt(t *testing.T) {
-
- current := []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}}
- one := access(current, 0, nil, false, false)
- two := access(current, 1, nil, false, false)
- three := access(current, 2, nil, false, false)
-
- assert.Equal(t, "Tyler", one.(map[string]interface{})["first"])
- assert.Equal(t, "Capitol", two.(map[string]interface{})["first"])
- assert.Nil(t, three)
-
-}
-
-func TestAccessorsGet(t *testing.T) {
-
- current := New(map[string]interface{}{"name": "Tyler"})
- assert.Equal(t, "Tyler", current.Get("name").data)
-
-}
-
-func TestAccessorsAccessSetSingleField(t *testing.T) {
-
- current := map[string]interface{}{"name": "Tyler"}
- access(current, "name", "Mat", true, false)
- assert.Equal(t, current["name"], "Mat")
-
- access(current, "age", 29, true, true)
- assert.Equal(t, current["age"], 29)
-
-}
-
-func TestAccessorsAccessSetSingleFieldNotExisting(t *testing.T) {
-
- current := map[string]interface{}{}
- access(current, "name", "Mat", true, false)
- assert.Equal(t, current["name"], "Mat")
-
-}
-
-func TestAccessorsAccessSetDeep(t *testing.T) {
-
- current := map[string]interface{}{"name": map[string]interface{}{"first": "Tyler", "last": "Bunnell"}}
-
- access(current, "name.first", "Mat", true, true)
- access(current, "name.last", "Ryer", true, true)
-
- assert.Equal(t, "Mat", access(current, "name.first", nil, false, true))
- assert.Equal(t, "Ryer", access(current, "name.last", nil, false, true))
-
-}
-func TestAccessorsAccessSetDeepDeep(t *testing.T) {
-
- current := map[string]interface{}{"one": map[string]interface{}{"two": map[string]interface{}{"three": map[string]interface{}{"four": 4}}}}
-
- access(current, "one.two.three.four", 5, true, true)
-
- assert.Equal(t, 5, access(current, "one.two.three.four", nil, false, true))
-
-}
-func TestAccessorsAccessSetArray(t *testing.T) {
-
- current := map[string]interface{}{"names": []interface{}{"Tyler"}}
-
- access(current, "names[0]", "Mat", true, true)
-
- assert.Equal(t, "Mat", access(current, "names[0]", nil, false, true))
-
-}
-func TestAccessorsAccessSetInsideArray(t *testing.T) {
-
- current := map[string]interface{}{"names": []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}}}
-
- access(current, "names[0].first", "Mat", true, true)
- access(current, "names[0].last", "Ryer", true, true)
- access(current, "names[1].first", "Captain", true, true)
- access(current, "names[1].last", "Underpants", true, true)
-
- assert.Equal(t, "Mat", access(current, "names[0].first", nil, false, true))
- assert.Equal(t, "Ryer", access(current, "names[0].last", nil, false, true))
- assert.Equal(t, "Captain", access(current, "names[1].first", nil, false, true))
- assert.Equal(t, "Underpants", access(current, "names[1].last", nil, false, true))
-
-}
-
-func TestAccessorsAccessSetFromArrayWithInt(t *testing.T) {
-
- current := []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}}
- one := access(current, 0, nil, false, false)
- two := access(current, 1, nil, false, false)
- three := access(current, 2, nil, false, false)
-
- assert.Equal(t, "Tyler", one.(map[string]interface{})["first"])
- assert.Equal(t, "Capitol", two.(map[string]interface{})["first"])
- assert.Nil(t, three)
-
-}
-
-func TestAccessorsSet(t *testing.T) {
-
- current := New(map[string]interface{}{"name": "Tyler"})
- current.Set("name", "Mat")
- assert.Equal(t, "Mat", current.Get("name").data)
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt
deleted file mode 100644
index 306023475..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt
+++ /dev/null
@@ -1,14 +0,0 @@
- case []{1}:
- a := object.([]{1})
- if isSet {
- a[index] = value.({1})
- } else {
- if index >= len(a) {
- if panics {
- panic(fmt.Sprintf("objx: Index %d is out of range because the []{1} only contains %d items.", index, len(a)))
- }
- return nil
- } else {
- return a[index]
- }
- }
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html
deleted file mode 100644
index 379ffc3c0..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<html>
- <head>
- <title>
- Codegen
- </title>
- <style>
- body {
- width: 800px;
- margin: auto;
- }
- textarea {
- width: 100%;
- min-height: 100px;
- font-family: Courier;
- }
- </style>
- </head>
- <body>
-
- <h2>
- Template
- </h2>
- <p>
- Use <code>{x}</code> as a placeholder for each argument.
- </p>
- <textarea id="template"></textarea>
-
- <h2>
- Arguments (comma separated)
- </h2>
- <p>
- One block per line
- </p>
- <textarea id="args"></textarea>
-
- <h2>
- Output
- </h2>
- <input id="go" type="button" value="Generate code" />
-
- <textarea id="output"></textarea>
-
- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
- <script>
-
- $(function(){
-
- $("#go").click(function(){
-
- var output = ""
- var template = $("#template").val()
- var args = $("#args").val()
-
- // collect the args
- var argLines = args.split("\n")
- for (var line in argLines) {
-
- var argLine = argLines[line];
- var thisTemp = template
-
- // get individual args
- var args = argLine.split(",")
-
- for (var argI in args) {
- var argText = args[argI];
- var argPlaceholder = "{" + argI + "}";
-
- while (thisTemp.indexOf(argPlaceholder) > -1) {
- thisTemp = thisTemp.replace(argPlaceholder, argText);
- }
-
- }
-
- output += thisTemp
-
- }
-
- $("#output").val(output);
-
- });
-
- });
-
- </script>
- </body>
-</html>
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt
deleted file mode 100644
index b396900b8..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- {4} ({1} and []{1})
- --------------------------------------------------
-*/
-
-// {4} gets the value as a {1}, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) {4}(optionalDefault ...{1}) {1} {
- if s, ok := v.data.({1}); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return {3}
-}
-
-// Must{4} gets the value as a {1}.
-//
-// Panics if the object is not a {1}.
-func (v *Value) Must{4}() {1} {
- return v.data.({1})
-}
-
-// {4}Slice gets the value as a []{1}, returns the optionalDefault
-// value or nil if the value is not a []{1}.
-func (v *Value) {4}Slice(optionalDefault ...[]{1}) []{1} {
- if s, ok := v.data.([]{1}); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// Must{4}Slice gets the value as a []{1}.
-//
-// Panics if the object is not a []{1}.
-func (v *Value) Must{4}Slice() []{1} {
- return v.data.([]{1})
-}
-
-// Is{4} gets whether the object contained is a {1} or not.
-func (v *Value) Is{4}() bool {
- _, ok := v.data.({1})
- return ok
-}
-
-// Is{4}Slice gets whether the object contained is a []{1} or not.
-func (v *Value) Is{4}Slice() bool {
- _, ok := v.data.([]{1})
- return ok
-}
-
-// Each{4} calls the specified callback for each object
-// in the []{1}.
-//
-// Panics if the object is the wrong type.
-func (v *Value) Each{4}(callback func(int, {1}) bool) *Value {
-
- for index, val := range v.Must{4}Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// Where{4} uses the specified decider function to select items
-// from the []{1}. The object contained in the result will contain
-// only the selected items.
-func (v *Value) Where{4}(decider func(int, {1}) bool) *Value {
-
- var selected []{1}
-
- v.Each{4}(func(index int, val {1}) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data:selected}
-
-}
-
-// Group{4} uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]{1}.
-func (v *Value) Group{4}(grouper func(int, {1}) string) *Value {
-
- groups := make(map[string][]{1})
-
- v.Each{4}(func(index int, val {1}) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]{1}, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data:groups}
-
-}
-
-// Replace{4} uses the specified function to replace each {1}s
-// by iterating each item. The data in the returned result will be a
-// []{1} containing the replaced items.
-func (v *Value) Replace{4}(replacer func(int, {1}) {1}) *Value {
-
- arr := v.Must{4}Slice()
- replaced := make([]{1}, len(arr))
-
- v.Each{4}(func(index int, val {1}) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data:replaced}
-
-}
-
-// Collect{4} uses the specified collector function to collect a value
-// for each of the {1}s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) Collect{4}(collector func(int, {1}) interface{}) *Value {
-
- arr := v.Must{4}Slice()
- collected := make([]interface{}, len(arr))
-
- v.Each{4}(func(index int, val {1}) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data:collected}
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func Test{4}(t *testing.T) {
-
- val := {1}( {2} )
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").{4}())
- assert.Equal(t, val, New(m).Get("value").Must{4}())
- assert.Equal(t, {1}({3}), New(m).Get("nothing").{4}())
- assert.Equal(t, val, New(m).Get("nothing").{4}({2}))
-
- assert.Panics(t, func() {
- New(m).Get("age").Must{4}()
- })
-
-}
-
-func Test{4}Slice(t *testing.T) {
-
- val := {1}( {2} )
- m := map[string]interface{}{"value": []{1}{ val }, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").{4}Slice()[0])
- assert.Equal(t, val, New(m).Get("value").Must{4}Slice()[0])
- assert.Equal(t, []{1}(nil), New(m).Get("nothing").{4}Slice())
- assert.Equal(t, val, New(m).Get("nothing").{4}Slice( []{1}{ {1}({2}) } )[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").Must{4}Slice()
- })
-
-}
-
-func TestIs{4}(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: {1}({2})}
- assert.True(t, v.Is{4}())
-
- v = &Value{data: []{1}{ {1}({2}) }}
- assert.True(t, v.Is{4}Slice())
-
-}
-
-func TestEach{4}(t *testing.T) {
-
- v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
- count := 0
- replacedVals := make([]{1}, 0)
- assert.Equal(t, v, v.Each{4}(func(i int, val {1}) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.Must{4}Slice()[0])
- assert.Equal(t, replacedVals[1], v.Must{4}Slice()[1])
- assert.Equal(t, replacedVals[2], v.Must{4}Slice()[2])
-
-}
-
-func TestWhere{4}(t *testing.T) {
-
- v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
-
- selected := v.Where{4}(func(i int, val {1}) bool {
- return i%2==0
- }).Must{4}Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroup{4}(t *testing.T) {
-
- v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
-
- grouped := v.Group{4}(func(i int, val {1}) string {
- return fmt.Sprintf("%v", i%2==0)
- }).data.(map[string][]{1})
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplace{4}(t *testing.T) {
-
- v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
-
- rawArr := v.Must{4}Slice()
-
- replaced := v.Replace{4}(func(index int, val {1}) {1} {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.Must{4}Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollect{4}(t *testing.T) {
-
- v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
-
- collected := v.Collect{4}(func(index int, val {1}) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt
deleted file mode 100644
index 069d43d8e..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Interface,interface{},"something",nil,Inter
-Map,map[string]interface{},map[string]interface{}{"name":"Tyler"},nil,MSI
-ObjxMap,(Map),New(1),New(nil),ObjxMap
-Bool,bool,true,false,Bool
-String,string,"hello","",Str
-Int,int,1,0,Int
-Int8,int8,1,0,Int8
-Int16,int16,1,0,Int16
-Int32,int32,1,0,Int32
-Int64,int64,1,0,Int64
-Uint,uint,1,0,Uint
-Uint8,uint8,1,0,Uint8
-Uint16,uint16,1,0,Uint16
-Uint32,uint32,1,0,Uint32
-Uint64,uint64,1,0,Uint64
-Uintptr,uintptr,1,0,Uintptr
-Float32,float32,1,0,Float32
-Float64,float64,1,0,Float64
-Complex64,complex64,1,0,Complex64
-Complex128,complex128,1,0,Complex128
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/constants.go b/Godeps/_workspace/src/github.com/stretchr/objx/constants.go
deleted file mode 100644
index f9eb42a25..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/constants.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package objx
-
-const (
- // PathSeparator is the character used to separate the elements
- // of the keypath.
- //
- // For example, `location.address.city`
- PathSeparator string = "."
-
- // SignatureSeparator is the character that is used to
- // separate the Base64 string from the security signature.
- SignatureSeparator = "_"
-)
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/conversions.go b/Godeps/_workspace/src/github.com/stretchr/objx/conversions.go
deleted file mode 100644
index 9cdfa9f9f..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/conversions.go
+++ /dev/null
@@ -1,117 +0,0 @@
-package objx
-
-import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "net/url"
-)
-
-// JSON converts the contained object to a JSON string
-// representation
-func (m Map) JSON() (string, error) {
-
- result, err := json.Marshal(m)
-
- if err != nil {
- err = errors.New("objx: JSON encode failed with: " + err.Error())
- }
-
- return string(result), err
-
-}
-
-// MustJSON converts the contained object to a JSON string
-// representation and panics if there is an error
-func (m Map) MustJSON() string {
- result, err := m.JSON()
- if err != nil {
- panic(err.Error())
- }
- return result
-}
-
-// Base64 converts the contained object to a Base64 string
-// representation of the JSON string representation
-func (m Map) Base64() (string, error) {
-
- var buf bytes.Buffer
-
- jsonData, err := m.JSON()
- if err != nil {
- return "", err
- }
-
- encoder := base64.NewEncoder(base64.StdEncoding, &buf)
- encoder.Write([]byte(jsonData))
- encoder.Close()
-
- return buf.String(), nil
-
-}
-
-// MustBase64 converts the contained object to a Base64 string
-// representation of the JSON string representation and panics
-// if there is an error
-func (m Map) MustBase64() string {
- result, err := m.Base64()
- if err != nil {
- panic(err.Error())
- }
- return result
-}
-
-// SignedBase64 converts the contained object to a Base64 string
-// representation of the JSON string representation and signs it
-// using the provided key.
-func (m Map) SignedBase64(key string) (string, error) {
-
- base64, err := m.Base64()
- if err != nil {
- return "", err
- }
-
- sig := HashWithKey(base64, key)
-
- return base64 + SignatureSeparator + sig, nil
-
-}
-
-// MustSignedBase64 converts the contained object to a Base64 string
-// representation of the JSON string representation and signs it
-// using the provided key and panics if there is an error
-func (m Map) MustSignedBase64(key string) string {
- result, err := m.SignedBase64(key)
- if err != nil {
- panic(err.Error())
- }
- return result
-}
-
-/*
- URL Query
- ------------------------------------------------
-*/
-
-// URLValues creates a url.Values object from an Obj. This
-// function requires that the wrapped object be a map[string]interface{}
-func (m Map) URLValues() url.Values {
-
- vals := make(url.Values)
-
- for k, v := range m {
- //TODO: can this be done without sprintf?
- vals.Set(k, fmt.Sprintf("%v", v))
- }
-
- return vals
-}
-
-// URLQuery gets an encoded URL query representing the given
-// Obj. This function requires that the wrapped object be a
-// map[string]interface{}
-func (m Map) URLQuery() (string, error) {
- return m.URLValues().Encode(), nil
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/conversions_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/conversions_test.go
deleted file mode 100644
index e9ccd2987..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/conversions_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package objx
-
-import (
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-func TestConversionJSON(t *testing.T) {
-
- jsonString := `{"name":"Mat"}`
- o := MustFromJSON(jsonString)
-
- result, err := o.JSON()
-
- if assert.NoError(t, err) {
- assert.Equal(t, jsonString, result)
- }
-
- assert.Equal(t, jsonString, o.MustJSON())
-
-}
-
-func TestConversionJSONWithError(t *testing.T) {
-
- o := MSI()
- o["test"] = func() {}
-
- assert.Panics(t, func() {
- o.MustJSON()
- })
-
- _, err := o.JSON()
-
- assert.Error(t, err)
-
-}
-
-func TestConversionBase64(t *testing.T) {
-
- o := New(map[string]interface{}{"name": "Mat"})
-
- result, err := o.Base64()
-
- if assert.NoError(t, err) {
- assert.Equal(t, "eyJuYW1lIjoiTWF0In0=", result)
- }
-
- assert.Equal(t, "eyJuYW1lIjoiTWF0In0=", o.MustBase64())
-
-}
-
-func TestConversionBase64WithError(t *testing.T) {
-
- o := MSI()
- o["test"] = func() {}
-
- assert.Panics(t, func() {
- o.MustBase64()
- })
-
- _, err := o.Base64()
-
- assert.Error(t, err)
-
-}
-
-func TestConversionSignedBase64(t *testing.T) {
-
- o := New(map[string]interface{}{"name": "Mat"})
-
- result, err := o.SignedBase64("key")
-
- if assert.NoError(t, err) {
- assert.Equal(t, "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6", result)
- }
-
- assert.Equal(t, "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6", o.MustSignedBase64("key"))
-
-}
-
-func TestConversionSignedBase64WithError(t *testing.T) {
-
- o := MSI()
- o["test"] = func() {}
-
- assert.Panics(t, func() {
- o.MustSignedBase64("key")
- })
-
- _, err := o.SignedBase64("key")
-
- assert.Error(t, err)
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/doc.go b/Godeps/_workspace/src/github.com/stretchr/objx/doc.go
deleted file mode 100644
index 47bf85e46..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/doc.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// objx - Go package for dealing with maps, slices, JSON and other data.
-//
-// Overview
-//
-// Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes
-// a powerful `Get` method (among others) that allows you to easily and quickly get
-// access to data within the map, without having to worry too much about type assertions,
-// missing data, default values etc.
-//
-// Pattern
-//
-// Objx uses a preditable pattern to make access data from within `map[string]interface{}'s
-// easy.
-//
-// Call one of the `objx.` functions to create your `objx.Map` to get going:
-//
-// m, err := objx.FromJSON(json)
-//
-// NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong,
-// the rest will be optimistic and try to figure things out without panicking.
-//
-// Use `Get` to access the value you're interested in. You can use dot and array
-// notation too:
-//
-// m.Get("places[0].latlng")
-//
-// Once you have saught the `Value` you're interested in, you can use the `Is*` methods
-// to determine its type.
-//
-// if m.Get("code").IsStr() { /* ... */ }
-//
-// Or you can just assume the type, and use one of the strong type methods to
-// extract the real value:
-//
-// m.Get("code").Int()
-//
-// If there's no value there (or if it's the wrong type) then a default value
-// will be returned, or you can be explicit about the default value.
-//
-// Get("code").Int(-1)
-//
-// If you're dealing with a slice of data as a value, Objx provides many useful
-// methods for iterating, manipulating and selecting that data. You can find out more
-// by exploring the index below.
-//
-// Reading data
-//
-// A simple example of how to use Objx:
-//
-// // use MustFromJSON to make an objx.Map from some JSON
-// m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`)
-//
-// // get the details
-// name := m.Get("name").Str()
-// age := m.Get("age").Int()
-//
-// // get their nickname (or use their name if they
-// // don't have one)
-// nickname := m.Get("nickname").Str(name)
-//
-// Ranging
-//
-// Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For
-// example, to `range` the data, do what you would expect:
-//
-// m := objx.MustFromJSON(json)
-// for key, value := range m {
-//
-// /* ... do your magic ... */
-//
-// }
-package objx
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/fixture_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/fixture_test.go
deleted file mode 100644
index 27f7d9049..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/fixture_test.go
+++ /dev/null
@@ -1,98 +0,0 @@
-package objx
-
-import (
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-var fixtures = []struct {
- // name is the name of the fixture (used for reporting
- // failures)
- name string
- // data is the JSON data to be worked on
- data string
- // get is the argument(s) to pass to Get
- get interface{}
- // output is the expected output
- output interface{}
-}{
- {
- name: "Simple get",
- data: `{"name": "Mat"}`,
- get: "name",
- output: "Mat",
- },
- {
- name: "Get with dot notation",
- data: `{"address": {"city": "Boulder"}}`,
- get: "address.city",
- output: "Boulder",
- },
- {
- name: "Deep get with dot notation",
- data: `{"one": {"two": {"three": {"four": "hello"}}}}`,
- get: "one.two.three.four",
- output: "hello",
- },
- {
- name: "Get missing with dot notation",
- data: `{"one": {"two": {"three": {"four": "hello"}}}}`,
- get: "one.ten",
- output: nil,
- },
- {
- name: "Get with array notation",
- data: `{"tags": ["one", "two", "three"]}`,
- get: "tags[1]",
- output: "two",
- },
- {
- name: "Get with array and dot notation",
- data: `{"types": { "tags": ["one", "two", "three"]}}`,
- get: "types.tags[1]",
- output: "two",
- },
- {
- name: "Get with array and dot notation - field after array",
- data: `{"tags": [{"name":"one"}, {"name":"two"}, {"name":"three"}]}`,
- get: "tags[1].name",
- output: "two",
- },
- {
- name: "Complex get with array and dot notation",
- data: `{"tags": [{"list": [{"one":"pizza"}]}]}`,
- get: "tags[0].list[0].one",
- output: "pizza",
- },
- {
- name: "Get field from within string should be nil",
- data: `{"name":"Tyler"}`,
- get: "name.something",
- output: nil,
- },
- {
- name: "Get field from within string (using array accessor) should be nil",
- data: `{"numbers":["one", "two", "three"]}`,
- get: "numbers[0].nope",
- output: nil,
- },
-}
-
-func TestFixtures(t *testing.T) {
-
- for _, fixture := range fixtures {
-
- m := MustFromJSON(fixture.data)
-
- // get the value
- t.Logf("Running get fixture: \"%s\" (%v)", fixture.name, fixture)
- value := m.Get(fixture.get.(string))
-
- // make sure it matches
- assert.Equal(t, fixture.output, value.data,
- "Get fixture \"%s\" failed: %v", fixture.name, fixture,
- )
-
- }
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/map.go b/Godeps/_workspace/src/github.com/stretchr/objx/map.go
deleted file mode 100644
index eb6ed8e28..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/map.go
+++ /dev/null
@@ -1,222 +0,0 @@
-package objx
-
-import (
- "encoding/base64"
- "encoding/json"
- "errors"
- "io/ioutil"
- "net/url"
- "strings"
-)
-
-// MSIConvertable is an interface that defines methods for converting your
-// custom types to a map[string]interface{} representation.
-type MSIConvertable interface {
- // MSI gets a map[string]interface{} (msi) representing the
- // object.
- MSI() map[string]interface{}
-}
-
-// Map provides extended functionality for working with
-// untyped data, in particular map[string]interface (msi).
-type Map map[string]interface{}
-
-// Value returns the internal value instance
-func (m Map) Value() *Value {
- return &Value{data: m}
-}
-
-// Nil represents a nil Map.
-var Nil Map = New(nil)
-
-// New creates a new Map containing the map[string]interface{} in the data argument.
-// If the data argument is not a map[string]interface, New attempts to call the
-// MSI() method on the MSIConvertable interface to create one.
-func New(data interface{}) Map {
- if _, ok := data.(map[string]interface{}); !ok {
- if converter, ok := data.(MSIConvertable); ok {
- data = converter.MSI()
- } else {
- return nil
- }
- }
- return Map(data.(map[string]interface{}))
-}
-
-// MSI creates a map[string]interface{} and puts it inside a new Map.
-//
-// The arguments follow a key, value pattern.
-//
-// Panics
-//
-// Panics if any key arugment is non-string or if there are an odd number of arguments.
-//
-// Example
-//
-// To easily create Maps:
-//
-// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true))
-//
-// // creates an Map equivalent to
-// m := objx.New(map[string]interface{}{"name": "Mat", "age": 29, "subobj": map[string]interface{}{"active": true}})
-func MSI(keyAndValuePairs ...interface{}) Map {
-
- newMap := make(map[string]interface{})
- keyAndValuePairsLen := len(keyAndValuePairs)
-
- if keyAndValuePairsLen%2 != 0 {
- panic("objx: MSI must have an even number of arguments following the 'key, value' pattern.")
- }
-
- for i := 0; i < keyAndValuePairsLen; i = i + 2 {
-
- key := keyAndValuePairs[i]
- value := keyAndValuePairs[i+1]
-
- // make sure the key is a string
- keyString, keyStringOK := key.(string)
- if !keyStringOK {
- panic("objx: MSI must follow 'string, interface{}' pattern. " + keyString + " is not a valid key.")
- }
-
- newMap[keyString] = value
-
- }
-
- return New(newMap)
-}
-
-// ****** Conversion Constructors
-
-// MustFromJSON creates a new Map containing the data specified in the
-// jsonString.
-//
-// Panics if the JSON is invalid.
-func MustFromJSON(jsonString string) Map {
- o, err := FromJSON(jsonString)
-
- if err != nil {
- panic("objx: MustFromJSON failed with error: " + err.Error())
- }
-
- return o
-}
-
-// FromJSON creates a new Map containing the data specified in the
-// jsonString.
-//
-// Returns an error if the JSON is invalid.
-func FromJSON(jsonString string) (Map, error) {
-
- var data interface{}
- err := json.Unmarshal([]byte(jsonString), &data)
-
- if err != nil {
- return Nil, err
- }
-
- return New(data), nil
-
-}
-
-// FromBase64 creates a new Obj containing the data specified
-// in the Base64 string.
-//
-// The string is an encoded JSON string returned by Base64
-func FromBase64(base64String string) (Map, error) {
-
- decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64String))
-
- decoded, err := ioutil.ReadAll(decoder)
- if err != nil {
- return nil, err
- }
-
- return FromJSON(string(decoded))
-}
-
-// MustFromBase64 creates a new Obj containing the data specified
-// in the Base64 string and panics if there is an error.
-//
-// The string is an encoded JSON string returned by Base64
-func MustFromBase64(base64String string) Map {
-
- result, err := FromBase64(base64String)
-
- if err != nil {
- panic("objx: MustFromBase64 failed with error: " + err.Error())
- }
-
- return result
-}
-
-// FromSignedBase64 creates a new Obj containing the data specified
-// in the Base64 string.
-//
-// The string is an encoded JSON string returned by SignedBase64
-func FromSignedBase64(base64String, key string) (Map, error) {
- parts := strings.Split(base64String, SignatureSeparator)
- if len(parts) != 2 {
- return nil, errors.New("objx: Signed base64 string is malformed.")
- }
-
- sig := HashWithKey(parts[0], key)
- if parts[1] != sig {
- return nil, errors.New("objx: Signature for base64 data does not match.")
- }
-
- return FromBase64(parts[0])
-}
-
-// MustFromSignedBase64 creates a new Obj containing the data specified
-// in the Base64 string and panics if there is an error.
-//
-// The string is an encoded JSON string returned by Base64
-func MustFromSignedBase64(base64String, key string) Map {
-
- result, err := FromSignedBase64(base64String, key)
-
- if err != nil {
- panic("objx: MustFromSignedBase64 failed with error: " + err.Error())
- }
-
- return result
-}
-
-// FromURLQuery generates a new Obj by parsing the specified
-// query.
-//
-// For queries with multiple values, the first value is selected.
-func FromURLQuery(query string) (Map, error) {
-
- vals, err := url.ParseQuery(query)
-
- if err != nil {
- return nil, err
- }
-
- m := make(map[string]interface{})
- for k, vals := range vals {
- m[k] = vals[0]
- }
-
- return New(m), nil
-}
-
-// MustFromURLQuery generates a new Obj by parsing the specified
-// query.
-//
-// For queries with multiple values, the first value is selected.
-//
-// Panics if it encounters an error
-func MustFromURLQuery(query string) Map {
-
- o, err := FromURLQuery(query)
-
- if err != nil {
- panic("objx: MustFromURLQuery failed with error: " + err.Error())
- }
-
- return o
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/map_for_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/map_for_test.go
deleted file mode 100644
index 6beb50675..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/map_for_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package objx
-
-var TestMap map[string]interface{} = map[string]interface{}{
- "name": "Tyler",
- "address": map[string]interface{}{
- "city": "Salt Lake City",
- "state": "UT",
- },
- "numbers": []interface{}{"one", "two", "three", "four", "five"},
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/map_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/map_test.go
deleted file mode 100644
index 1f8b45c61..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/map_test.go
+++ /dev/null
@@ -1,147 +0,0 @@
-package objx
-
-import (
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-type Convertable struct {
- name string
-}
-
-func (c *Convertable) MSI() map[string]interface{} {
- return map[string]interface{}{"name": c.name}
-}
-
-type Unconvertable struct {
- name string
-}
-
-func TestMapCreation(t *testing.T) {
-
- o := New(nil)
- assert.Nil(t, o)
-
- o = New("Tyler")
- assert.Nil(t, o)
-
- unconvertable := &Unconvertable{name: "Tyler"}
- o = New(unconvertable)
- assert.Nil(t, o)
-
- convertable := &Convertable{name: "Tyler"}
- o = New(convertable)
- if assert.NotNil(t, convertable) {
- assert.Equal(t, "Tyler", o["name"], "Tyler")
- }
-
- o = MSI()
- if assert.NotNil(t, o) {
- assert.NotNil(t, o)
- }
-
- o = MSI("name", "Tyler")
- if assert.NotNil(t, o) {
- if assert.NotNil(t, o) {
- assert.Equal(t, o["name"], "Tyler")
- }
- }
-
-}
-
-func TestMapMustFromJSONWithError(t *testing.T) {
-
- _, err := FromJSON(`"name":"Mat"}`)
- assert.Error(t, err)
-
-}
-
-func TestMapFromJSON(t *testing.T) {
-
- o := MustFromJSON(`{"name":"Mat"}`)
-
- if assert.NotNil(t, o) {
- if assert.NotNil(t, o) {
- assert.Equal(t, "Mat", o["name"])
- }
- }
-
-}
-
-func TestMapFromJSONWithError(t *testing.T) {
-
- var m Map
-
- assert.Panics(t, func() {
- m = MustFromJSON(`"name":"Mat"}`)
- })
-
- assert.Nil(t, m)
-
-}
-
-func TestMapFromBase64String(t *testing.T) {
-
- base64String := "eyJuYW1lIjoiTWF0In0="
-
- o, err := FromBase64(base64String)
-
- if assert.NoError(t, err) {
- assert.Equal(t, o.Get("name").Str(), "Mat")
- }
-
- assert.Equal(t, MustFromBase64(base64String).Get("name").Str(), "Mat")
-
-}
-
-func TestMapFromBase64StringWithError(t *testing.T) {
-
- base64String := "eyJuYW1lIjoiTWFasd0In0="
-
- _, err := FromBase64(base64String)
-
- assert.Error(t, err)
-
- assert.Panics(t, func() {
- MustFromBase64(base64String)
- })
-
-}
-
-func TestMapFromSignedBase64String(t *testing.T) {
-
- base64String := "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6"
-
- o, err := FromSignedBase64(base64String, "key")
-
- if assert.NoError(t, err) {
- assert.Equal(t, o.Get("name").Str(), "Mat")
- }
-
- assert.Equal(t, MustFromSignedBase64(base64String, "key").Get("name").Str(), "Mat")
-
-}
-
-func TestMapFromSignedBase64StringWithError(t *testing.T) {
-
- base64String := "eyJuYW1lasdIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6"
-
- _, err := FromSignedBase64(base64String, "key")
-
- assert.Error(t, err)
-
- assert.Panics(t, func() {
- MustFromSignedBase64(base64String, "key")
- })
-
-}
-
-func TestMapFromURLQuery(t *testing.T) {
-
- m, err := FromURLQuery("name=tyler&state=UT")
- if assert.NoError(t, err) && assert.NotNil(t, m) {
- assert.Equal(t, "tyler", m.Get("name").Str())
- assert.Equal(t, "UT", m.Get("state").Str())
- }
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/mutations.go b/Godeps/_workspace/src/github.com/stretchr/objx/mutations.go
deleted file mode 100644
index b35c86392..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/mutations.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package objx
-
-// Exclude returns a new Map with the keys in the specified []string
-// excluded.
-func (d Map) Exclude(exclude []string) Map {
-
- excluded := make(Map)
- for k, v := range d {
- var shouldInclude bool = true
- for _, toExclude := range exclude {
- if k == toExclude {
- shouldInclude = false
- break
- }
- }
- if shouldInclude {
- excluded[k] = v
- }
- }
-
- return excluded
-}
-
-// Copy creates a shallow copy of the Obj.
-func (m Map) Copy() Map {
- copied := make(map[string]interface{})
- for k, v := range m {
- copied[k] = v
- }
- return New(copied)
-}
-
-// Merge blends the specified map with a copy of this map and returns the result.
-//
-// Keys that appear in both will be selected from the specified map.
-// This method requires that the wrapped object be a map[string]interface{}
-func (m Map) Merge(merge Map) Map {
- return m.Copy().MergeHere(merge)
-}
-
-// Merge blends the specified map with this map and returns the current map.
-//
-// Keys that appear in both will be selected from the specified map. The original map
-// will be modified. This method requires that
-// the wrapped object be a map[string]interface{}
-func (m Map) MergeHere(merge Map) Map {
-
- for k, v := range merge {
- m[k] = v
- }
-
- return m
-
-}
-
-// Transform builds a new Obj giving the transformer a chance
-// to change the keys and values as it goes. This method requires that
-// the wrapped object be a map[string]interface{}
-func (m Map) Transform(transformer func(key string, value interface{}) (string, interface{})) Map {
- newMap := make(map[string]interface{})
- for k, v := range m {
- modifiedKey, modifiedVal := transformer(k, v)
- newMap[modifiedKey] = modifiedVal
- }
- return New(newMap)
-}
-
-// TransformKeys builds a new map using the specified key mapping.
-//
-// Unspecified keys will be unaltered.
-// This method requires that the wrapped object be a map[string]interface{}
-func (m Map) TransformKeys(mapping map[string]string) Map {
- return m.Transform(func(key string, value interface{}) (string, interface{}) {
-
- if newKey, ok := mapping[key]; ok {
- return newKey, value
- }
-
- return key, value
- })
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/mutations_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/mutations_test.go
deleted file mode 100644
index e20ee23bc..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/mutations_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package objx
-
-import (
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-func TestExclude(t *testing.T) {
-
- d := make(Map)
- d["name"] = "Mat"
- d["age"] = 29
- d["secret"] = "ABC"
-
- excluded := d.Exclude([]string{"secret"})
-
- assert.Equal(t, d["name"], excluded["name"])
- assert.Equal(t, d["age"], excluded["age"])
- assert.False(t, excluded.Has("secret"), "secret should be excluded")
-
-}
-
-func TestCopy(t *testing.T) {
-
- d1 := make(map[string]interface{})
- d1["name"] = "Tyler"
- d1["location"] = "UT"
-
- d1Obj := New(d1)
- d2Obj := d1Obj.Copy()
-
- d2Obj["name"] = "Mat"
-
- assert.Equal(t, d1Obj.Get("name").Str(), "Tyler")
- assert.Equal(t, d2Obj.Get("name").Str(), "Mat")
-
-}
-
-func TestMerge(t *testing.T) {
-
- d := make(map[string]interface{})
- d["name"] = "Mat"
-
- d1 := make(map[string]interface{})
- d1["name"] = "Tyler"
- d1["location"] = "UT"
-
- dObj := New(d)
- d1Obj := New(d1)
-
- merged := dObj.Merge(d1Obj)
-
- assert.Equal(t, merged.Get("name").Str(), d1Obj.Get("name").Str())
- assert.Equal(t, merged.Get("location").Str(), d1Obj.Get("location").Str())
- assert.Empty(t, dObj.Get("location").Str())
-
-}
-
-func TestMergeHere(t *testing.T) {
-
- d := make(map[string]interface{})
- d["name"] = "Mat"
-
- d1 := make(map[string]interface{})
- d1["name"] = "Tyler"
- d1["location"] = "UT"
-
- dObj := New(d)
- d1Obj := New(d1)
-
- merged := dObj.MergeHere(d1Obj)
-
- assert.Equal(t, dObj, merged, "With MergeHere, it should return the first modified map")
- assert.Equal(t, merged.Get("name").Str(), d1Obj.Get("name").Str())
- assert.Equal(t, merged.Get("location").Str(), d1Obj.Get("location").Str())
- assert.Equal(t, merged.Get("location").Str(), dObj.Get("location").Str())
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/security.go b/Godeps/_workspace/src/github.com/stretchr/objx/security.go
deleted file mode 100644
index fdd6be9cf..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/security.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package objx
-
-import (
- "crypto/sha1"
- "encoding/hex"
-)
-
-// HashWithKey hashes the specified string using the security
-// key.
-func HashWithKey(data, key string) string {
- hash := sha1.New()
- hash.Write([]byte(data + ":" + key))
- return hex.EncodeToString(hash.Sum(nil))
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/security_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/security_test.go
deleted file mode 100644
index 8f0898f62..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/security_test.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package objx
-
-import (
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-func TestHashWithKey(t *testing.T) {
-
- assert.Equal(t, "0ce84d8d01f2c7b6e0882b784429c54d280ea2d9", HashWithKey("abc", "def"))
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/simple_example_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/simple_example_test.go
deleted file mode 100644
index 5408c7fd3..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/simple_example_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package objx
-
-import (
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-func TestSimpleExample(t *testing.T) {
-
- // build a map from a JSON object
- o := MustFromJSON(`{"name":"Mat","foods":["indian","chinese"], "location":{"county":"hobbiton","city":"the shire"}}`)
-
- // Map can be used as a straight map[string]interface{}
- assert.Equal(t, o["name"], "Mat")
-
- // Get an Value object
- v := o.Get("name")
- assert.Equal(t, v, &Value{data: "Mat"})
-
- // Test the contained value
- assert.False(t, v.IsInt())
- assert.False(t, v.IsBool())
- assert.True(t, v.IsStr())
-
- // Get the contained value
- assert.Equal(t, v.Str(), "Mat")
-
- // Get a default value if the contained value is not of the expected type or does not exist
- assert.Equal(t, 1, v.Int(1))
-
- // Get a value by using array notation
- assert.Equal(t, "indian", o.Get("foods[0]").Data())
-
- // Set a value by using array notation
- o.Set("foods[0]", "italian")
- assert.Equal(t, "italian", o.Get("foods[0]").Str())
-
- // Get a value by using dot notation
- assert.Equal(t, "hobbiton", o.Get("location.county").Str())
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/tests.go b/Godeps/_workspace/src/github.com/stretchr/objx/tests.go
deleted file mode 100644
index d9e0b479a..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/tests.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package objx
-
-// Has gets whether there is something at the specified selector
-// or not.
-//
-// If m is nil, Has will always return false.
-func (m Map) Has(selector string) bool {
- if m == nil {
- return false
- }
- return !m.Get(selector).IsNil()
-}
-
-// IsNil gets whether the data is nil or not.
-func (v *Value) IsNil() bool {
- return v == nil || v.data == nil
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/tests_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/tests_test.go
deleted file mode 100644
index bcc1eb03d..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/tests_test.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package objx
-
-import (
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-func TestHas(t *testing.T) {
-
- m := New(TestMap)
-
- assert.True(t, m.Has("name"))
- assert.True(t, m.Has("address.state"))
- assert.True(t, m.Has("numbers[4]"))
-
- assert.False(t, m.Has("address.state.nope"))
- assert.False(t, m.Has("address.nope"))
- assert.False(t, m.Has("nope"))
- assert.False(t, m.Has("numbers[5]"))
-
- m = nil
- assert.False(t, m.Has("nothing"))
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen.go b/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen.go
deleted file mode 100644
index f3ecb29b9..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen.go
+++ /dev/null
@@ -1,2881 +0,0 @@
-package objx
-
-/*
- Inter (interface{} and []interface{})
- --------------------------------------------------
-*/
-
-// Inter gets the value as a interface{}, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Inter(optionalDefault ...interface{}) interface{} {
- if s, ok := v.data.(interface{}); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustInter gets the value as a interface{}.
-//
-// Panics if the object is not a interface{}.
-func (v *Value) MustInter() interface{} {
- return v.data.(interface{})
-}
-
-// InterSlice gets the value as a []interface{}, returns the optionalDefault
-// value or nil if the value is not a []interface{}.
-func (v *Value) InterSlice(optionalDefault ...[]interface{}) []interface{} {
- if s, ok := v.data.([]interface{}); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustInterSlice gets the value as a []interface{}.
-//
-// Panics if the object is not a []interface{}.
-func (v *Value) MustInterSlice() []interface{} {
- return v.data.([]interface{})
-}
-
-// IsInter gets whether the object contained is a interface{} or not.
-func (v *Value) IsInter() bool {
- _, ok := v.data.(interface{})
- return ok
-}
-
-// IsInterSlice gets whether the object contained is a []interface{} or not.
-func (v *Value) IsInterSlice() bool {
- _, ok := v.data.([]interface{})
- return ok
-}
-
-// EachInter calls the specified callback for each object
-// in the []interface{}.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachInter(callback func(int, interface{}) bool) *Value {
-
- for index, val := range v.MustInterSlice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereInter uses the specified decider function to select items
-// from the []interface{}. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereInter(decider func(int, interface{}) bool) *Value {
-
- var selected []interface{}
-
- v.EachInter(func(index int, val interface{}) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupInter uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]interface{}.
-func (v *Value) GroupInter(grouper func(int, interface{}) string) *Value {
-
- groups := make(map[string][]interface{})
-
- v.EachInter(func(index int, val interface{}) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]interface{}, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceInter uses the specified function to replace each interface{}s
-// by iterating each item. The data in the returned result will be a
-// []interface{} containing the replaced items.
-func (v *Value) ReplaceInter(replacer func(int, interface{}) interface{}) *Value {
-
- arr := v.MustInterSlice()
- replaced := make([]interface{}, len(arr))
-
- v.EachInter(func(index int, val interface{}) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectInter uses the specified collector function to collect a value
-// for each of the interface{}s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectInter(collector func(int, interface{}) interface{}) *Value {
-
- arr := v.MustInterSlice()
- collected := make([]interface{}, len(arr))
-
- v.EachInter(func(index int, val interface{}) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- MSI (map[string]interface{} and []map[string]interface{})
- --------------------------------------------------
-*/
-
-// MSI gets the value as a map[string]interface{}, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) MSI(optionalDefault ...map[string]interface{}) map[string]interface{} {
- if s, ok := v.data.(map[string]interface{}); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustMSI gets the value as a map[string]interface{}.
-//
-// Panics if the object is not a map[string]interface{}.
-func (v *Value) MustMSI() map[string]interface{} {
- return v.data.(map[string]interface{})
-}
-
-// MSISlice gets the value as a []map[string]interface{}, returns the optionalDefault
-// value or nil if the value is not a []map[string]interface{}.
-func (v *Value) MSISlice(optionalDefault ...[]map[string]interface{}) []map[string]interface{} {
- if s, ok := v.data.([]map[string]interface{}); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustMSISlice gets the value as a []map[string]interface{}.
-//
-// Panics if the object is not a []map[string]interface{}.
-func (v *Value) MustMSISlice() []map[string]interface{} {
- return v.data.([]map[string]interface{})
-}
-
-// IsMSI gets whether the object contained is a map[string]interface{} or not.
-func (v *Value) IsMSI() bool {
- _, ok := v.data.(map[string]interface{})
- return ok
-}
-
-// IsMSISlice gets whether the object contained is a []map[string]interface{} or not.
-func (v *Value) IsMSISlice() bool {
- _, ok := v.data.([]map[string]interface{})
- return ok
-}
-
-// EachMSI calls the specified callback for each object
-// in the []map[string]interface{}.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachMSI(callback func(int, map[string]interface{}) bool) *Value {
-
- for index, val := range v.MustMSISlice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereMSI uses the specified decider function to select items
-// from the []map[string]interface{}. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereMSI(decider func(int, map[string]interface{}) bool) *Value {
-
- var selected []map[string]interface{}
-
- v.EachMSI(func(index int, val map[string]interface{}) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupMSI uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]map[string]interface{}.
-func (v *Value) GroupMSI(grouper func(int, map[string]interface{}) string) *Value {
-
- groups := make(map[string][]map[string]interface{})
-
- v.EachMSI(func(index int, val map[string]interface{}) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]map[string]interface{}, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceMSI uses the specified function to replace each map[string]interface{}s
-// by iterating each item. The data in the returned result will be a
-// []map[string]interface{} containing the replaced items.
-func (v *Value) ReplaceMSI(replacer func(int, map[string]interface{}) map[string]interface{}) *Value {
-
- arr := v.MustMSISlice()
- replaced := make([]map[string]interface{}, len(arr))
-
- v.EachMSI(func(index int, val map[string]interface{}) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectMSI uses the specified collector function to collect a value
-// for each of the map[string]interface{}s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectMSI(collector func(int, map[string]interface{}) interface{}) *Value {
-
- arr := v.MustMSISlice()
- collected := make([]interface{}, len(arr))
-
- v.EachMSI(func(index int, val map[string]interface{}) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- ObjxMap ((Map) and [](Map))
- --------------------------------------------------
-*/
-
-// ObjxMap gets the value as a (Map), returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) ObjxMap(optionalDefault ...(Map)) Map {
- if s, ok := v.data.((Map)); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return New(nil)
-}
-
-// MustObjxMap gets the value as a (Map).
-//
-// Panics if the object is not a (Map).
-func (v *Value) MustObjxMap() Map {
- return v.data.((Map))
-}
-
-// ObjxMapSlice gets the value as a [](Map), returns the optionalDefault
-// value or nil if the value is not a [](Map).
-func (v *Value) ObjxMapSlice(optionalDefault ...[](Map)) [](Map) {
- if s, ok := v.data.([](Map)); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustObjxMapSlice gets the value as a [](Map).
-//
-// Panics if the object is not a [](Map).
-func (v *Value) MustObjxMapSlice() [](Map) {
- return v.data.([](Map))
-}
-
-// IsObjxMap gets whether the object contained is a (Map) or not.
-func (v *Value) IsObjxMap() bool {
- _, ok := v.data.((Map))
- return ok
-}
-
-// IsObjxMapSlice gets whether the object contained is a [](Map) or not.
-func (v *Value) IsObjxMapSlice() bool {
- _, ok := v.data.([](Map))
- return ok
-}
-
-// EachObjxMap calls the specified callback for each object
-// in the [](Map).
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachObjxMap(callback func(int, Map) bool) *Value {
-
- for index, val := range v.MustObjxMapSlice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereObjxMap uses the specified decider function to select items
-// from the [](Map). The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereObjxMap(decider func(int, Map) bool) *Value {
-
- var selected [](Map)
-
- v.EachObjxMap(func(index int, val Map) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupObjxMap uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][](Map).
-func (v *Value) GroupObjxMap(grouper func(int, Map) string) *Value {
-
- groups := make(map[string][](Map))
-
- v.EachObjxMap(func(index int, val Map) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([](Map), 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceObjxMap uses the specified function to replace each (Map)s
-// by iterating each item. The data in the returned result will be a
-// [](Map) containing the replaced items.
-func (v *Value) ReplaceObjxMap(replacer func(int, Map) Map) *Value {
-
- arr := v.MustObjxMapSlice()
- replaced := make([](Map), len(arr))
-
- v.EachObjxMap(func(index int, val Map) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectObjxMap uses the specified collector function to collect a value
-// for each of the (Map)s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectObjxMap(collector func(int, Map) interface{}) *Value {
-
- arr := v.MustObjxMapSlice()
- collected := make([]interface{}, len(arr))
-
- v.EachObjxMap(func(index int, val Map) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Bool (bool and []bool)
- --------------------------------------------------
-*/
-
-// Bool gets the value as a bool, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Bool(optionalDefault ...bool) bool {
- if s, ok := v.data.(bool); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return false
-}
-
-// MustBool gets the value as a bool.
-//
-// Panics if the object is not a bool.
-func (v *Value) MustBool() bool {
- return v.data.(bool)
-}
-
-// BoolSlice gets the value as a []bool, returns the optionalDefault
-// value or nil if the value is not a []bool.
-func (v *Value) BoolSlice(optionalDefault ...[]bool) []bool {
- if s, ok := v.data.([]bool); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustBoolSlice gets the value as a []bool.
-//
-// Panics if the object is not a []bool.
-func (v *Value) MustBoolSlice() []bool {
- return v.data.([]bool)
-}
-
-// IsBool gets whether the object contained is a bool or not.
-func (v *Value) IsBool() bool {
- _, ok := v.data.(bool)
- return ok
-}
-
-// IsBoolSlice gets whether the object contained is a []bool or not.
-func (v *Value) IsBoolSlice() bool {
- _, ok := v.data.([]bool)
- return ok
-}
-
-// EachBool calls the specified callback for each object
-// in the []bool.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachBool(callback func(int, bool) bool) *Value {
-
- for index, val := range v.MustBoolSlice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereBool uses the specified decider function to select items
-// from the []bool. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereBool(decider func(int, bool) bool) *Value {
-
- var selected []bool
-
- v.EachBool(func(index int, val bool) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupBool uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]bool.
-func (v *Value) GroupBool(grouper func(int, bool) string) *Value {
-
- groups := make(map[string][]bool)
-
- v.EachBool(func(index int, val bool) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]bool, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceBool uses the specified function to replace each bools
-// by iterating each item. The data in the returned result will be a
-// []bool containing the replaced items.
-func (v *Value) ReplaceBool(replacer func(int, bool) bool) *Value {
-
- arr := v.MustBoolSlice()
- replaced := make([]bool, len(arr))
-
- v.EachBool(func(index int, val bool) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectBool uses the specified collector function to collect a value
-// for each of the bools in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectBool(collector func(int, bool) interface{}) *Value {
-
- arr := v.MustBoolSlice()
- collected := make([]interface{}, len(arr))
-
- v.EachBool(func(index int, val bool) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Str (string and []string)
- --------------------------------------------------
-*/
-
-// Str gets the value as a string, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Str(optionalDefault ...string) string {
- if s, ok := v.data.(string); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return ""
-}
-
-// MustStr gets the value as a string.
-//
-// Panics if the object is not a string.
-func (v *Value) MustStr() string {
- return v.data.(string)
-}
-
-// StrSlice gets the value as a []string, returns the optionalDefault
-// value or nil if the value is not a []string.
-func (v *Value) StrSlice(optionalDefault ...[]string) []string {
- if s, ok := v.data.([]string); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustStrSlice gets the value as a []string.
-//
-// Panics if the object is not a []string.
-func (v *Value) MustStrSlice() []string {
- return v.data.([]string)
-}
-
-// IsStr gets whether the object contained is a string or not.
-func (v *Value) IsStr() bool {
- _, ok := v.data.(string)
- return ok
-}
-
-// IsStrSlice gets whether the object contained is a []string or not.
-func (v *Value) IsStrSlice() bool {
- _, ok := v.data.([]string)
- return ok
-}
-
-// EachStr calls the specified callback for each object
-// in the []string.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachStr(callback func(int, string) bool) *Value {
-
- for index, val := range v.MustStrSlice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereStr uses the specified decider function to select items
-// from the []string. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereStr(decider func(int, string) bool) *Value {
-
- var selected []string
-
- v.EachStr(func(index int, val string) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupStr uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]string.
-func (v *Value) GroupStr(grouper func(int, string) string) *Value {
-
- groups := make(map[string][]string)
-
- v.EachStr(func(index int, val string) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]string, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceStr uses the specified function to replace each strings
-// by iterating each item. The data in the returned result will be a
-// []string containing the replaced items.
-func (v *Value) ReplaceStr(replacer func(int, string) string) *Value {
-
- arr := v.MustStrSlice()
- replaced := make([]string, len(arr))
-
- v.EachStr(func(index int, val string) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectStr uses the specified collector function to collect a value
-// for each of the strings in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectStr(collector func(int, string) interface{}) *Value {
-
- arr := v.MustStrSlice()
- collected := make([]interface{}, len(arr))
-
- v.EachStr(func(index int, val string) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Int (int and []int)
- --------------------------------------------------
-*/
-
-// Int gets the value as a int, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Int(optionalDefault ...int) int {
- if s, ok := v.data.(int); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustInt gets the value as a int.
-//
-// Panics if the object is not a int.
-func (v *Value) MustInt() int {
- return v.data.(int)
-}
-
-// IntSlice gets the value as a []int, returns the optionalDefault
-// value or nil if the value is not a []int.
-func (v *Value) IntSlice(optionalDefault ...[]int) []int {
- if s, ok := v.data.([]int); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustIntSlice gets the value as a []int.
-//
-// Panics if the object is not a []int.
-func (v *Value) MustIntSlice() []int {
- return v.data.([]int)
-}
-
-// IsInt gets whether the object contained is a int or not.
-func (v *Value) IsInt() bool {
- _, ok := v.data.(int)
- return ok
-}
-
-// IsIntSlice gets whether the object contained is a []int or not.
-func (v *Value) IsIntSlice() bool {
- _, ok := v.data.([]int)
- return ok
-}
-
-// EachInt calls the specified callback for each object
-// in the []int.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachInt(callback func(int, int) bool) *Value {
-
- for index, val := range v.MustIntSlice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereInt uses the specified decider function to select items
-// from the []int. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereInt(decider func(int, int) bool) *Value {
-
- var selected []int
-
- v.EachInt(func(index int, val int) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupInt uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]int.
-func (v *Value) GroupInt(grouper func(int, int) string) *Value {
-
- groups := make(map[string][]int)
-
- v.EachInt(func(index int, val int) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]int, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceInt uses the specified function to replace each ints
-// by iterating each item. The data in the returned result will be a
-// []int containing the replaced items.
-func (v *Value) ReplaceInt(replacer func(int, int) int) *Value {
-
- arr := v.MustIntSlice()
- replaced := make([]int, len(arr))
-
- v.EachInt(func(index int, val int) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectInt uses the specified collector function to collect a value
-// for each of the ints in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectInt(collector func(int, int) interface{}) *Value {
-
- arr := v.MustIntSlice()
- collected := make([]interface{}, len(arr))
-
- v.EachInt(func(index int, val int) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Int8 (int8 and []int8)
- --------------------------------------------------
-*/
-
-// Int8 gets the value as a int8, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Int8(optionalDefault ...int8) int8 {
- if s, ok := v.data.(int8); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustInt8 gets the value as a int8.
-//
-// Panics if the object is not a int8.
-func (v *Value) MustInt8() int8 {
- return v.data.(int8)
-}
-
-// Int8Slice gets the value as a []int8, returns the optionalDefault
-// value or nil if the value is not a []int8.
-func (v *Value) Int8Slice(optionalDefault ...[]int8) []int8 {
- if s, ok := v.data.([]int8); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustInt8Slice gets the value as a []int8.
-//
-// Panics if the object is not a []int8.
-func (v *Value) MustInt8Slice() []int8 {
- return v.data.([]int8)
-}
-
-// IsInt8 gets whether the object contained is a int8 or not.
-func (v *Value) IsInt8() bool {
- _, ok := v.data.(int8)
- return ok
-}
-
-// IsInt8Slice gets whether the object contained is a []int8 or not.
-func (v *Value) IsInt8Slice() bool {
- _, ok := v.data.([]int8)
- return ok
-}
-
-// EachInt8 calls the specified callback for each object
-// in the []int8.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachInt8(callback func(int, int8) bool) *Value {
-
- for index, val := range v.MustInt8Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereInt8 uses the specified decider function to select items
-// from the []int8. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereInt8(decider func(int, int8) bool) *Value {
-
- var selected []int8
-
- v.EachInt8(func(index int, val int8) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupInt8 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]int8.
-func (v *Value) GroupInt8(grouper func(int, int8) string) *Value {
-
- groups := make(map[string][]int8)
-
- v.EachInt8(func(index int, val int8) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]int8, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceInt8 uses the specified function to replace each int8s
-// by iterating each item. The data in the returned result will be a
-// []int8 containing the replaced items.
-func (v *Value) ReplaceInt8(replacer func(int, int8) int8) *Value {
-
- arr := v.MustInt8Slice()
- replaced := make([]int8, len(arr))
-
- v.EachInt8(func(index int, val int8) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectInt8 uses the specified collector function to collect a value
-// for each of the int8s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectInt8(collector func(int, int8) interface{}) *Value {
-
- arr := v.MustInt8Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachInt8(func(index int, val int8) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Int16 (int16 and []int16)
- --------------------------------------------------
-*/
-
-// Int16 gets the value as a int16, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Int16(optionalDefault ...int16) int16 {
- if s, ok := v.data.(int16); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustInt16 gets the value as a int16.
-//
-// Panics if the object is not a int16.
-func (v *Value) MustInt16() int16 {
- return v.data.(int16)
-}
-
-// Int16Slice gets the value as a []int16, returns the optionalDefault
-// value or nil if the value is not a []int16.
-func (v *Value) Int16Slice(optionalDefault ...[]int16) []int16 {
- if s, ok := v.data.([]int16); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustInt16Slice gets the value as a []int16.
-//
-// Panics if the object is not a []int16.
-func (v *Value) MustInt16Slice() []int16 {
- return v.data.([]int16)
-}
-
-// IsInt16 gets whether the object contained is a int16 or not.
-func (v *Value) IsInt16() bool {
- _, ok := v.data.(int16)
- return ok
-}
-
-// IsInt16Slice gets whether the object contained is a []int16 or not.
-func (v *Value) IsInt16Slice() bool {
- _, ok := v.data.([]int16)
- return ok
-}
-
-// EachInt16 calls the specified callback for each object
-// in the []int16.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachInt16(callback func(int, int16) bool) *Value {
-
- for index, val := range v.MustInt16Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereInt16 uses the specified decider function to select items
-// from the []int16. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereInt16(decider func(int, int16) bool) *Value {
-
- var selected []int16
-
- v.EachInt16(func(index int, val int16) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupInt16 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]int16.
-func (v *Value) GroupInt16(grouper func(int, int16) string) *Value {
-
- groups := make(map[string][]int16)
-
- v.EachInt16(func(index int, val int16) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]int16, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceInt16 uses the specified function to replace each int16s
-// by iterating each item. The data in the returned result will be a
-// []int16 containing the replaced items.
-func (v *Value) ReplaceInt16(replacer func(int, int16) int16) *Value {
-
- arr := v.MustInt16Slice()
- replaced := make([]int16, len(arr))
-
- v.EachInt16(func(index int, val int16) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectInt16 uses the specified collector function to collect a value
-// for each of the int16s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectInt16(collector func(int, int16) interface{}) *Value {
-
- arr := v.MustInt16Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachInt16(func(index int, val int16) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Int32 (int32 and []int32)
- --------------------------------------------------
-*/
-
-// Int32 gets the value as a int32, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Int32(optionalDefault ...int32) int32 {
- if s, ok := v.data.(int32); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustInt32 gets the value as a int32.
-//
-// Panics if the object is not a int32.
-func (v *Value) MustInt32() int32 {
- return v.data.(int32)
-}
-
-// Int32Slice gets the value as a []int32, returns the optionalDefault
-// value or nil if the value is not a []int32.
-func (v *Value) Int32Slice(optionalDefault ...[]int32) []int32 {
- if s, ok := v.data.([]int32); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustInt32Slice gets the value as a []int32.
-//
-// Panics if the object is not a []int32.
-func (v *Value) MustInt32Slice() []int32 {
- return v.data.([]int32)
-}
-
-// IsInt32 gets whether the object contained is a int32 or not.
-func (v *Value) IsInt32() bool {
- _, ok := v.data.(int32)
- return ok
-}
-
-// IsInt32Slice gets whether the object contained is a []int32 or not.
-func (v *Value) IsInt32Slice() bool {
- _, ok := v.data.([]int32)
- return ok
-}
-
-// EachInt32 calls the specified callback for each object
-// in the []int32.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachInt32(callback func(int, int32) bool) *Value {
-
- for index, val := range v.MustInt32Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereInt32 uses the specified decider function to select items
-// from the []int32. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereInt32(decider func(int, int32) bool) *Value {
-
- var selected []int32
-
- v.EachInt32(func(index int, val int32) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupInt32 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]int32.
-func (v *Value) GroupInt32(grouper func(int, int32) string) *Value {
-
- groups := make(map[string][]int32)
-
- v.EachInt32(func(index int, val int32) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]int32, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceInt32 uses the specified function to replace each int32s
-// by iterating each item. The data in the returned result will be a
-// []int32 containing the replaced items.
-func (v *Value) ReplaceInt32(replacer func(int, int32) int32) *Value {
-
- arr := v.MustInt32Slice()
- replaced := make([]int32, len(arr))
-
- v.EachInt32(func(index int, val int32) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectInt32 uses the specified collector function to collect a value
-// for each of the int32s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectInt32(collector func(int, int32) interface{}) *Value {
-
- arr := v.MustInt32Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachInt32(func(index int, val int32) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Int64 (int64 and []int64)
- --------------------------------------------------
-*/
-
-// Int64 gets the value as a int64, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Int64(optionalDefault ...int64) int64 {
- if s, ok := v.data.(int64); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustInt64 gets the value as a int64.
-//
-// Panics if the object is not a int64.
-func (v *Value) MustInt64() int64 {
- return v.data.(int64)
-}
-
-// Int64Slice gets the value as a []int64, returns the optionalDefault
-// value or nil if the value is not a []int64.
-func (v *Value) Int64Slice(optionalDefault ...[]int64) []int64 {
- if s, ok := v.data.([]int64); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustInt64Slice gets the value as a []int64.
-//
-// Panics if the object is not a []int64.
-func (v *Value) MustInt64Slice() []int64 {
- return v.data.([]int64)
-}
-
-// IsInt64 gets whether the object contained is a int64 or not.
-func (v *Value) IsInt64() bool {
- _, ok := v.data.(int64)
- return ok
-}
-
-// IsInt64Slice gets whether the object contained is a []int64 or not.
-func (v *Value) IsInt64Slice() bool {
- _, ok := v.data.([]int64)
- return ok
-}
-
-// EachInt64 calls the specified callback for each object
-// in the []int64.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachInt64(callback func(int, int64) bool) *Value {
-
- for index, val := range v.MustInt64Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereInt64 uses the specified decider function to select items
-// from the []int64. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereInt64(decider func(int, int64) bool) *Value {
-
- var selected []int64
-
- v.EachInt64(func(index int, val int64) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupInt64 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]int64.
-func (v *Value) GroupInt64(grouper func(int, int64) string) *Value {
-
- groups := make(map[string][]int64)
-
- v.EachInt64(func(index int, val int64) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]int64, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceInt64 uses the specified function to replace each int64s
-// by iterating each item. The data in the returned result will be a
-// []int64 containing the replaced items.
-func (v *Value) ReplaceInt64(replacer func(int, int64) int64) *Value {
-
- arr := v.MustInt64Slice()
- replaced := make([]int64, len(arr))
-
- v.EachInt64(func(index int, val int64) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectInt64 uses the specified collector function to collect a value
-// for each of the int64s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectInt64(collector func(int, int64) interface{}) *Value {
-
- arr := v.MustInt64Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachInt64(func(index int, val int64) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Uint (uint and []uint)
- --------------------------------------------------
-*/
-
-// Uint gets the value as a uint, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Uint(optionalDefault ...uint) uint {
- if s, ok := v.data.(uint); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustUint gets the value as a uint.
-//
-// Panics if the object is not a uint.
-func (v *Value) MustUint() uint {
- return v.data.(uint)
-}
-
-// UintSlice gets the value as a []uint, returns the optionalDefault
-// value or nil if the value is not a []uint.
-func (v *Value) UintSlice(optionalDefault ...[]uint) []uint {
- if s, ok := v.data.([]uint); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustUintSlice gets the value as a []uint.
-//
-// Panics if the object is not a []uint.
-func (v *Value) MustUintSlice() []uint {
- return v.data.([]uint)
-}
-
-// IsUint gets whether the object contained is a uint or not.
-func (v *Value) IsUint() bool {
- _, ok := v.data.(uint)
- return ok
-}
-
-// IsUintSlice gets whether the object contained is a []uint or not.
-func (v *Value) IsUintSlice() bool {
- _, ok := v.data.([]uint)
- return ok
-}
-
-// EachUint calls the specified callback for each object
-// in the []uint.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachUint(callback func(int, uint) bool) *Value {
-
- for index, val := range v.MustUintSlice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereUint uses the specified decider function to select items
-// from the []uint. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereUint(decider func(int, uint) bool) *Value {
-
- var selected []uint
-
- v.EachUint(func(index int, val uint) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupUint uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]uint.
-func (v *Value) GroupUint(grouper func(int, uint) string) *Value {
-
- groups := make(map[string][]uint)
-
- v.EachUint(func(index int, val uint) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]uint, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceUint uses the specified function to replace each uints
-// by iterating each item. The data in the returned result will be a
-// []uint containing the replaced items.
-func (v *Value) ReplaceUint(replacer func(int, uint) uint) *Value {
-
- arr := v.MustUintSlice()
- replaced := make([]uint, len(arr))
-
- v.EachUint(func(index int, val uint) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectUint uses the specified collector function to collect a value
-// for each of the uints in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectUint(collector func(int, uint) interface{}) *Value {
-
- arr := v.MustUintSlice()
- collected := make([]interface{}, len(arr))
-
- v.EachUint(func(index int, val uint) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Uint8 (uint8 and []uint8)
- --------------------------------------------------
-*/
-
-// Uint8 gets the value as a uint8, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Uint8(optionalDefault ...uint8) uint8 {
- if s, ok := v.data.(uint8); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustUint8 gets the value as a uint8.
-//
-// Panics if the object is not a uint8.
-func (v *Value) MustUint8() uint8 {
- return v.data.(uint8)
-}
-
-// Uint8Slice gets the value as a []uint8, returns the optionalDefault
-// value or nil if the value is not a []uint8.
-func (v *Value) Uint8Slice(optionalDefault ...[]uint8) []uint8 {
- if s, ok := v.data.([]uint8); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustUint8Slice gets the value as a []uint8.
-//
-// Panics if the object is not a []uint8.
-func (v *Value) MustUint8Slice() []uint8 {
- return v.data.([]uint8)
-}
-
-// IsUint8 gets whether the object contained is a uint8 or not.
-func (v *Value) IsUint8() bool {
- _, ok := v.data.(uint8)
- return ok
-}
-
-// IsUint8Slice gets whether the object contained is a []uint8 or not.
-func (v *Value) IsUint8Slice() bool {
- _, ok := v.data.([]uint8)
- return ok
-}
-
-// EachUint8 calls the specified callback for each object
-// in the []uint8.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachUint8(callback func(int, uint8) bool) *Value {
-
- for index, val := range v.MustUint8Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereUint8 uses the specified decider function to select items
-// from the []uint8. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereUint8(decider func(int, uint8) bool) *Value {
-
- var selected []uint8
-
- v.EachUint8(func(index int, val uint8) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupUint8 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]uint8.
-func (v *Value) GroupUint8(grouper func(int, uint8) string) *Value {
-
- groups := make(map[string][]uint8)
-
- v.EachUint8(func(index int, val uint8) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]uint8, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceUint8 uses the specified function to replace each uint8s
-// by iterating each item. The data in the returned result will be a
-// []uint8 containing the replaced items.
-func (v *Value) ReplaceUint8(replacer func(int, uint8) uint8) *Value {
-
- arr := v.MustUint8Slice()
- replaced := make([]uint8, len(arr))
-
- v.EachUint8(func(index int, val uint8) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectUint8 uses the specified collector function to collect a value
-// for each of the uint8s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectUint8(collector func(int, uint8) interface{}) *Value {
-
- arr := v.MustUint8Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachUint8(func(index int, val uint8) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Uint16 (uint16 and []uint16)
- --------------------------------------------------
-*/
-
-// Uint16 gets the value as a uint16, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Uint16(optionalDefault ...uint16) uint16 {
- if s, ok := v.data.(uint16); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustUint16 gets the value as a uint16.
-//
-// Panics if the object is not a uint16.
-func (v *Value) MustUint16() uint16 {
- return v.data.(uint16)
-}
-
-// Uint16Slice gets the value as a []uint16, returns the optionalDefault
-// value or nil if the value is not a []uint16.
-func (v *Value) Uint16Slice(optionalDefault ...[]uint16) []uint16 {
- if s, ok := v.data.([]uint16); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustUint16Slice gets the value as a []uint16.
-//
-// Panics if the object is not a []uint16.
-func (v *Value) MustUint16Slice() []uint16 {
- return v.data.([]uint16)
-}
-
-// IsUint16 gets whether the object contained is a uint16 or not.
-func (v *Value) IsUint16() bool {
- _, ok := v.data.(uint16)
- return ok
-}
-
-// IsUint16Slice gets whether the object contained is a []uint16 or not.
-func (v *Value) IsUint16Slice() bool {
- _, ok := v.data.([]uint16)
- return ok
-}
-
-// EachUint16 calls the specified callback for each object
-// in the []uint16.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachUint16(callback func(int, uint16) bool) *Value {
-
- for index, val := range v.MustUint16Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereUint16 uses the specified decider function to select items
-// from the []uint16. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereUint16(decider func(int, uint16) bool) *Value {
-
- var selected []uint16
-
- v.EachUint16(func(index int, val uint16) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupUint16 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]uint16.
-func (v *Value) GroupUint16(grouper func(int, uint16) string) *Value {
-
- groups := make(map[string][]uint16)
-
- v.EachUint16(func(index int, val uint16) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]uint16, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceUint16 uses the specified function to replace each uint16s
-// by iterating each item. The data in the returned result will be a
-// []uint16 containing the replaced items.
-func (v *Value) ReplaceUint16(replacer func(int, uint16) uint16) *Value {
-
- arr := v.MustUint16Slice()
- replaced := make([]uint16, len(arr))
-
- v.EachUint16(func(index int, val uint16) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectUint16 uses the specified collector function to collect a value
-// for each of the uint16s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectUint16(collector func(int, uint16) interface{}) *Value {
-
- arr := v.MustUint16Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachUint16(func(index int, val uint16) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Uint32 (uint32 and []uint32)
- --------------------------------------------------
-*/
-
-// Uint32 gets the value as a uint32, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Uint32(optionalDefault ...uint32) uint32 {
- if s, ok := v.data.(uint32); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustUint32 gets the value as a uint32.
-//
-// Panics if the object is not a uint32.
-func (v *Value) MustUint32() uint32 {
- return v.data.(uint32)
-}
-
-// Uint32Slice gets the value as a []uint32, returns the optionalDefault
-// value or nil if the value is not a []uint32.
-func (v *Value) Uint32Slice(optionalDefault ...[]uint32) []uint32 {
- if s, ok := v.data.([]uint32); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustUint32Slice gets the value as a []uint32.
-//
-// Panics if the object is not a []uint32.
-func (v *Value) MustUint32Slice() []uint32 {
- return v.data.([]uint32)
-}
-
-// IsUint32 gets whether the object contained is a uint32 or not.
-func (v *Value) IsUint32() bool {
- _, ok := v.data.(uint32)
- return ok
-}
-
-// IsUint32Slice gets whether the object contained is a []uint32 or not.
-func (v *Value) IsUint32Slice() bool {
- _, ok := v.data.([]uint32)
- return ok
-}
-
-// EachUint32 calls the specified callback for each object
-// in the []uint32.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachUint32(callback func(int, uint32) bool) *Value {
-
- for index, val := range v.MustUint32Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereUint32 uses the specified decider function to select items
-// from the []uint32. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereUint32(decider func(int, uint32) bool) *Value {
-
- var selected []uint32
-
- v.EachUint32(func(index int, val uint32) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupUint32 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]uint32.
-func (v *Value) GroupUint32(grouper func(int, uint32) string) *Value {
-
- groups := make(map[string][]uint32)
-
- v.EachUint32(func(index int, val uint32) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]uint32, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceUint32 uses the specified function to replace each uint32s
-// by iterating each item. The data in the returned result will be a
-// []uint32 containing the replaced items.
-func (v *Value) ReplaceUint32(replacer func(int, uint32) uint32) *Value {
-
- arr := v.MustUint32Slice()
- replaced := make([]uint32, len(arr))
-
- v.EachUint32(func(index int, val uint32) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectUint32 uses the specified collector function to collect a value
-// for each of the uint32s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectUint32(collector func(int, uint32) interface{}) *Value {
-
- arr := v.MustUint32Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachUint32(func(index int, val uint32) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Uint64 (uint64 and []uint64)
- --------------------------------------------------
-*/
-
-// Uint64 gets the value as a uint64, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Uint64(optionalDefault ...uint64) uint64 {
- if s, ok := v.data.(uint64); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustUint64 gets the value as a uint64.
-//
-// Panics if the object is not a uint64.
-func (v *Value) MustUint64() uint64 {
- return v.data.(uint64)
-}
-
-// Uint64Slice gets the value as a []uint64, returns the optionalDefault
-// value or nil if the value is not a []uint64.
-func (v *Value) Uint64Slice(optionalDefault ...[]uint64) []uint64 {
- if s, ok := v.data.([]uint64); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustUint64Slice gets the value as a []uint64.
-//
-// Panics if the object is not a []uint64.
-func (v *Value) MustUint64Slice() []uint64 {
- return v.data.([]uint64)
-}
-
-// IsUint64 gets whether the object contained is a uint64 or not.
-func (v *Value) IsUint64() bool {
- _, ok := v.data.(uint64)
- return ok
-}
-
-// IsUint64Slice gets whether the object contained is a []uint64 or not.
-func (v *Value) IsUint64Slice() bool {
- _, ok := v.data.([]uint64)
- return ok
-}
-
-// EachUint64 calls the specified callback for each object
-// in the []uint64.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachUint64(callback func(int, uint64) bool) *Value {
-
- for index, val := range v.MustUint64Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereUint64 uses the specified decider function to select items
-// from the []uint64. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereUint64(decider func(int, uint64) bool) *Value {
-
- var selected []uint64
-
- v.EachUint64(func(index int, val uint64) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupUint64 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]uint64.
-func (v *Value) GroupUint64(grouper func(int, uint64) string) *Value {
-
- groups := make(map[string][]uint64)
-
- v.EachUint64(func(index int, val uint64) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]uint64, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceUint64 uses the specified function to replace each uint64s
-// by iterating each item. The data in the returned result will be a
-// []uint64 containing the replaced items.
-func (v *Value) ReplaceUint64(replacer func(int, uint64) uint64) *Value {
-
- arr := v.MustUint64Slice()
- replaced := make([]uint64, len(arr))
-
- v.EachUint64(func(index int, val uint64) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectUint64 uses the specified collector function to collect a value
-// for each of the uint64s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectUint64(collector func(int, uint64) interface{}) *Value {
-
- arr := v.MustUint64Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachUint64(func(index int, val uint64) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Uintptr (uintptr and []uintptr)
- --------------------------------------------------
-*/
-
-// Uintptr gets the value as a uintptr, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Uintptr(optionalDefault ...uintptr) uintptr {
- if s, ok := v.data.(uintptr); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustUintptr gets the value as a uintptr.
-//
-// Panics if the object is not a uintptr.
-func (v *Value) MustUintptr() uintptr {
- return v.data.(uintptr)
-}
-
-// UintptrSlice gets the value as a []uintptr, returns the optionalDefault
-// value or nil if the value is not a []uintptr.
-func (v *Value) UintptrSlice(optionalDefault ...[]uintptr) []uintptr {
- if s, ok := v.data.([]uintptr); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustUintptrSlice gets the value as a []uintptr.
-//
-// Panics if the object is not a []uintptr.
-func (v *Value) MustUintptrSlice() []uintptr {
- return v.data.([]uintptr)
-}
-
-// IsUintptr gets whether the object contained is a uintptr or not.
-func (v *Value) IsUintptr() bool {
- _, ok := v.data.(uintptr)
- return ok
-}
-
-// IsUintptrSlice gets whether the object contained is a []uintptr or not.
-func (v *Value) IsUintptrSlice() bool {
- _, ok := v.data.([]uintptr)
- return ok
-}
-
-// EachUintptr calls the specified callback for each object
-// in the []uintptr.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachUintptr(callback func(int, uintptr) bool) *Value {
-
- for index, val := range v.MustUintptrSlice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereUintptr uses the specified decider function to select items
-// from the []uintptr. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereUintptr(decider func(int, uintptr) bool) *Value {
-
- var selected []uintptr
-
- v.EachUintptr(func(index int, val uintptr) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupUintptr uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]uintptr.
-func (v *Value) GroupUintptr(grouper func(int, uintptr) string) *Value {
-
- groups := make(map[string][]uintptr)
-
- v.EachUintptr(func(index int, val uintptr) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]uintptr, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceUintptr uses the specified function to replace each uintptrs
-// by iterating each item. The data in the returned result will be a
-// []uintptr containing the replaced items.
-func (v *Value) ReplaceUintptr(replacer func(int, uintptr) uintptr) *Value {
-
- arr := v.MustUintptrSlice()
- replaced := make([]uintptr, len(arr))
-
- v.EachUintptr(func(index int, val uintptr) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectUintptr uses the specified collector function to collect a value
-// for each of the uintptrs in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectUintptr(collector func(int, uintptr) interface{}) *Value {
-
- arr := v.MustUintptrSlice()
- collected := make([]interface{}, len(arr))
-
- v.EachUintptr(func(index int, val uintptr) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Float32 (float32 and []float32)
- --------------------------------------------------
-*/
-
-// Float32 gets the value as a float32, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Float32(optionalDefault ...float32) float32 {
- if s, ok := v.data.(float32); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustFloat32 gets the value as a float32.
-//
-// Panics if the object is not a float32.
-func (v *Value) MustFloat32() float32 {
- return v.data.(float32)
-}
-
-// Float32Slice gets the value as a []float32, returns the optionalDefault
-// value or nil if the value is not a []float32.
-func (v *Value) Float32Slice(optionalDefault ...[]float32) []float32 {
- if s, ok := v.data.([]float32); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustFloat32Slice gets the value as a []float32.
-//
-// Panics if the object is not a []float32.
-func (v *Value) MustFloat32Slice() []float32 {
- return v.data.([]float32)
-}
-
-// IsFloat32 gets whether the object contained is a float32 or not.
-func (v *Value) IsFloat32() bool {
- _, ok := v.data.(float32)
- return ok
-}
-
-// IsFloat32Slice gets whether the object contained is a []float32 or not.
-func (v *Value) IsFloat32Slice() bool {
- _, ok := v.data.([]float32)
- return ok
-}
-
-// EachFloat32 calls the specified callback for each object
-// in the []float32.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachFloat32(callback func(int, float32) bool) *Value {
-
- for index, val := range v.MustFloat32Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereFloat32 uses the specified decider function to select items
-// from the []float32. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereFloat32(decider func(int, float32) bool) *Value {
-
- var selected []float32
-
- v.EachFloat32(func(index int, val float32) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupFloat32 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]float32.
-func (v *Value) GroupFloat32(grouper func(int, float32) string) *Value {
-
- groups := make(map[string][]float32)
-
- v.EachFloat32(func(index int, val float32) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]float32, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceFloat32 uses the specified function to replace each float32s
-// by iterating each item. The data in the returned result will be a
-// []float32 containing the replaced items.
-func (v *Value) ReplaceFloat32(replacer func(int, float32) float32) *Value {
-
- arr := v.MustFloat32Slice()
- replaced := make([]float32, len(arr))
-
- v.EachFloat32(func(index int, val float32) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectFloat32 uses the specified collector function to collect a value
-// for each of the float32s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectFloat32(collector func(int, float32) interface{}) *Value {
-
- arr := v.MustFloat32Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachFloat32(func(index int, val float32) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Float64 (float64 and []float64)
- --------------------------------------------------
-*/
-
-// Float64 gets the value as a float64, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Float64(optionalDefault ...float64) float64 {
- if s, ok := v.data.(float64); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustFloat64 gets the value as a float64.
-//
-// Panics if the object is not a float64.
-func (v *Value) MustFloat64() float64 {
- return v.data.(float64)
-}
-
-// Float64Slice gets the value as a []float64, returns the optionalDefault
-// value or nil if the value is not a []float64.
-func (v *Value) Float64Slice(optionalDefault ...[]float64) []float64 {
- if s, ok := v.data.([]float64); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustFloat64Slice gets the value as a []float64.
-//
-// Panics if the object is not a []float64.
-func (v *Value) MustFloat64Slice() []float64 {
- return v.data.([]float64)
-}
-
-// IsFloat64 gets whether the object contained is a float64 or not.
-func (v *Value) IsFloat64() bool {
- _, ok := v.data.(float64)
- return ok
-}
-
-// IsFloat64Slice gets whether the object contained is a []float64 or not.
-func (v *Value) IsFloat64Slice() bool {
- _, ok := v.data.([]float64)
- return ok
-}
-
-// EachFloat64 calls the specified callback for each object
-// in the []float64.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachFloat64(callback func(int, float64) bool) *Value {
-
- for index, val := range v.MustFloat64Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereFloat64 uses the specified decider function to select items
-// from the []float64. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereFloat64(decider func(int, float64) bool) *Value {
-
- var selected []float64
-
- v.EachFloat64(func(index int, val float64) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupFloat64 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]float64.
-func (v *Value) GroupFloat64(grouper func(int, float64) string) *Value {
-
- groups := make(map[string][]float64)
-
- v.EachFloat64(func(index int, val float64) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]float64, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceFloat64 uses the specified function to replace each float64s
-// by iterating each item. The data in the returned result will be a
-// []float64 containing the replaced items.
-func (v *Value) ReplaceFloat64(replacer func(int, float64) float64) *Value {
-
- arr := v.MustFloat64Slice()
- replaced := make([]float64, len(arr))
-
- v.EachFloat64(func(index int, val float64) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectFloat64 uses the specified collector function to collect a value
-// for each of the float64s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectFloat64(collector func(int, float64) interface{}) *Value {
-
- arr := v.MustFloat64Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachFloat64(func(index int, val float64) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Complex64 (complex64 and []complex64)
- --------------------------------------------------
-*/
-
-// Complex64 gets the value as a complex64, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Complex64(optionalDefault ...complex64) complex64 {
- if s, ok := v.data.(complex64); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustComplex64 gets the value as a complex64.
-//
-// Panics if the object is not a complex64.
-func (v *Value) MustComplex64() complex64 {
- return v.data.(complex64)
-}
-
-// Complex64Slice gets the value as a []complex64, returns the optionalDefault
-// value or nil if the value is not a []complex64.
-func (v *Value) Complex64Slice(optionalDefault ...[]complex64) []complex64 {
- if s, ok := v.data.([]complex64); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustComplex64Slice gets the value as a []complex64.
-//
-// Panics if the object is not a []complex64.
-func (v *Value) MustComplex64Slice() []complex64 {
- return v.data.([]complex64)
-}
-
-// IsComplex64 gets whether the object contained is a complex64 or not.
-func (v *Value) IsComplex64() bool {
- _, ok := v.data.(complex64)
- return ok
-}
-
-// IsComplex64Slice gets whether the object contained is a []complex64 or not.
-func (v *Value) IsComplex64Slice() bool {
- _, ok := v.data.([]complex64)
- return ok
-}
-
-// EachComplex64 calls the specified callback for each object
-// in the []complex64.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachComplex64(callback func(int, complex64) bool) *Value {
-
- for index, val := range v.MustComplex64Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereComplex64 uses the specified decider function to select items
-// from the []complex64. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereComplex64(decider func(int, complex64) bool) *Value {
-
- var selected []complex64
-
- v.EachComplex64(func(index int, val complex64) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupComplex64 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]complex64.
-func (v *Value) GroupComplex64(grouper func(int, complex64) string) *Value {
-
- groups := make(map[string][]complex64)
-
- v.EachComplex64(func(index int, val complex64) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]complex64, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceComplex64 uses the specified function to replace each complex64s
-// by iterating each item. The data in the returned result will be a
-// []complex64 containing the replaced items.
-func (v *Value) ReplaceComplex64(replacer func(int, complex64) complex64) *Value {
-
- arr := v.MustComplex64Slice()
- replaced := make([]complex64, len(arr))
-
- v.EachComplex64(func(index int, val complex64) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectComplex64 uses the specified collector function to collect a value
-// for each of the complex64s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectComplex64(collector func(int, complex64) interface{}) *Value {
-
- arr := v.MustComplex64Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachComplex64(func(index int, val complex64) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
-
-/*
- Complex128 (complex128 and []complex128)
- --------------------------------------------------
-*/
-
-// Complex128 gets the value as a complex128, returns the optionalDefault
-// value or a system default object if the value is the wrong type.
-func (v *Value) Complex128(optionalDefault ...complex128) complex128 {
- if s, ok := v.data.(complex128); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return 0
-}
-
-// MustComplex128 gets the value as a complex128.
-//
-// Panics if the object is not a complex128.
-func (v *Value) MustComplex128() complex128 {
- return v.data.(complex128)
-}
-
-// Complex128Slice gets the value as a []complex128, returns the optionalDefault
-// value or nil if the value is not a []complex128.
-func (v *Value) Complex128Slice(optionalDefault ...[]complex128) []complex128 {
- if s, ok := v.data.([]complex128); ok {
- return s
- }
- if len(optionalDefault) == 1 {
- return optionalDefault[0]
- }
- return nil
-}
-
-// MustComplex128Slice gets the value as a []complex128.
-//
-// Panics if the object is not a []complex128.
-func (v *Value) MustComplex128Slice() []complex128 {
- return v.data.([]complex128)
-}
-
-// IsComplex128 gets whether the object contained is a complex128 or not.
-func (v *Value) IsComplex128() bool {
- _, ok := v.data.(complex128)
- return ok
-}
-
-// IsComplex128Slice gets whether the object contained is a []complex128 or not.
-func (v *Value) IsComplex128Slice() bool {
- _, ok := v.data.([]complex128)
- return ok
-}
-
-// EachComplex128 calls the specified callback for each object
-// in the []complex128.
-//
-// Panics if the object is the wrong type.
-func (v *Value) EachComplex128(callback func(int, complex128) bool) *Value {
-
- for index, val := range v.MustComplex128Slice() {
- carryon := callback(index, val)
- if carryon == false {
- break
- }
- }
-
- return v
-
-}
-
-// WhereComplex128 uses the specified decider function to select items
-// from the []complex128. The object contained in the result will contain
-// only the selected items.
-func (v *Value) WhereComplex128(decider func(int, complex128) bool) *Value {
-
- var selected []complex128
-
- v.EachComplex128(func(index int, val complex128) bool {
- shouldSelect := decider(index, val)
- if shouldSelect == false {
- selected = append(selected, val)
- }
- return true
- })
-
- return &Value{data: selected}
-
-}
-
-// GroupComplex128 uses the specified grouper function to group the items
-// keyed by the return of the grouper. The object contained in the
-// result will contain a map[string][]complex128.
-func (v *Value) GroupComplex128(grouper func(int, complex128) string) *Value {
-
- groups := make(map[string][]complex128)
-
- v.EachComplex128(func(index int, val complex128) bool {
- group := grouper(index, val)
- if _, ok := groups[group]; !ok {
- groups[group] = make([]complex128, 0)
- }
- groups[group] = append(groups[group], val)
- return true
- })
-
- return &Value{data: groups}
-
-}
-
-// ReplaceComplex128 uses the specified function to replace each complex128s
-// by iterating each item. The data in the returned result will be a
-// []complex128 containing the replaced items.
-func (v *Value) ReplaceComplex128(replacer func(int, complex128) complex128) *Value {
-
- arr := v.MustComplex128Slice()
- replaced := make([]complex128, len(arr))
-
- v.EachComplex128(func(index int, val complex128) bool {
- replaced[index] = replacer(index, val)
- return true
- })
-
- return &Value{data: replaced}
-
-}
-
-// CollectComplex128 uses the specified collector function to collect a value
-// for each of the complex128s in the slice. The data returned will be a
-// []interface{}.
-func (v *Value) CollectComplex128(collector func(int, complex128) interface{}) *Value {
-
- arr := v.MustComplex128Slice()
- collected := make([]interface{}, len(arr))
-
- v.EachComplex128(func(index int, val complex128) bool {
- collected[index] = collector(index, val)
- return true
- })
-
- return &Value{data: collected}
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen_test.go
deleted file mode 100644
index f7a4fceea..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen_test.go
+++ /dev/null
@@ -1,2867 +0,0 @@
-package objx
-
-import (
- "fmt"
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestInter(t *testing.T) {
-
- val := interface{}("something")
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Inter())
- assert.Equal(t, val, New(m).Get("value").MustInter())
- assert.Equal(t, interface{}(nil), New(m).Get("nothing").Inter())
- assert.Equal(t, val, New(m).Get("nothing").Inter("something"))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustInter()
- })
-
-}
-
-func TestInterSlice(t *testing.T) {
-
- val := interface{}("something")
- m := map[string]interface{}{"value": []interface{}{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").InterSlice()[0])
- assert.Equal(t, val, New(m).Get("value").MustInterSlice()[0])
- assert.Equal(t, []interface{}(nil), New(m).Get("nothing").InterSlice())
- assert.Equal(t, val, New(m).Get("nothing").InterSlice([]interface{}{interface{}("something")})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustInterSlice()
- })
-
-}
-
-func TestIsInter(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: interface{}("something")}
- assert.True(t, v.IsInter())
-
- v = &Value{data: []interface{}{interface{}("something")}}
- assert.True(t, v.IsInterSlice())
-
-}
-
-func TestEachInter(t *testing.T) {
-
- v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
- count := 0
- replacedVals := make([]interface{}, 0)
- assert.Equal(t, v, v.EachInter(func(i int, val interface{}) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustInterSlice()[0])
- assert.Equal(t, replacedVals[1], v.MustInterSlice()[1])
- assert.Equal(t, replacedVals[2], v.MustInterSlice()[2])
-
-}
-
-func TestWhereInter(t *testing.T) {
-
- v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
-
- selected := v.WhereInter(func(i int, val interface{}) bool {
- return i%2 == 0
- }).MustInterSlice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupInter(t *testing.T) {
-
- v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
-
- grouped := v.GroupInter(func(i int, val interface{}) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]interface{})
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceInter(t *testing.T) {
-
- v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
-
- rawArr := v.MustInterSlice()
-
- replaced := v.ReplaceInter(func(index int, val interface{}) interface{} {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustInterSlice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectInter(t *testing.T) {
-
- v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
-
- collected := v.CollectInter(func(index int, val interface{}) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestMSI(t *testing.T) {
-
- val := map[string]interface{}(map[string]interface{}{"name": "Tyler"})
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").MSI())
- assert.Equal(t, val, New(m).Get("value").MustMSI())
- assert.Equal(t, map[string]interface{}(nil), New(m).Get("nothing").MSI())
- assert.Equal(t, val, New(m).Get("nothing").MSI(map[string]interface{}{"name": "Tyler"}))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustMSI()
- })
-
-}
-
-func TestMSISlice(t *testing.T) {
-
- val := map[string]interface{}(map[string]interface{}{"name": "Tyler"})
- m := map[string]interface{}{"value": []map[string]interface{}{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").MSISlice()[0])
- assert.Equal(t, val, New(m).Get("value").MustMSISlice()[0])
- assert.Equal(t, []map[string]interface{}(nil), New(m).Get("nothing").MSISlice())
- assert.Equal(t, val, New(m).Get("nothing").MSISlice([]map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"})})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustMSISlice()
- })
-
-}
-
-func TestIsMSI(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: map[string]interface{}(map[string]interface{}{"name": "Tyler"})}
- assert.True(t, v.IsMSI())
-
- v = &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
- assert.True(t, v.IsMSISlice())
-
-}
-
-func TestEachMSI(t *testing.T) {
-
- v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
- count := 0
- replacedVals := make([]map[string]interface{}, 0)
- assert.Equal(t, v, v.EachMSI(func(i int, val map[string]interface{}) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustMSISlice()[0])
- assert.Equal(t, replacedVals[1], v.MustMSISlice()[1])
- assert.Equal(t, replacedVals[2], v.MustMSISlice()[2])
-
-}
-
-func TestWhereMSI(t *testing.T) {
-
- v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
-
- selected := v.WhereMSI(func(i int, val map[string]interface{}) bool {
- return i%2 == 0
- }).MustMSISlice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupMSI(t *testing.T) {
-
- v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
-
- grouped := v.GroupMSI(func(i int, val map[string]interface{}) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]map[string]interface{})
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceMSI(t *testing.T) {
-
- v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
-
- rawArr := v.MustMSISlice()
-
- replaced := v.ReplaceMSI(func(index int, val map[string]interface{}) map[string]interface{} {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustMSISlice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectMSI(t *testing.T) {
-
- v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
-
- collected := v.CollectMSI(func(index int, val map[string]interface{}) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestObjxMap(t *testing.T) {
-
- val := (Map)(New(1))
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").ObjxMap())
- assert.Equal(t, val, New(m).Get("value").MustObjxMap())
- assert.Equal(t, (Map)(New(nil)), New(m).Get("nothing").ObjxMap())
- assert.Equal(t, val, New(m).Get("nothing").ObjxMap(New(1)))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustObjxMap()
- })
-
-}
-
-func TestObjxMapSlice(t *testing.T) {
-
- val := (Map)(New(1))
- m := map[string]interface{}{"value": [](Map){val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").ObjxMapSlice()[0])
- assert.Equal(t, val, New(m).Get("value").MustObjxMapSlice()[0])
- assert.Equal(t, [](Map)(nil), New(m).Get("nothing").ObjxMapSlice())
- assert.Equal(t, val, New(m).Get("nothing").ObjxMapSlice([](Map){(Map)(New(1))})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustObjxMapSlice()
- })
-
-}
-
-func TestIsObjxMap(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: (Map)(New(1))}
- assert.True(t, v.IsObjxMap())
-
- v = &Value{data: [](Map){(Map)(New(1))}}
- assert.True(t, v.IsObjxMapSlice())
-
-}
-
-func TestEachObjxMap(t *testing.T) {
-
- v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}}
- count := 0
- replacedVals := make([](Map), 0)
- assert.Equal(t, v, v.EachObjxMap(func(i int, val Map) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustObjxMapSlice()[0])
- assert.Equal(t, replacedVals[1], v.MustObjxMapSlice()[1])
- assert.Equal(t, replacedVals[2], v.MustObjxMapSlice()[2])
-
-}
-
-func TestWhereObjxMap(t *testing.T) {
-
- v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}}
-
- selected := v.WhereObjxMap(func(i int, val Map) bool {
- return i%2 == 0
- }).MustObjxMapSlice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupObjxMap(t *testing.T) {
-
- v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}}
-
- grouped := v.GroupObjxMap(func(i int, val Map) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][](Map))
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceObjxMap(t *testing.T) {
-
- v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}}
-
- rawArr := v.MustObjxMapSlice()
-
- replaced := v.ReplaceObjxMap(func(index int, val Map) Map {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustObjxMapSlice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectObjxMap(t *testing.T) {
-
- v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}}
-
- collected := v.CollectObjxMap(func(index int, val Map) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestBool(t *testing.T) {
-
- val := bool(true)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Bool())
- assert.Equal(t, val, New(m).Get("value").MustBool())
- assert.Equal(t, bool(false), New(m).Get("nothing").Bool())
- assert.Equal(t, val, New(m).Get("nothing").Bool(true))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustBool()
- })
-
-}
-
-func TestBoolSlice(t *testing.T) {
-
- val := bool(true)
- m := map[string]interface{}{"value": []bool{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").BoolSlice()[0])
- assert.Equal(t, val, New(m).Get("value").MustBoolSlice()[0])
- assert.Equal(t, []bool(nil), New(m).Get("nothing").BoolSlice())
- assert.Equal(t, val, New(m).Get("nothing").BoolSlice([]bool{bool(true)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustBoolSlice()
- })
-
-}
-
-func TestIsBool(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: bool(true)}
- assert.True(t, v.IsBool())
-
- v = &Value{data: []bool{bool(true)}}
- assert.True(t, v.IsBoolSlice())
-
-}
-
-func TestEachBool(t *testing.T) {
-
- v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true)}}
- count := 0
- replacedVals := make([]bool, 0)
- assert.Equal(t, v, v.EachBool(func(i int, val bool) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustBoolSlice()[0])
- assert.Equal(t, replacedVals[1], v.MustBoolSlice()[1])
- assert.Equal(t, replacedVals[2], v.MustBoolSlice()[2])
-
-}
-
-func TestWhereBool(t *testing.T) {
-
- v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
-
- selected := v.WhereBool(func(i int, val bool) bool {
- return i%2 == 0
- }).MustBoolSlice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupBool(t *testing.T) {
-
- v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
-
- grouped := v.GroupBool(func(i int, val bool) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]bool)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceBool(t *testing.T) {
-
- v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
-
- rawArr := v.MustBoolSlice()
-
- replaced := v.ReplaceBool(func(index int, val bool) bool {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustBoolSlice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectBool(t *testing.T) {
-
- v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
-
- collected := v.CollectBool(func(index int, val bool) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestStr(t *testing.T) {
-
- val := string("hello")
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Str())
- assert.Equal(t, val, New(m).Get("value").MustStr())
- assert.Equal(t, string(""), New(m).Get("nothing").Str())
- assert.Equal(t, val, New(m).Get("nothing").Str("hello"))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustStr()
- })
-
-}
-
-func TestStrSlice(t *testing.T) {
-
- val := string("hello")
- m := map[string]interface{}{"value": []string{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").StrSlice()[0])
- assert.Equal(t, val, New(m).Get("value").MustStrSlice()[0])
- assert.Equal(t, []string(nil), New(m).Get("nothing").StrSlice())
- assert.Equal(t, val, New(m).Get("nothing").StrSlice([]string{string("hello")})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustStrSlice()
- })
-
-}
-
-func TestIsStr(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: string("hello")}
- assert.True(t, v.IsStr())
-
- v = &Value{data: []string{string("hello")}}
- assert.True(t, v.IsStrSlice())
-
-}
-
-func TestEachStr(t *testing.T) {
-
- v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
- count := 0
- replacedVals := make([]string, 0)
- assert.Equal(t, v, v.EachStr(func(i int, val string) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustStrSlice()[0])
- assert.Equal(t, replacedVals[1], v.MustStrSlice()[1])
- assert.Equal(t, replacedVals[2], v.MustStrSlice()[2])
-
-}
-
-func TestWhereStr(t *testing.T) {
-
- v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
-
- selected := v.WhereStr(func(i int, val string) bool {
- return i%2 == 0
- }).MustStrSlice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupStr(t *testing.T) {
-
- v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
-
- grouped := v.GroupStr(func(i int, val string) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]string)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceStr(t *testing.T) {
-
- v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
-
- rawArr := v.MustStrSlice()
-
- replaced := v.ReplaceStr(func(index int, val string) string {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustStrSlice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectStr(t *testing.T) {
-
- v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
-
- collected := v.CollectStr(func(index int, val string) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestInt(t *testing.T) {
-
- val := int(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Int())
- assert.Equal(t, val, New(m).Get("value").MustInt())
- assert.Equal(t, int(0), New(m).Get("nothing").Int())
- assert.Equal(t, val, New(m).Get("nothing").Int(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustInt()
- })
-
-}
-
-func TestIntSlice(t *testing.T) {
-
- val := int(1)
- m := map[string]interface{}{"value": []int{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").IntSlice()[0])
- assert.Equal(t, val, New(m).Get("value").MustIntSlice()[0])
- assert.Equal(t, []int(nil), New(m).Get("nothing").IntSlice())
- assert.Equal(t, val, New(m).Get("nothing").IntSlice([]int{int(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustIntSlice()
- })
-
-}
-
-func TestIsInt(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: int(1)}
- assert.True(t, v.IsInt())
-
- v = &Value{data: []int{int(1)}}
- assert.True(t, v.IsIntSlice())
-
-}
-
-func TestEachInt(t *testing.T) {
-
- v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1)}}
- count := 0
- replacedVals := make([]int, 0)
- assert.Equal(t, v, v.EachInt(func(i int, val int) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustIntSlice()[0])
- assert.Equal(t, replacedVals[1], v.MustIntSlice()[1])
- assert.Equal(t, replacedVals[2], v.MustIntSlice()[2])
-
-}
-
-func TestWhereInt(t *testing.T) {
-
- v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
-
- selected := v.WhereInt(func(i int, val int) bool {
- return i%2 == 0
- }).MustIntSlice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupInt(t *testing.T) {
-
- v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
-
- grouped := v.GroupInt(func(i int, val int) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]int)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceInt(t *testing.T) {
-
- v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
-
- rawArr := v.MustIntSlice()
-
- replaced := v.ReplaceInt(func(index int, val int) int {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustIntSlice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectInt(t *testing.T) {
-
- v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
-
- collected := v.CollectInt(func(index int, val int) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestInt8(t *testing.T) {
-
- val := int8(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Int8())
- assert.Equal(t, val, New(m).Get("value").MustInt8())
- assert.Equal(t, int8(0), New(m).Get("nothing").Int8())
- assert.Equal(t, val, New(m).Get("nothing").Int8(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustInt8()
- })
-
-}
-
-func TestInt8Slice(t *testing.T) {
-
- val := int8(1)
- m := map[string]interface{}{"value": []int8{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Int8Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustInt8Slice()[0])
- assert.Equal(t, []int8(nil), New(m).Get("nothing").Int8Slice())
- assert.Equal(t, val, New(m).Get("nothing").Int8Slice([]int8{int8(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustInt8Slice()
- })
-
-}
-
-func TestIsInt8(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: int8(1)}
- assert.True(t, v.IsInt8())
-
- v = &Value{data: []int8{int8(1)}}
- assert.True(t, v.IsInt8Slice())
-
-}
-
-func TestEachInt8(t *testing.T) {
-
- v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1)}}
- count := 0
- replacedVals := make([]int8, 0)
- assert.Equal(t, v, v.EachInt8(func(i int, val int8) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustInt8Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustInt8Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustInt8Slice()[2])
-
-}
-
-func TestWhereInt8(t *testing.T) {
-
- v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
-
- selected := v.WhereInt8(func(i int, val int8) bool {
- return i%2 == 0
- }).MustInt8Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupInt8(t *testing.T) {
-
- v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
-
- grouped := v.GroupInt8(func(i int, val int8) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]int8)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceInt8(t *testing.T) {
-
- v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
-
- rawArr := v.MustInt8Slice()
-
- replaced := v.ReplaceInt8(func(index int, val int8) int8 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustInt8Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectInt8(t *testing.T) {
-
- v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
-
- collected := v.CollectInt8(func(index int, val int8) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestInt16(t *testing.T) {
-
- val := int16(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Int16())
- assert.Equal(t, val, New(m).Get("value").MustInt16())
- assert.Equal(t, int16(0), New(m).Get("nothing").Int16())
- assert.Equal(t, val, New(m).Get("nothing").Int16(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustInt16()
- })
-
-}
-
-func TestInt16Slice(t *testing.T) {
-
- val := int16(1)
- m := map[string]interface{}{"value": []int16{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Int16Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustInt16Slice()[0])
- assert.Equal(t, []int16(nil), New(m).Get("nothing").Int16Slice())
- assert.Equal(t, val, New(m).Get("nothing").Int16Slice([]int16{int16(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustInt16Slice()
- })
-
-}
-
-func TestIsInt16(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: int16(1)}
- assert.True(t, v.IsInt16())
-
- v = &Value{data: []int16{int16(1)}}
- assert.True(t, v.IsInt16Slice())
-
-}
-
-func TestEachInt16(t *testing.T) {
-
- v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1)}}
- count := 0
- replacedVals := make([]int16, 0)
- assert.Equal(t, v, v.EachInt16(func(i int, val int16) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustInt16Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustInt16Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustInt16Slice()[2])
-
-}
-
-func TestWhereInt16(t *testing.T) {
-
- v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
-
- selected := v.WhereInt16(func(i int, val int16) bool {
- return i%2 == 0
- }).MustInt16Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupInt16(t *testing.T) {
-
- v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
-
- grouped := v.GroupInt16(func(i int, val int16) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]int16)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceInt16(t *testing.T) {
-
- v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
-
- rawArr := v.MustInt16Slice()
-
- replaced := v.ReplaceInt16(func(index int, val int16) int16 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustInt16Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectInt16(t *testing.T) {
-
- v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
-
- collected := v.CollectInt16(func(index int, val int16) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestInt32(t *testing.T) {
-
- val := int32(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Int32())
- assert.Equal(t, val, New(m).Get("value").MustInt32())
- assert.Equal(t, int32(0), New(m).Get("nothing").Int32())
- assert.Equal(t, val, New(m).Get("nothing").Int32(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustInt32()
- })
-
-}
-
-func TestInt32Slice(t *testing.T) {
-
- val := int32(1)
- m := map[string]interface{}{"value": []int32{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Int32Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustInt32Slice()[0])
- assert.Equal(t, []int32(nil), New(m).Get("nothing").Int32Slice())
- assert.Equal(t, val, New(m).Get("nothing").Int32Slice([]int32{int32(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustInt32Slice()
- })
-
-}
-
-func TestIsInt32(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: int32(1)}
- assert.True(t, v.IsInt32())
-
- v = &Value{data: []int32{int32(1)}}
- assert.True(t, v.IsInt32Slice())
-
-}
-
-func TestEachInt32(t *testing.T) {
-
- v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1)}}
- count := 0
- replacedVals := make([]int32, 0)
- assert.Equal(t, v, v.EachInt32(func(i int, val int32) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustInt32Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustInt32Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustInt32Slice()[2])
-
-}
-
-func TestWhereInt32(t *testing.T) {
-
- v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
-
- selected := v.WhereInt32(func(i int, val int32) bool {
- return i%2 == 0
- }).MustInt32Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupInt32(t *testing.T) {
-
- v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
-
- grouped := v.GroupInt32(func(i int, val int32) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]int32)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceInt32(t *testing.T) {
-
- v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
-
- rawArr := v.MustInt32Slice()
-
- replaced := v.ReplaceInt32(func(index int, val int32) int32 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustInt32Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectInt32(t *testing.T) {
-
- v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
-
- collected := v.CollectInt32(func(index int, val int32) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestInt64(t *testing.T) {
-
- val := int64(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Int64())
- assert.Equal(t, val, New(m).Get("value").MustInt64())
- assert.Equal(t, int64(0), New(m).Get("nothing").Int64())
- assert.Equal(t, val, New(m).Get("nothing").Int64(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustInt64()
- })
-
-}
-
-func TestInt64Slice(t *testing.T) {
-
- val := int64(1)
- m := map[string]interface{}{"value": []int64{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Int64Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustInt64Slice()[0])
- assert.Equal(t, []int64(nil), New(m).Get("nothing").Int64Slice())
- assert.Equal(t, val, New(m).Get("nothing").Int64Slice([]int64{int64(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustInt64Slice()
- })
-
-}
-
-func TestIsInt64(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: int64(1)}
- assert.True(t, v.IsInt64())
-
- v = &Value{data: []int64{int64(1)}}
- assert.True(t, v.IsInt64Slice())
-
-}
-
-func TestEachInt64(t *testing.T) {
-
- v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1)}}
- count := 0
- replacedVals := make([]int64, 0)
- assert.Equal(t, v, v.EachInt64(func(i int, val int64) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustInt64Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustInt64Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustInt64Slice()[2])
-
-}
-
-func TestWhereInt64(t *testing.T) {
-
- v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
-
- selected := v.WhereInt64(func(i int, val int64) bool {
- return i%2 == 0
- }).MustInt64Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupInt64(t *testing.T) {
-
- v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
-
- grouped := v.GroupInt64(func(i int, val int64) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]int64)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceInt64(t *testing.T) {
-
- v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
-
- rawArr := v.MustInt64Slice()
-
- replaced := v.ReplaceInt64(func(index int, val int64) int64 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustInt64Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectInt64(t *testing.T) {
-
- v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
-
- collected := v.CollectInt64(func(index int, val int64) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestUint(t *testing.T) {
-
- val := uint(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Uint())
- assert.Equal(t, val, New(m).Get("value").MustUint())
- assert.Equal(t, uint(0), New(m).Get("nothing").Uint())
- assert.Equal(t, val, New(m).Get("nothing").Uint(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustUint()
- })
-
-}
-
-func TestUintSlice(t *testing.T) {
-
- val := uint(1)
- m := map[string]interface{}{"value": []uint{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").UintSlice()[0])
- assert.Equal(t, val, New(m).Get("value").MustUintSlice()[0])
- assert.Equal(t, []uint(nil), New(m).Get("nothing").UintSlice())
- assert.Equal(t, val, New(m).Get("nothing").UintSlice([]uint{uint(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustUintSlice()
- })
-
-}
-
-func TestIsUint(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: uint(1)}
- assert.True(t, v.IsUint())
-
- v = &Value{data: []uint{uint(1)}}
- assert.True(t, v.IsUintSlice())
-
-}
-
-func TestEachUint(t *testing.T) {
-
- v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1)}}
- count := 0
- replacedVals := make([]uint, 0)
- assert.Equal(t, v, v.EachUint(func(i int, val uint) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustUintSlice()[0])
- assert.Equal(t, replacedVals[1], v.MustUintSlice()[1])
- assert.Equal(t, replacedVals[2], v.MustUintSlice()[2])
-
-}
-
-func TestWhereUint(t *testing.T) {
-
- v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
-
- selected := v.WhereUint(func(i int, val uint) bool {
- return i%2 == 0
- }).MustUintSlice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupUint(t *testing.T) {
-
- v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
-
- grouped := v.GroupUint(func(i int, val uint) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]uint)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceUint(t *testing.T) {
-
- v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
-
- rawArr := v.MustUintSlice()
-
- replaced := v.ReplaceUint(func(index int, val uint) uint {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustUintSlice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectUint(t *testing.T) {
-
- v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
-
- collected := v.CollectUint(func(index int, val uint) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestUint8(t *testing.T) {
-
- val := uint8(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Uint8())
- assert.Equal(t, val, New(m).Get("value").MustUint8())
- assert.Equal(t, uint8(0), New(m).Get("nothing").Uint8())
- assert.Equal(t, val, New(m).Get("nothing").Uint8(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustUint8()
- })
-
-}
-
-func TestUint8Slice(t *testing.T) {
-
- val := uint8(1)
- m := map[string]interface{}{"value": []uint8{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Uint8Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustUint8Slice()[0])
- assert.Equal(t, []uint8(nil), New(m).Get("nothing").Uint8Slice())
- assert.Equal(t, val, New(m).Get("nothing").Uint8Slice([]uint8{uint8(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustUint8Slice()
- })
-
-}
-
-func TestIsUint8(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: uint8(1)}
- assert.True(t, v.IsUint8())
-
- v = &Value{data: []uint8{uint8(1)}}
- assert.True(t, v.IsUint8Slice())
-
-}
-
-func TestEachUint8(t *testing.T) {
-
- v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
- count := 0
- replacedVals := make([]uint8, 0)
- assert.Equal(t, v, v.EachUint8(func(i int, val uint8) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustUint8Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustUint8Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustUint8Slice()[2])
-
-}
-
-func TestWhereUint8(t *testing.T) {
-
- v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
-
- selected := v.WhereUint8(func(i int, val uint8) bool {
- return i%2 == 0
- }).MustUint8Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupUint8(t *testing.T) {
-
- v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
-
- grouped := v.GroupUint8(func(i int, val uint8) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]uint8)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceUint8(t *testing.T) {
-
- v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
-
- rawArr := v.MustUint8Slice()
-
- replaced := v.ReplaceUint8(func(index int, val uint8) uint8 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustUint8Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectUint8(t *testing.T) {
-
- v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
-
- collected := v.CollectUint8(func(index int, val uint8) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestUint16(t *testing.T) {
-
- val := uint16(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Uint16())
- assert.Equal(t, val, New(m).Get("value").MustUint16())
- assert.Equal(t, uint16(0), New(m).Get("nothing").Uint16())
- assert.Equal(t, val, New(m).Get("nothing").Uint16(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustUint16()
- })
-
-}
-
-func TestUint16Slice(t *testing.T) {
-
- val := uint16(1)
- m := map[string]interface{}{"value": []uint16{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Uint16Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustUint16Slice()[0])
- assert.Equal(t, []uint16(nil), New(m).Get("nothing").Uint16Slice())
- assert.Equal(t, val, New(m).Get("nothing").Uint16Slice([]uint16{uint16(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustUint16Slice()
- })
-
-}
-
-func TestIsUint16(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: uint16(1)}
- assert.True(t, v.IsUint16())
-
- v = &Value{data: []uint16{uint16(1)}}
- assert.True(t, v.IsUint16Slice())
-
-}
-
-func TestEachUint16(t *testing.T) {
-
- v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
- count := 0
- replacedVals := make([]uint16, 0)
- assert.Equal(t, v, v.EachUint16(func(i int, val uint16) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustUint16Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustUint16Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustUint16Slice()[2])
-
-}
-
-func TestWhereUint16(t *testing.T) {
-
- v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
-
- selected := v.WhereUint16(func(i int, val uint16) bool {
- return i%2 == 0
- }).MustUint16Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupUint16(t *testing.T) {
-
- v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
-
- grouped := v.GroupUint16(func(i int, val uint16) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]uint16)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceUint16(t *testing.T) {
-
- v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
-
- rawArr := v.MustUint16Slice()
-
- replaced := v.ReplaceUint16(func(index int, val uint16) uint16 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustUint16Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectUint16(t *testing.T) {
-
- v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
-
- collected := v.CollectUint16(func(index int, val uint16) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestUint32(t *testing.T) {
-
- val := uint32(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Uint32())
- assert.Equal(t, val, New(m).Get("value").MustUint32())
- assert.Equal(t, uint32(0), New(m).Get("nothing").Uint32())
- assert.Equal(t, val, New(m).Get("nothing").Uint32(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustUint32()
- })
-
-}
-
-func TestUint32Slice(t *testing.T) {
-
- val := uint32(1)
- m := map[string]interface{}{"value": []uint32{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Uint32Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustUint32Slice()[0])
- assert.Equal(t, []uint32(nil), New(m).Get("nothing").Uint32Slice())
- assert.Equal(t, val, New(m).Get("nothing").Uint32Slice([]uint32{uint32(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustUint32Slice()
- })
-
-}
-
-func TestIsUint32(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: uint32(1)}
- assert.True(t, v.IsUint32())
-
- v = &Value{data: []uint32{uint32(1)}}
- assert.True(t, v.IsUint32Slice())
-
-}
-
-func TestEachUint32(t *testing.T) {
-
- v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
- count := 0
- replacedVals := make([]uint32, 0)
- assert.Equal(t, v, v.EachUint32(func(i int, val uint32) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustUint32Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustUint32Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustUint32Slice()[2])
-
-}
-
-func TestWhereUint32(t *testing.T) {
-
- v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
-
- selected := v.WhereUint32(func(i int, val uint32) bool {
- return i%2 == 0
- }).MustUint32Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupUint32(t *testing.T) {
-
- v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
-
- grouped := v.GroupUint32(func(i int, val uint32) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]uint32)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceUint32(t *testing.T) {
-
- v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
-
- rawArr := v.MustUint32Slice()
-
- replaced := v.ReplaceUint32(func(index int, val uint32) uint32 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustUint32Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectUint32(t *testing.T) {
-
- v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
-
- collected := v.CollectUint32(func(index int, val uint32) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestUint64(t *testing.T) {
-
- val := uint64(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Uint64())
- assert.Equal(t, val, New(m).Get("value").MustUint64())
- assert.Equal(t, uint64(0), New(m).Get("nothing").Uint64())
- assert.Equal(t, val, New(m).Get("nothing").Uint64(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustUint64()
- })
-
-}
-
-func TestUint64Slice(t *testing.T) {
-
- val := uint64(1)
- m := map[string]interface{}{"value": []uint64{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Uint64Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustUint64Slice()[0])
- assert.Equal(t, []uint64(nil), New(m).Get("nothing").Uint64Slice())
- assert.Equal(t, val, New(m).Get("nothing").Uint64Slice([]uint64{uint64(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustUint64Slice()
- })
-
-}
-
-func TestIsUint64(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: uint64(1)}
- assert.True(t, v.IsUint64())
-
- v = &Value{data: []uint64{uint64(1)}}
- assert.True(t, v.IsUint64Slice())
-
-}
-
-func TestEachUint64(t *testing.T) {
-
- v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
- count := 0
- replacedVals := make([]uint64, 0)
- assert.Equal(t, v, v.EachUint64(func(i int, val uint64) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustUint64Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustUint64Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustUint64Slice()[2])
-
-}
-
-func TestWhereUint64(t *testing.T) {
-
- v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
-
- selected := v.WhereUint64(func(i int, val uint64) bool {
- return i%2 == 0
- }).MustUint64Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupUint64(t *testing.T) {
-
- v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
-
- grouped := v.GroupUint64(func(i int, val uint64) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]uint64)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceUint64(t *testing.T) {
-
- v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
-
- rawArr := v.MustUint64Slice()
-
- replaced := v.ReplaceUint64(func(index int, val uint64) uint64 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustUint64Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectUint64(t *testing.T) {
-
- v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
-
- collected := v.CollectUint64(func(index int, val uint64) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestUintptr(t *testing.T) {
-
- val := uintptr(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Uintptr())
- assert.Equal(t, val, New(m).Get("value").MustUintptr())
- assert.Equal(t, uintptr(0), New(m).Get("nothing").Uintptr())
- assert.Equal(t, val, New(m).Get("nothing").Uintptr(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustUintptr()
- })
-
-}
-
-func TestUintptrSlice(t *testing.T) {
-
- val := uintptr(1)
- m := map[string]interface{}{"value": []uintptr{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").UintptrSlice()[0])
- assert.Equal(t, val, New(m).Get("value").MustUintptrSlice()[0])
- assert.Equal(t, []uintptr(nil), New(m).Get("nothing").UintptrSlice())
- assert.Equal(t, val, New(m).Get("nothing").UintptrSlice([]uintptr{uintptr(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustUintptrSlice()
- })
-
-}
-
-func TestIsUintptr(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: uintptr(1)}
- assert.True(t, v.IsUintptr())
-
- v = &Value{data: []uintptr{uintptr(1)}}
- assert.True(t, v.IsUintptrSlice())
-
-}
-
-func TestEachUintptr(t *testing.T) {
-
- v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
- count := 0
- replacedVals := make([]uintptr, 0)
- assert.Equal(t, v, v.EachUintptr(func(i int, val uintptr) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustUintptrSlice()[0])
- assert.Equal(t, replacedVals[1], v.MustUintptrSlice()[1])
- assert.Equal(t, replacedVals[2], v.MustUintptrSlice()[2])
-
-}
-
-func TestWhereUintptr(t *testing.T) {
-
- v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
-
- selected := v.WhereUintptr(func(i int, val uintptr) bool {
- return i%2 == 0
- }).MustUintptrSlice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupUintptr(t *testing.T) {
-
- v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
-
- grouped := v.GroupUintptr(func(i int, val uintptr) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]uintptr)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceUintptr(t *testing.T) {
-
- v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
-
- rawArr := v.MustUintptrSlice()
-
- replaced := v.ReplaceUintptr(func(index int, val uintptr) uintptr {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustUintptrSlice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectUintptr(t *testing.T) {
-
- v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
-
- collected := v.CollectUintptr(func(index int, val uintptr) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestFloat32(t *testing.T) {
-
- val := float32(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Float32())
- assert.Equal(t, val, New(m).Get("value").MustFloat32())
- assert.Equal(t, float32(0), New(m).Get("nothing").Float32())
- assert.Equal(t, val, New(m).Get("nothing").Float32(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustFloat32()
- })
-
-}
-
-func TestFloat32Slice(t *testing.T) {
-
- val := float32(1)
- m := map[string]interface{}{"value": []float32{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Float32Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustFloat32Slice()[0])
- assert.Equal(t, []float32(nil), New(m).Get("nothing").Float32Slice())
- assert.Equal(t, val, New(m).Get("nothing").Float32Slice([]float32{float32(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustFloat32Slice()
- })
-
-}
-
-func TestIsFloat32(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: float32(1)}
- assert.True(t, v.IsFloat32())
-
- v = &Value{data: []float32{float32(1)}}
- assert.True(t, v.IsFloat32Slice())
-
-}
-
-func TestEachFloat32(t *testing.T) {
-
- v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1)}}
- count := 0
- replacedVals := make([]float32, 0)
- assert.Equal(t, v, v.EachFloat32(func(i int, val float32) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustFloat32Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustFloat32Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustFloat32Slice()[2])
-
-}
-
-func TestWhereFloat32(t *testing.T) {
-
- v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
-
- selected := v.WhereFloat32(func(i int, val float32) bool {
- return i%2 == 0
- }).MustFloat32Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupFloat32(t *testing.T) {
-
- v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
-
- grouped := v.GroupFloat32(func(i int, val float32) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]float32)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceFloat32(t *testing.T) {
-
- v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
-
- rawArr := v.MustFloat32Slice()
-
- replaced := v.ReplaceFloat32(func(index int, val float32) float32 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustFloat32Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectFloat32(t *testing.T) {
-
- v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
-
- collected := v.CollectFloat32(func(index int, val float32) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestFloat64(t *testing.T) {
-
- val := float64(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Float64())
- assert.Equal(t, val, New(m).Get("value").MustFloat64())
- assert.Equal(t, float64(0), New(m).Get("nothing").Float64())
- assert.Equal(t, val, New(m).Get("nothing").Float64(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustFloat64()
- })
-
-}
-
-func TestFloat64Slice(t *testing.T) {
-
- val := float64(1)
- m := map[string]interface{}{"value": []float64{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Float64Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustFloat64Slice()[0])
- assert.Equal(t, []float64(nil), New(m).Get("nothing").Float64Slice())
- assert.Equal(t, val, New(m).Get("nothing").Float64Slice([]float64{float64(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustFloat64Slice()
- })
-
-}
-
-func TestIsFloat64(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: float64(1)}
- assert.True(t, v.IsFloat64())
-
- v = &Value{data: []float64{float64(1)}}
- assert.True(t, v.IsFloat64Slice())
-
-}
-
-func TestEachFloat64(t *testing.T) {
-
- v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1)}}
- count := 0
- replacedVals := make([]float64, 0)
- assert.Equal(t, v, v.EachFloat64(func(i int, val float64) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustFloat64Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustFloat64Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustFloat64Slice()[2])
-
-}
-
-func TestWhereFloat64(t *testing.T) {
-
- v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
-
- selected := v.WhereFloat64(func(i int, val float64) bool {
- return i%2 == 0
- }).MustFloat64Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupFloat64(t *testing.T) {
-
- v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
-
- grouped := v.GroupFloat64(func(i int, val float64) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]float64)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceFloat64(t *testing.T) {
-
- v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
-
- rawArr := v.MustFloat64Slice()
-
- replaced := v.ReplaceFloat64(func(index int, val float64) float64 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustFloat64Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectFloat64(t *testing.T) {
-
- v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
-
- collected := v.CollectFloat64(func(index int, val float64) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestComplex64(t *testing.T) {
-
- val := complex64(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Complex64())
- assert.Equal(t, val, New(m).Get("value").MustComplex64())
- assert.Equal(t, complex64(0), New(m).Get("nothing").Complex64())
- assert.Equal(t, val, New(m).Get("nothing").Complex64(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustComplex64()
- })
-
-}
-
-func TestComplex64Slice(t *testing.T) {
-
- val := complex64(1)
- m := map[string]interface{}{"value": []complex64{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Complex64Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustComplex64Slice()[0])
- assert.Equal(t, []complex64(nil), New(m).Get("nothing").Complex64Slice())
- assert.Equal(t, val, New(m).Get("nothing").Complex64Slice([]complex64{complex64(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustComplex64Slice()
- })
-
-}
-
-func TestIsComplex64(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: complex64(1)}
- assert.True(t, v.IsComplex64())
-
- v = &Value{data: []complex64{complex64(1)}}
- assert.True(t, v.IsComplex64Slice())
-
-}
-
-func TestEachComplex64(t *testing.T) {
-
- v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
- count := 0
- replacedVals := make([]complex64, 0)
- assert.Equal(t, v, v.EachComplex64(func(i int, val complex64) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustComplex64Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustComplex64Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustComplex64Slice()[2])
-
-}
-
-func TestWhereComplex64(t *testing.T) {
-
- v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
-
- selected := v.WhereComplex64(func(i int, val complex64) bool {
- return i%2 == 0
- }).MustComplex64Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupComplex64(t *testing.T) {
-
- v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
-
- grouped := v.GroupComplex64(func(i int, val complex64) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]complex64)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceComplex64(t *testing.T) {
-
- v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
-
- rawArr := v.MustComplex64Slice()
-
- replaced := v.ReplaceComplex64(func(index int, val complex64) complex64 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustComplex64Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectComplex64(t *testing.T) {
-
- v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
-
- collected := v.CollectComplex64(func(index int, val complex64) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
-
-// ************************************************************
-// TESTS
-// ************************************************************
-
-func TestComplex128(t *testing.T) {
-
- val := complex128(1)
- m := map[string]interface{}{"value": val, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Complex128())
- assert.Equal(t, val, New(m).Get("value").MustComplex128())
- assert.Equal(t, complex128(0), New(m).Get("nothing").Complex128())
- assert.Equal(t, val, New(m).Get("nothing").Complex128(1))
-
- assert.Panics(t, func() {
- New(m).Get("age").MustComplex128()
- })
-
-}
-
-func TestComplex128Slice(t *testing.T) {
-
- val := complex128(1)
- m := map[string]interface{}{"value": []complex128{val}, "nothing": nil}
- assert.Equal(t, val, New(m).Get("value").Complex128Slice()[0])
- assert.Equal(t, val, New(m).Get("value").MustComplex128Slice()[0])
- assert.Equal(t, []complex128(nil), New(m).Get("nothing").Complex128Slice())
- assert.Equal(t, val, New(m).Get("nothing").Complex128Slice([]complex128{complex128(1)})[0])
-
- assert.Panics(t, func() {
- New(m).Get("nothing").MustComplex128Slice()
- })
-
-}
-
-func TestIsComplex128(t *testing.T) {
-
- var v *Value
-
- v = &Value{data: complex128(1)}
- assert.True(t, v.IsComplex128())
-
- v = &Value{data: []complex128{complex128(1)}}
- assert.True(t, v.IsComplex128Slice())
-
-}
-
-func TestEachComplex128(t *testing.T) {
-
- v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
- count := 0
- replacedVals := make([]complex128, 0)
- assert.Equal(t, v, v.EachComplex128(func(i int, val complex128) bool {
-
- count++
- replacedVals = append(replacedVals, val)
-
- // abort early
- if i == 2 {
- return false
- }
-
- return true
-
- }))
-
- assert.Equal(t, count, 3)
- assert.Equal(t, replacedVals[0], v.MustComplex128Slice()[0])
- assert.Equal(t, replacedVals[1], v.MustComplex128Slice()[1])
- assert.Equal(t, replacedVals[2], v.MustComplex128Slice()[2])
-
-}
-
-func TestWhereComplex128(t *testing.T) {
-
- v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
-
- selected := v.WhereComplex128(func(i int, val complex128) bool {
- return i%2 == 0
- }).MustComplex128Slice()
-
- assert.Equal(t, 3, len(selected))
-
-}
-
-func TestGroupComplex128(t *testing.T) {
-
- v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
-
- grouped := v.GroupComplex128(func(i int, val complex128) string {
- return fmt.Sprintf("%v", i%2 == 0)
- }).data.(map[string][]complex128)
-
- assert.Equal(t, 2, len(grouped))
- assert.Equal(t, 3, len(grouped["true"]))
- assert.Equal(t, 3, len(grouped["false"]))
-
-}
-
-func TestReplaceComplex128(t *testing.T) {
-
- v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
-
- rawArr := v.MustComplex128Slice()
-
- replaced := v.ReplaceComplex128(func(index int, val complex128) complex128 {
- if index < len(rawArr)-1 {
- return rawArr[index+1]
- }
- return rawArr[0]
- })
-
- replacedArr := replaced.MustComplex128Slice()
- if assert.Equal(t, 6, len(replacedArr)) {
- assert.Equal(t, replacedArr[0], rawArr[1])
- assert.Equal(t, replacedArr[1], rawArr[2])
- assert.Equal(t, replacedArr[2], rawArr[3])
- assert.Equal(t, replacedArr[3], rawArr[4])
- assert.Equal(t, replacedArr[4], rawArr[5])
- assert.Equal(t, replacedArr[5], rawArr[0])
- }
-
-}
-
-func TestCollectComplex128(t *testing.T) {
-
- v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
-
- collected := v.CollectComplex128(func(index int, val complex128) interface{} {
- return index
- })
-
- collectedArr := collected.MustInterSlice()
- if assert.Equal(t, 6, len(collectedArr)) {
- assert.Equal(t, collectedArr[0], 0)
- assert.Equal(t, collectedArr[1], 1)
- assert.Equal(t, collectedArr[2], 2)
- assert.Equal(t, collectedArr[3], 3)
- assert.Equal(t, collectedArr[4], 4)
- assert.Equal(t, collectedArr[5], 5)
- }
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/value.go b/Godeps/_workspace/src/github.com/stretchr/objx/value.go
deleted file mode 100644
index 956a2211d..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/value.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package objx
-
-import (
- "fmt"
- "strconv"
-)
-
-// Value provides methods for extracting interface{} data in various
-// types.
-type Value struct {
- // data contains the raw data being managed by this Value
- data interface{}
-}
-
-// Data returns the raw data contained by this Value
-func (v *Value) Data() interface{} {
- return v.data
-}
-
-// String returns the value always as a string
-func (v *Value) String() string {
- switch {
- case v.IsStr():
- return v.Str()
- case v.IsBool():
- return strconv.FormatBool(v.Bool())
- case v.IsFloat32():
- return strconv.FormatFloat(float64(v.Float32()), 'f', -1, 32)
- case v.IsFloat64():
- return strconv.FormatFloat(v.Float64(), 'f', -1, 64)
- case v.IsInt():
- return strconv.FormatInt(int64(v.Int()), 10)
- case v.IsInt():
- return strconv.FormatInt(int64(v.Int()), 10)
- case v.IsInt8():
- return strconv.FormatInt(int64(v.Int8()), 10)
- case v.IsInt16():
- return strconv.FormatInt(int64(v.Int16()), 10)
- case v.IsInt32():
- return strconv.FormatInt(int64(v.Int32()), 10)
- case v.IsInt64():
- return strconv.FormatInt(v.Int64(), 10)
- case v.IsUint():
- return strconv.FormatUint(uint64(v.Uint()), 10)
- case v.IsUint8():
- return strconv.FormatUint(uint64(v.Uint8()), 10)
- case v.IsUint16():
- return strconv.FormatUint(uint64(v.Uint16()), 10)
- case v.IsUint32():
- return strconv.FormatUint(uint64(v.Uint32()), 10)
- case v.IsUint64():
- return strconv.FormatUint(v.Uint64(), 10)
- }
-
- return fmt.Sprintf("%#v", v.Data())
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/value_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/value_test.go
deleted file mode 100644
index 521405801..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/objx/value_test.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package objx
-
-import (
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-func TestStringTypeString(t *testing.T) {
- m := New(map[string]interface{}{"string": "foo"})
- assert.Equal(t, "foo", m.Get("string").String())
-}
-
-func TestStringTypeBool(t *testing.T) {
- m := New(map[string]interface{}{"bool": true})
- assert.Equal(t, "true", m.Get("bool").String())
-}
-
-func TestStringTypeInt(t *testing.T) {
- m := New(map[string]interface{}{
- "int": int(1),
- "int8": int8(8),
- "int16": int16(16),
- "int32": int32(32),
- "int64": int64(64),
- })
-
- assert.Equal(t, "1", m.Get("int").String())
- assert.Equal(t, "8", m.Get("int8").String())
- assert.Equal(t, "16", m.Get("int16").String())
- assert.Equal(t, "32", m.Get("int32").String())
- assert.Equal(t, "64", m.Get("int64").String())
-}
-
-func TestStringTypeUint(t *testing.T) {
- m := New(map[string]interface{}{
- "uint": uint(1),
- "uint8": uint8(8),
- "uint16": uint16(16),
- "uint32": uint32(32),
- "uint64": uint64(64),
- })
-
- assert.Equal(t, "1", m.Get("uint").String())
- assert.Equal(t, "8", m.Get("uint8").String())
- assert.Equal(t, "16", m.Get("uint16").String())
- assert.Equal(t, "32", m.Get("uint32").String())
- assert.Equal(t, "64", m.Get("uint64").String())
-}
-
-func TestStringTypeFloat(t *testing.T) {
- m := New(map[string]interface{}{
- "float32": float32(32.32),
- "float64": float64(64.64),
- })
-
- assert.Equal(t, "32.32", m.Get("float32").String())
- assert.Equal(t, "64.64", m.Get("float64").String())
-}
-
-func TestStringTypeOther(t *testing.T) {
- m := New(map[string]interface{}{
- "other": []string{"foo", "bar"},
- })
-
- assert.Equal(t, "[]string{\"foo\", \"bar\"}", m.Get("other").String())
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go
deleted file mode 100644
index 1935d18da..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go
+++ /dev/null
@@ -1,979 +0,0 @@
-package assert
-
-import (
- "bufio"
- "bytes"
- "encoding/json"
- "fmt"
- "math"
- "reflect"
- "regexp"
- "runtime"
- "strings"
- "time"
- "unicode"
- "unicode/utf8"
-
- "github.com/davecgh/go-spew/spew"
- "github.com/pmezard/go-difflib/difflib"
-)
-
-// TestingT is an interface wrapper around *testing.T
-type TestingT interface {
- Errorf(format string, args ...interface{})
-}
-
-// Comparison a custom function that returns true on success and false on failure
-type Comparison func() (success bool)
-
-/*
- Helper functions
-*/
-
-// ObjectsAreEqual determines if two objects are considered equal.
-//
-// This function does no assertion of any kind.
-func ObjectsAreEqual(expected, actual interface{}) bool {
-
- if expected == nil || actual == nil {
- return expected == actual
- }
-
- return reflect.DeepEqual(expected, actual)
-
-}
-
-// ObjectsAreEqualValues gets whether two objects are equal, or if their
-// values are equal.
-func ObjectsAreEqualValues(expected, actual interface{}) bool {
- if ObjectsAreEqual(expected, actual) {
- return true
- }
-
- actualType := reflect.TypeOf(actual)
- if actualType == nil {
- return false
- }
- expectedValue := reflect.ValueOf(expected)
- if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
- // Attempt comparison after type conversion
- return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
- }
-
- return false
-}
-
-/* CallerInfo is necessary because the assert functions use the testing object
-internally, causing it to print the file:line of the assert method, rather than where
-the problem actually occured in calling code.*/
-
-// CallerInfo returns an array of strings containing the file and line number
-// of each stack frame leading from the current test to the assert call that
-// failed.
-func CallerInfo() []string {
-
- pc := uintptr(0)
- file := ""
- line := 0
- ok := false
- name := ""
-
- callers := []string{}
- for i := 0; ; i++ {
- pc, file, line, ok = runtime.Caller(i)
- if !ok {
- return nil
- }
-
- // This is a huge edge case, but it will panic if this is the case, see #180
- if file == "<autogenerated>" {
- break
- }
-
- parts := strings.Split(file, "/")
- dir := parts[len(parts)-2]
- file = parts[len(parts)-1]
- if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
- callers = append(callers, fmt.Sprintf("%s:%d", file, line))
- }
-
- f := runtime.FuncForPC(pc)
- if f == nil {
- break
- }
- name = f.Name()
- // Drop the package
- segments := strings.Split(name, ".")
- name = segments[len(segments)-1]
- if isTest(name, "Test") ||
- isTest(name, "Benchmark") ||
- isTest(name, "Example") {
- break
- }
- }
-
- return callers
-}
-
-// Stolen from the `go test` tool.
-// isTest tells whether name looks like a test (or benchmark, according to prefix).
-// It is a Test (say) if there is a character after Test that is not a lower-case letter.
-// We don't want TesticularCancer.
-func isTest(name, prefix string) bool {
- if !strings.HasPrefix(name, prefix) {
- return false
- }
- if len(name) == len(prefix) { // "Test" is ok
- return true
- }
- rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
- return !unicode.IsLower(rune)
-}
-
-// getWhitespaceString returns a string that is long enough to overwrite the default
-// output from the go testing framework.
-func getWhitespaceString() string {
-
- _, file, line, ok := runtime.Caller(1)
- if !ok {
- return ""
- }
- parts := strings.Split(file, "/")
- file = parts[len(parts)-1]
-
- return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line)))
-
-}
-
-func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
- if len(msgAndArgs) == 0 || msgAndArgs == nil {
- return ""
- }
- if len(msgAndArgs) == 1 {
- return msgAndArgs[0].(string)
- }
- if len(msgAndArgs) > 1 {
- return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
- }
- return ""
-}
-
-// Indents all lines of the message by appending a number of tabs to each line, in an output format compatible with Go's
-// test printing (see inner comment for specifics)
-func indentMessageLines(message string, tabs int) string {
- outBuf := new(bytes.Buffer)
-
- for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
- if i != 0 {
- outBuf.WriteRune('\n')
- }
- for ii := 0; ii < tabs; ii++ {
- outBuf.WriteRune('\t')
- // Bizarrely, all lines except the first need one fewer tabs prepended, so deliberately advance the counter
- // by 1 prematurely.
- if ii == 0 && i > 0 {
- ii++
- }
- }
- outBuf.WriteString(scanner.Text())
- }
-
- return outBuf.String()
-}
-
-// Fail reports a failure through
-func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
-
- message := messageFromMsgAndArgs(msgAndArgs...)
-
- errorTrace := strings.Join(CallerInfo(), "\n\r\t\t\t")
- if len(message) > 0 {
- t.Errorf("\r%s\r\tError Trace:\t%s\n"+
- "\r\tError:%s\n"+
- "\r\tMessages:\t%s\n\r",
- getWhitespaceString(),
- errorTrace,
- indentMessageLines(failureMessage, 2),
- message)
- } else {
- t.Errorf("\r%s\r\tError Trace:\t%s\n"+
- "\r\tError:%s\n\r",
- getWhitespaceString(),
- errorTrace,
- indentMessageLines(failureMessage, 2))
- }
-
- return false
-}
-
-// Implements asserts that an object is implemented by the specified interface.
-//
-// assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
-func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
-
- interfaceType := reflect.TypeOf(interfaceObject).Elem()
-
- if !reflect.TypeOf(object).Implements(interfaceType) {
- return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...)
- }
-
- return true
-
-}
-
-// IsType asserts that the specified objects are of the same type.
-func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
-
- if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
- return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
- }
-
- return true
-}
-
-// Equal asserts that two objects are equal.
-//
-// assert.Equal(t, 123, 123, "123 and 123 should be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
-
- if !ObjectsAreEqual(expected, actual) {
- diff := diff(expected, actual)
- return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
- " != %#v (actual)%s", expected, actual, diff), msgAndArgs...)
- }
-
- return true
-
-}
-
-// EqualValues asserts that two objects are equal or convertable to the same types
-// and equal.
-//
-// assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
-
- if !ObjectsAreEqualValues(expected, actual) {
- return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
- " != %#v (actual)", expected, actual), msgAndArgs...)
- }
-
- return true
-
-}
-
-// Exactly asserts that two objects are equal is value and type.
-//
-// assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
-
- aType := reflect.TypeOf(expected)
- bType := reflect.TypeOf(actual)
-
- if aType != bType {
- return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...)
- }
-
- return Equal(t, expected, actual, msgAndArgs...)
-
-}
-
-// NotNil asserts that the specified object is not nil.
-//
-// assert.NotNil(t, err, "err should be something")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
- if !isNil(object) {
- return true
- }
- return Fail(t, "Expected value not to be nil.", msgAndArgs...)
-}
-
-// isNil checks if a specified object is nil or not, without Failing.
-func isNil(object interface{}) bool {
- if object == nil {
- return true
- }
-
- value := reflect.ValueOf(object)
- kind := value.Kind()
- if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
- return true
- }
-
- return false
-}
-
-// Nil asserts that the specified object is nil.
-//
-// assert.Nil(t, err, "err should be nothing")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
- if isNil(object) {
- return true
- }
- return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
-}
-
-var numericZeros = []interface{}{
- int(0),
- int8(0),
- int16(0),
- int32(0),
- int64(0),
- uint(0),
- uint8(0),
- uint16(0),
- uint32(0),
- uint64(0),
- float32(0),
- float64(0),
-}
-
-// isEmpty gets whether the specified object is considered empty or not.
-func isEmpty(object interface{}) bool {
-
- if object == nil {
- return true
- } else if object == "" {
- return true
- } else if object == false {
- return true
- }
-
- for _, v := range numericZeros {
- if object == v {
- return true
- }
- }
-
- objValue := reflect.ValueOf(object)
-
- switch objValue.Kind() {
- case reflect.Map:
- fallthrough
- case reflect.Slice, reflect.Chan:
- {
- return (objValue.Len() == 0)
- }
- case reflect.Ptr:
- {
- if objValue.IsNil() {
- return true
- }
- switch object.(type) {
- case *time.Time:
- return object.(*time.Time).IsZero()
- default:
- return false
- }
- }
- }
- return false
-}
-
-// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
-// a slice or a channel with len == 0.
-//
-// assert.Empty(t, obj)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
-
- pass := isEmpty(object)
- if !pass {
- Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
- }
-
- return pass
-
-}
-
-// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
-// a slice or a channel with len == 0.
-//
-// if assert.NotEmpty(t, obj) {
-// assert.Equal(t, "two", obj[1])
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
-
- pass := !isEmpty(object)
- if !pass {
- Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
- }
-
- return pass
-
-}
-
-// getLen try to get length of object.
-// return (false, 0) if impossible.
-func getLen(x interface{}) (ok bool, length int) {
- v := reflect.ValueOf(x)
- defer func() {
- if e := recover(); e != nil {
- ok = false
- }
- }()
- return true, v.Len()
-}
-
-// Len asserts that the specified object has specific length.
-// Len also fails if the object has a type that len() not accept.
-//
-// assert.Len(t, mySlice, 3, "The size of slice is not 3")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
- ok, l := getLen(object)
- if !ok {
- return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
- }
-
- if l != length {
- return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
- }
- return true
-}
-
-// True asserts that the specified value is true.
-//
-// assert.True(t, myBool, "myBool should be true")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
-
- if value != true {
- return Fail(t, "Should be true", msgAndArgs...)
- }
-
- return true
-
-}
-
-// False asserts that the specified value is true.
-//
-// assert.False(t, myBool, "myBool should be false")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
-
- if value != false {
- return Fail(t, "Should be false", msgAndArgs...)
- }
-
- return true
-
-}
-
-// NotEqual asserts that the specified values are NOT equal.
-//
-// assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
-
- if ObjectsAreEqual(expected, actual) {
- return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
- }
-
- return true
-
-}
-
-// containsElement try loop over the list check if the list includes the element.
-// return (false, false) if impossible.
-// return (true, false) if element was not found.
-// return (true, true) if element was found.
-func includeElement(list interface{}, element interface{}) (ok, found bool) {
-
- listValue := reflect.ValueOf(list)
- elementValue := reflect.ValueOf(element)
- defer func() {
- if e := recover(); e != nil {
- ok = false
- found = false
- }
- }()
-
- if reflect.TypeOf(list).Kind() == reflect.String {
- return true, strings.Contains(listValue.String(), elementValue.String())
- }
-
- if reflect.TypeOf(list).Kind() == reflect.Map {
- mapKeys := listValue.MapKeys()
- for i := 0; i < len(mapKeys); i++ {
- if ObjectsAreEqual(mapKeys[i].Interface(), element) {
- return true, true
- }
- }
- return true, false
- }
-
- for i := 0; i < listValue.Len(); i++ {
- if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
- return true, true
- }
- }
- return true, false
-
-}
-
-// Contains asserts that the specified string, list(array, slice...) or map contains the
-// specified substring or element.
-//
-// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
-// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
-// assert.Contains(t, {"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
-
- ok, found := includeElement(s, contains)
- if !ok {
- return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
- }
- if !found {
- return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
- }
-
- return true
-
-}
-
-// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
-// specified substring or element.
-//
-// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
-// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
-// assert.NotContains(t, {"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
-
- ok, found := includeElement(s, contains)
- if !ok {
- return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
- }
- if found {
- return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
- }
-
- return true
-
-}
-
-// Condition uses a Comparison to assert a complex condition.
-func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
- result := comp()
- if !result {
- Fail(t, "Condition failed!", msgAndArgs...)
- }
- return result
-}
-
-// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
-// methods, and represents a simple func that takes no arguments, and returns nothing.
-type PanicTestFunc func()
-
-// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
-func didPanic(f PanicTestFunc) (bool, interface{}) {
-
- didPanic := false
- var message interface{}
- func() {
-
- defer func() {
- if message = recover(); message != nil {
- didPanic = true
- }
- }()
-
- // call the target function
- f()
-
- }()
-
- return didPanic, message
-
-}
-
-// Panics asserts that the code inside the specified PanicTestFunc panics.
-//
-// assert.Panics(t, func(){
-// GoCrazy()
-// }, "Calling GoCrazy() should panic")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
-
- if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
- return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
- }
-
- return true
-}
-
-// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
-//
-// assert.NotPanics(t, func(){
-// RemainCalm()
-// }, "Calling RemainCalm() should NOT panic")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
-
- if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
- return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
- }
-
- return true
-}
-
-// WithinDuration asserts that the two times are within duration delta of each other.
-//
-// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
-
- dt := expected.Sub(actual)
- if dt < -delta || dt > delta {
- return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
- }
-
- return true
-}
-
-func toFloat(x interface{}) (float64, bool) {
- var xf float64
- xok := true
-
- switch xn := x.(type) {
- case uint8:
- xf = float64(xn)
- case uint16:
- xf = float64(xn)
- case uint32:
- xf = float64(xn)
- case uint64:
- xf = float64(xn)
- case int:
- xf = float64(xn)
- case int8:
- xf = float64(xn)
- case int16:
- xf = float64(xn)
- case int32:
- xf = float64(xn)
- case int64:
- xf = float64(xn)
- case float32:
- xf = float64(xn)
- case float64:
- xf = float64(xn)
- default:
- xok = false
- }
-
- return xf, xok
-}
-
-// InDelta asserts that the two numerals are within delta of each other.
-//
-// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
-
- af, aok := toFloat(expected)
- bf, bok := toFloat(actual)
-
- if !aok || !bok {
- return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...)
- }
-
- if math.IsNaN(af) {
- return Fail(t, fmt.Sprintf("Actual must not be NaN"), msgAndArgs...)
- }
-
- if math.IsNaN(bf) {
- return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...)
- }
-
- dt := af - bf
- if dt < -delta || dt > delta {
- return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
- }
-
- return true
-}
-
-// InDeltaSlice is the same as InDelta, except it compares two slices.
-func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
- if expected == nil || actual == nil ||
- reflect.TypeOf(actual).Kind() != reflect.Slice ||
- reflect.TypeOf(expected).Kind() != reflect.Slice {
- return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
- }
-
- actualSlice := reflect.ValueOf(actual)
- expectedSlice := reflect.ValueOf(expected)
-
- for i := 0; i < actualSlice.Len(); i++ {
- result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta)
- if !result {
- return result
- }
- }
-
- return true
-}
-
-// min(|expected|, |actual|) * epsilon
-func calcEpsilonDelta(expected, actual interface{}, epsilon float64) float64 {
- af, aok := toFloat(expected)
- bf, bok := toFloat(actual)
-
- if !aok || !bok {
- // invalid input
- return 0
- }
-
- if af < 0 {
- af = -af
- }
- if bf < 0 {
- bf = -bf
- }
- var delta float64
- if af < bf {
- delta = af * epsilon
- } else {
- delta = bf * epsilon
- }
- return delta
-}
-
-// InEpsilon asserts that expected and actual have a relative error less than epsilon
-//
-// Returns whether the assertion was successful (true) or not (false).
-func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
- delta := calcEpsilonDelta(expected, actual, epsilon)
-
- return InDelta(t, expected, actual, delta, msgAndArgs...)
-}
-
-// InEpsilonSlice is the same as InEpsilon, except it compares two slices.
-func InEpsilonSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
- if expected == nil || actual == nil ||
- reflect.TypeOf(actual).Kind() != reflect.Slice ||
- reflect.TypeOf(expected).Kind() != reflect.Slice {
- return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
- }
-
- actualSlice := reflect.ValueOf(actual)
- expectedSlice := reflect.ValueOf(expected)
-
- for i := 0; i < actualSlice.Len(); i++ {
- result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta)
- if !result {
- return result
- }
- }
-
- return true
-}
-
-/*
- Errors
-*/
-
-// NoError asserts that a function returned no error (i.e. `nil`).
-//
-// actualObj, err := SomeFunction()
-// if assert.NoError(t, err) {
-// assert.Equal(t, actualObj, expectedObj)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
- if isNil(err) {
- return true
- }
-
- return Fail(t, fmt.Sprintf("Received unexpected error %q", err), msgAndArgs...)
-}
-
-// Error asserts that a function returned an error (i.e. not `nil`).
-//
-// actualObj, err := SomeFunction()
-// if assert.Error(t, err, "An error was expected") {
-// assert.Equal(t, err, expectedError)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
-
- message := messageFromMsgAndArgs(msgAndArgs...)
- return NotNil(t, err, "An error is expected but got nil. %s", message)
-
-}
-
-// EqualError asserts that a function returned an error (i.e. not `nil`)
-// and that it is equal to the provided error.
-//
-// actualObj, err := SomeFunction()
-// if assert.Error(t, err, "An error was expected") {
-// assert.Equal(t, err, expectedError)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
-
- message := messageFromMsgAndArgs(msgAndArgs...)
- if !NotNil(t, theError, "An error is expected but got nil. %s", message) {
- return false
- }
- s := "An error with value \"%s\" is expected but got \"%s\". %s"
- return Equal(t, errString, theError.Error(),
- s, errString, theError.Error(), message)
-}
-
-// matchRegexp return true if a specified regexp matches a string.
-func matchRegexp(rx interface{}, str interface{}) bool {
-
- var r *regexp.Regexp
- if rr, ok := rx.(*regexp.Regexp); ok {
- r = rr
- } else {
- r = regexp.MustCompile(fmt.Sprint(rx))
- }
-
- return (r.FindStringIndex(fmt.Sprint(str)) != nil)
-
-}
-
-// Regexp asserts that a specified regexp matches a string.
-//
-// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
-// assert.Regexp(t, "start...$", "it's not starting")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
-
- match := matchRegexp(rx, str)
-
- if !match {
- Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...)
- }
-
- return match
-}
-
-// NotRegexp asserts that a specified regexp does not match a string.
-//
-// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
-// assert.NotRegexp(t, "^start", "it's not starting")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
- match := matchRegexp(rx, str)
-
- if match {
- Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...)
- }
-
- return !match
-
-}
-
-// Zero asserts that i is the zero value for its type and returns the truth.
-func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
- if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
- return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
- }
- return true
-}
-
-// NotZero asserts that i is not the zero value for its type and returns the truth.
-func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
- if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
- return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
- }
- return true
-}
-
-// JSONEq asserts that two JSON strings are equivalent.
-//
-// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
- var expectedJSONAsInterface, actualJSONAsInterface interface{}
-
- if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
- return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...)
- }
-
- if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil {
- return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...)
- }
-
- return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
-}
-
-func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
- t := reflect.TypeOf(v)
- k := t.Kind()
-
- if k == reflect.Ptr {
- t = t.Elem()
- k = t.Kind()
- }
- return t, k
-}
-
-// diff returns a diff of both values as long as both are of the same type and
-// are a struct, map, slice or array. Otherwise it returns an empty string.
-func diff(expected interface{}, actual interface{}) string {
- if expected == nil || actual == nil {
- return ""
- }
-
- et, ek := typeAndKind(expected)
- at, _ := typeAndKind(actual)
-
- if et != at {
- return ""
- }
-
- if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array {
- return ""
- }
-
- spew.Config.SortKeys = true
- e := spew.Sdump(expected)
- a := spew.Sdump(actual)
-
- diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
- A: difflib.SplitLines(e),
- B: difflib.SplitLines(a),
- FromFile: "Expected",
- FromDate: "",
- ToFile: "Actual",
- ToDate: "",
- Context: 1,
- })
-
- return "\n\nDiff:\n" + diff
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go
deleted file mode 100644
index a12352e4c..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go
+++ /dev/null
@@ -1,1089 +0,0 @@
-package assert
-
-import (
- "errors"
- "io"
- "math"
- "os"
- "reflect"
- "regexp"
- "testing"
- "time"
-)
-
-var (
- i interface{}
- zeros = []interface{}{
- false,
- byte(0),
- complex64(0),
- complex128(0),
- float32(0),
- float64(0),
- int(0),
- int8(0),
- int16(0),
- int32(0),
- int64(0),
- rune(0),
- uint(0),
- uint8(0),
- uint16(0),
- uint32(0),
- uint64(0),
- uintptr(0),
- "",
- [0]interface{}{},
- []interface{}(nil),
- struct{ x int }{},
- (*interface{})(nil),
- (func())(nil),
- nil,
- interface{}(nil),
- map[interface{}]interface{}(nil),
- (chan interface{})(nil),
- (<-chan interface{})(nil),
- (chan<- interface{})(nil),
- }
- nonZeros = []interface{}{
- true,
- byte(1),
- complex64(1),
- complex128(1),
- float32(1),
- float64(1),
- int(1),
- int8(1),
- int16(1),
- int32(1),
- int64(1),
- rune(1),
- uint(1),
- uint8(1),
- uint16(1),
- uint32(1),
- uint64(1),
- uintptr(1),
- "s",
- [1]interface{}{1},
- []interface{}{},
- struct{ x int }{1},
- (*interface{})(&i),
- (func())(func() {}),
- interface{}(1),
- map[interface{}]interface{}{},
- (chan interface{})(make(chan interface{})),
- (<-chan interface{})(make(chan interface{})),
- (chan<- interface{})(make(chan interface{})),
- }
-)
-
-// AssertionTesterInterface defines an interface to be used for testing assertion methods
-type AssertionTesterInterface interface {
- TestMethod()
-}
-
-// AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface
-type AssertionTesterConformingObject struct {
-}
-
-func (a *AssertionTesterConformingObject) TestMethod() {
-}
-
-// AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface
-type AssertionTesterNonConformingObject struct {
-}
-
-func TestObjectsAreEqual(t *testing.T) {
-
- if !ObjectsAreEqual("Hello World", "Hello World") {
- t.Error("objectsAreEqual should return true")
- }
- if !ObjectsAreEqual(123, 123) {
- t.Error("objectsAreEqual should return true")
- }
- if !ObjectsAreEqual(123.5, 123.5) {
- t.Error("objectsAreEqual should return true")
- }
- if !ObjectsAreEqual([]byte("Hello World"), []byte("Hello World")) {
- t.Error("objectsAreEqual should return true")
- }
- if !ObjectsAreEqual(nil, nil) {
- t.Error("objectsAreEqual should return true")
- }
- if ObjectsAreEqual(map[int]int{5: 10}, map[int]int{10: 20}) {
- t.Error("objectsAreEqual should return false")
- }
- if ObjectsAreEqual('x', "x") {
- t.Error("objectsAreEqual should return false")
- }
- if ObjectsAreEqual("x", 'x') {
- t.Error("objectsAreEqual should return false")
- }
- if ObjectsAreEqual(0, 0.1) {
- t.Error("objectsAreEqual should return false")
- }
- if ObjectsAreEqual(0.1, 0) {
- t.Error("objectsAreEqual should return false")
- }
- if ObjectsAreEqual(uint32(10), int32(10)) {
- t.Error("objectsAreEqual should return false")
- }
- if !ObjectsAreEqualValues(uint32(10), int32(10)) {
- t.Error("ObjectsAreEqualValues should return true")
- }
- if ObjectsAreEqualValues(0, nil) {
- t.Fail()
- }
- if ObjectsAreEqualValues(nil, 0) {
- t.Fail()
- }
-
-}
-
-func TestImplements(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) {
- t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface")
- }
- if Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) {
- t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface")
- }
-
-}
-
-func TestIsType(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) {
- t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject")
- }
- if IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) {
- t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject")
- }
-
-}
-
-func TestEqual(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !Equal(mockT, "Hello World", "Hello World") {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, 123, 123) {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, 123.5, 123.5) {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, []byte("Hello World"), []byte("Hello World")) {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, nil, nil) {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, int32(123), int32(123)) {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, uint64(123), uint64(123)) {
- t.Error("Equal should return true")
- }
-
-}
-
-func TestNotNil(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !NotNil(mockT, new(AssertionTesterConformingObject)) {
- t.Error("NotNil should return true: object is not nil")
- }
- if NotNil(mockT, nil) {
- t.Error("NotNil should return false: object is nil")
- }
- if NotNil(mockT, (*struct{})(nil)) {
- t.Error("NotNil should return false: object is (*struct{})(nil)")
- }
-
-}
-
-func TestNil(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !Nil(mockT, nil) {
- t.Error("Nil should return true: object is nil")
- }
- if !Nil(mockT, (*struct{})(nil)) {
- t.Error("Nil should return true: object is (*struct{})(nil)")
- }
- if Nil(mockT, new(AssertionTesterConformingObject)) {
- t.Error("Nil should return false: object is not nil")
- }
-
-}
-
-func TestTrue(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !True(mockT, true) {
- t.Error("True should return true")
- }
- if True(mockT, false) {
- t.Error("True should return false")
- }
-
-}
-
-func TestFalse(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !False(mockT, false) {
- t.Error("False should return true")
- }
- if False(mockT, true) {
- t.Error("False should return false")
- }
-
-}
-
-func TestExactly(t *testing.T) {
-
- mockT := new(testing.T)
-
- a := float32(1)
- b := float64(1)
- c := float32(1)
- d := float32(2)
-
- if Exactly(mockT, a, b) {
- t.Error("Exactly should return false")
- }
- if Exactly(mockT, a, d) {
- t.Error("Exactly should return false")
- }
- if !Exactly(mockT, a, c) {
- t.Error("Exactly should return true")
- }
-
- if Exactly(mockT, nil, a) {
- t.Error("Exactly should return false")
- }
- if Exactly(mockT, a, nil) {
- t.Error("Exactly should return false")
- }
-
-}
-
-func TestNotEqual(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !NotEqual(mockT, "Hello World", "Hello World!") {
- t.Error("NotEqual should return true")
- }
- if !NotEqual(mockT, 123, 1234) {
- t.Error("NotEqual should return true")
- }
- if !NotEqual(mockT, 123.5, 123.55) {
- t.Error("NotEqual should return true")
- }
- if !NotEqual(mockT, []byte("Hello World"), []byte("Hello World!")) {
- t.Error("NotEqual should return true")
- }
- if !NotEqual(mockT, nil, new(AssertionTesterConformingObject)) {
- t.Error("NotEqual should return true")
- }
- funcA := func() int { return 23 }
- funcB := func() int { return 42 }
- if !NotEqual(mockT, funcA, funcB) {
- t.Error("NotEqual should return true")
- }
-
- if NotEqual(mockT, "Hello World", "Hello World") {
- t.Error("NotEqual should return false")
- }
- if NotEqual(mockT, 123, 123) {
- t.Error("NotEqual should return false")
- }
- if NotEqual(mockT, 123.5, 123.5) {
- t.Error("NotEqual should return false")
- }
- if NotEqual(mockT, []byte("Hello World"), []byte("Hello World")) {
- t.Error("NotEqual should return false")
- }
- if NotEqual(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) {
- t.Error("NotEqual should return false")
- }
-}
-
-type A struct {
- Name, Value string
-}
-
-func TestContains(t *testing.T) {
-
- mockT := new(testing.T)
- list := []string{"Foo", "Bar"}
- complexList := []*A{
- {"b", "c"},
- {"d", "e"},
- {"g", "h"},
- {"j", "k"},
- }
- simpleMap := map[interface{}]interface{}{"Foo": "Bar"}
-
- if !Contains(mockT, "Hello World", "Hello") {
- t.Error("Contains should return true: \"Hello World\" contains \"Hello\"")
- }
- if Contains(mockT, "Hello World", "Salut") {
- t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"")
- }
-
- if !Contains(mockT, list, "Bar") {
- t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Bar\"")
- }
- if Contains(mockT, list, "Salut") {
- t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"")
- }
- if !Contains(mockT, complexList, &A{"g", "h"}) {
- t.Error("Contains should return true: complexList contains {\"g\", \"h\"}")
- }
- if Contains(mockT, complexList, &A{"g", "e"}) {
- t.Error("Contains should return false: complexList contains {\"g\", \"e\"}")
- }
- if Contains(mockT, complexList, &A{"g", "e"}) {
- t.Error("Contains should return false: complexList contains {\"g\", \"e\"}")
- }
- if !Contains(mockT, simpleMap, "Foo") {
- t.Error("Contains should return true: \"{\"Foo\": \"Bar\"}\" contains \"Foo\"")
- }
- if Contains(mockT, simpleMap, "Bar") {
- t.Error("Contains should return false: \"{\"Foo\": \"Bar\"}\" does not contains \"Bar\"")
- }
-}
-
-func TestNotContains(t *testing.T) {
-
- mockT := new(testing.T)
- list := []string{"Foo", "Bar"}
- simpleMap := map[interface{}]interface{}{"Foo": "Bar"}
-
- if !NotContains(mockT, "Hello World", "Hello!") {
- t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"")
- }
- if NotContains(mockT, "Hello World", "Hello") {
- t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"")
- }
-
- if !NotContains(mockT, list, "Foo!") {
- t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"")
- }
- if NotContains(mockT, list, "Foo") {
- t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
- }
- if NotContains(mockT, simpleMap, "Foo") {
- t.Error("Contains should return true: \"{\"Foo\": \"Bar\"}\" contains \"Foo\"")
- }
- if !NotContains(mockT, simpleMap, "Bar") {
- t.Error("Contains should return false: \"{\"Foo\": \"Bar\"}\" does not contains \"Bar\"")
- }
-}
-
-func Test_includeElement(t *testing.T) {
-
- list1 := []string{"Foo", "Bar"}
- list2 := []int{1, 2}
- simpleMap := map[interface{}]interface{}{"Foo": "Bar"}
-
- ok, found := includeElement("Hello World", "World")
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(list1, "Foo")
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(list1, "Bar")
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(list2, 1)
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(list2, 2)
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(list1, "Foo!")
- True(t, ok)
- False(t, found)
-
- ok, found = includeElement(list2, 3)
- True(t, ok)
- False(t, found)
-
- ok, found = includeElement(list2, "1")
- True(t, ok)
- False(t, found)
-
- ok, found = includeElement(simpleMap, "Foo")
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(simpleMap, "Bar")
- True(t, ok)
- False(t, found)
-
- ok, found = includeElement(1433, "1")
- False(t, ok)
- False(t, found)
-}
-
-func TestCondition(t *testing.T) {
- mockT := new(testing.T)
-
- if !Condition(mockT, func() bool { return true }, "Truth") {
- t.Error("Condition should return true")
- }
-
- if Condition(mockT, func() bool { return false }, "Lie") {
- t.Error("Condition should return false")
- }
-
-}
-
-func TestDidPanic(t *testing.T) {
-
- if funcDidPanic, _ := didPanic(func() {
- panic("Panic!")
- }); !funcDidPanic {
- t.Error("didPanic should return true")
- }
-
- if funcDidPanic, _ := didPanic(func() {
- }); funcDidPanic {
- t.Error("didPanic should return false")
- }
-
-}
-
-func TestPanics(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !Panics(mockT, func() {
- panic("Panic!")
- }) {
- t.Error("Panics should return true")
- }
-
- if Panics(mockT, func() {
- }) {
- t.Error("Panics should return false")
- }
-
-}
-
-func TestNotPanics(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !NotPanics(mockT, func() {
- }) {
- t.Error("NotPanics should return true")
- }
-
- if NotPanics(mockT, func() {
- panic("Panic!")
- }) {
- t.Error("NotPanics should return false")
- }
-
-}
-
-func TestNoError(t *testing.T) {
-
- mockT := new(testing.T)
-
- // start with a nil error
- var err error
-
- True(t, NoError(mockT, err), "NoError should return True for nil arg")
-
- // now set an error
- err = errors.New("some error")
-
- False(t, NoError(mockT, err), "NoError with error should return False")
-
-}
-
-func TestError(t *testing.T) {
-
- mockT := new(testing.T)
-
- // start with a nil error
- var err error
-
- False(t, Error(mockT, err), "Error should return False for nil arg")
-
- // now set an error
- err = errors.New("some error")
-
- True(t, Error(mockT, err), "Error with error should return True")
-
-}
-
-func TestEqualError(t *testing.T) {
- mockT := new(testing.T)
-
- // start with a nil error
- var err error
- False(t, EqualError(mockT, err, ""),
- "EqualError should return false for nil arg")
-
- // now set an error
- err = errors.New("some error")
- False(t, EqualError(mockT, err, "Not some error"),
- "EqualError should return false for different error string")
- True(t, EqualError(mockT, err, "some error"),
- "EqualError should return true")
-}
-
-func Test_isEmpty(t *testing.T) {
-
- chWithValue := make(chan struct{}, 1)
- chWithValue <- struct{}{}
-
- True(t, isEmpty(""))
- True(t, isEmpty(nil))
- True(t, isEmpty([]string{}))
- True(t, isEmpty(0))
- True(t, isEmpty(int32(0)))
- True(t, isEmpty(int64(0)))
- True(t, isEmpty(false))
- True(t, isEmpty(map[string]string{}))
- True(t, isEmpty(new(time.Time)))
- True(t, isEmpty(make(chan struct{})))
- False(t, isEmpty("something"))
- False(t, isEmpty(errors.New("something")))
- False(t, isEmpty([]string{"something"}))
- False(t, isEmpty(1))
- False(t, isEmpty(true))
- False(t, isEmpty(map[string]string{"Hello": "World"}))
- False(t, isEmpty(chWithValue))
-
-}
-
-func TestEmpty(t *testing.T) {
-
- mockT := new(testing.T)
- chWithValue := make(chan struct{}, 1)
- chWithValue <- struct{}{}
- var ti *time.Time
- var s *string
- var f *os.File
-
- True(t, Empty(mockT, ""), "Empty string is empty")
- True(t, Empty(mockT, nil), "Nil is empty")
- True(t, Empty(mockT, []string{}), "Empty string array is empty")
- True(t, Empty(mockT, 0), "Zero int value is empty")
- True(t, Empty(mockT, false), "False value is empty")
- True(t, Empty(mockT, make(chan struct{})), "Channel without values is empty")
- True(t, Empty(mockT, s), "Nil string pointer is empty")
- True(t, Empty(mockT, f), "Nil os.File pointer is empty")
- True(t, Empty(mockT, ti), "Nil time.Time pointer is empty")
-
- False(t, Empty(mockT, "something"), "Non Empty string is not empty")
- False(t, Empty(mockT, errors.New("something")), "Non nil object is not empty")
- False(t, Empty(mockT, []string{"something"}), "Non empty string array is not empty")
- False(t, Empty(mockT, 1), "Non-zero int value is not empty")
- False(t, Empty(mockT, true), "True value is not empty")
- False(t, Empty(mockT, chWithValue), "Channel with values is not empty")
-}
-
-func TestNotEmpty(t *testing.T) {
-
- mockT := new(testing.T)
- chWithValue := make(chan struct{}, 1)
- chWithValue <- struct{}{}
-
- False(t, NotEmpty(mockT, ""), "Empty string is empty")
- False(t, NotEmpty(mockT, nil), "Nil is empty")
- False(t, NotEmpty(mockT, []string{}), "Empty string array is empty")
- False(t, NotEmpty(mockT, 0), "Zero int value is empty")
- False(t, NotEmpty(mockT, false), "False value is empty")
- False(t, NotEmpty(mockT, make(chan struct{})), "Channel without values is empty")
-
- True(t, NotEmpty(mockT, "something"), "Non Empty string is not empty")
- True(t, NotEmpty(mockT, errors.New("something")), "Non nil object is not empty")
- True(t, NotEmpty(mockT, []string{"something"}), "Non empty string array is not empty")
- True(t, NotEmpty(mockT, 1), "Non-zero int value is not empty")
- True(t, NotEmpty(mockT, true), "True value is not empty")
- True(t, NotEmpty(mockT, chWithValue), "Channel with values is not empty")
-}
-
-func Test_getLen(t *testing.T) {
- falseCases := []interface{}{
- nil,
- 0,
- true,
- false,
- 'A',
- struct{}{},
- }
- for _, v := range falseCases {
- ok, l := getLen(v)
- False(t, ok, "Expected getLen fail to get length of %#v", v)
- Equal(t, 0, l, "getLen should return 0 for %#v", v)
- }
-
- ch := make(chan int, 5)
- ch <- 1
- ch <- 2
- ch <- 3
- trueCases := []struct {
- v interface{}
- l int
- }{
- {[]int{1, 2, 3}, 3},
- {[...]int{1, 2, 3}, 3},
- {"ABC", 3},
- {map[int]int{1: 2, 2: 4, 3: 6}, 3},
- {ch, 3},
-
- {[]int{}, 0},
- {map[int]int{}, 0},
- {make(chan int), 0},
-
- {[]int(nil), 0},
- {map[int]int(nil), 0},
- {(chan int)(nil), 0},
- }
-
- for _, c := range trueCases {
- ok, l := getLen(c.v)
- True(t, ok, "Expected getLen success to get length of %#v", c.v)
- Equal(t, c.l, l)
- }
-}
-
-func TestLen(t *testing.T) {
- mockT := new(testing.T)
-
- False(t, Len(mockT, nil, 0), "nil does not have length")
- False(t, Len(mockT, 0, 0), "int does not have length")
- False(t, Len(mockT, true, 0), "true does not have length")
- False(t, Len(mockT, false, 0), "false does not have length")
- False(t, Len(mockT, 'A', 0), "Rune does not have length")
- False(t, Len(mockT, struct{}{}, 0), "Struct does not have length")
-
- ch := make(chan int, 5)
- ch <- 1
- ch <- 2
- ch <- 3
-
- cases := []struct {
- v interface{}
- l int
- }{
- {[]int{1, 2, 3}, 3},
- {[...]int{1, 2, 3}, 3},
- {"ABC", 3},
- {map[int]int{1: 2, 2: 4, 3: 6}, 3},
- {ch, 3},
-
- {[]int{}, 0},
- {map[int]int{}, 0},
- {make(chan int), 0},
-
- {[]int(nil), 0},
- {map[int]int(nil), 0},
- {(chan int)(nil), 0},
- }
-
- for _, c := range cases {
- True(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l)
- }
-
- cases = []struct {
- v interface{}
- l int
- }{
- {[]int{1, 2, 3}, 4},
- {[...]int{1, 2, 3}, 2},
- {"ABC", 2},
- {map[int]int{1: 2, 2: 4, 3: 6}, 4},
- {ch, 2},
-
- {[]int{}, 1},
- {map[int]int{}, 1},
- {make(chan int), 1},
-
- {[]int(nil), 1},
- {map[int]int(nil), 1},
- {(chan int)(nil), 1},
- }
-
- for _, c := range cases {
- False(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l)
- }
-}
-
-func TestWithinDuration(t *testing.T) {
-
- mockT := new(testing.T)
- a := time.Now()
- b := a.Add(10 * time.Second)
-
- True(t, WithinDuration(mockT, a, b, 10*time.Second), "A 10s difference is within a 10s time difference")
- True(t, WithinDuration(mockT, b, a, 10*time.Second), "A 10s difference is within a 10s time difference")
-
- False(t, WithinDuration(mockT, a, b, 9*time.Second), "A 10s difference is not within a 9s time difference")
- False(t, WithinDuration(mockT, b, a, 9*time.Second), "A 10s difference is not within a 9s time difference")
-
- False(t, WithinDuration(mockT, a, b, -9*time.Second), "A 10s difference is not within a 9s time difference")
- False(t, WithinDuration(mockT, b, a, -9*time.Second), "A 10s difference is not within a 9s time difference")
-
- False(t, WithinDuration(mockT, a, b, -11*time.Second), "A 10s difference is not within a 9s time difference")
- False(t, WithinDuration(mockT, b, a, -11*time.Second), "A 10s difference is not within a 9s time difference")
-}
-
-func TestInDelta(t *testing.T) {
- mockT := new(testing.T)
-
- True(t, InDelta(mockT, 1.001, 1, 0.01), "|1.001 - 1| <= 0.01")
- True(t, InDelta(mockT, 1, 1.001, 0.01), "|1 - 1.001| <= 0.01")
- True(t, InDelta(mockT, 1, 2, 1), "|1 - 2| <= 1")
- False(t, InDelta(mockT, 1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail")
- False(t, InDelta(mockT, 2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail")
- False(t, InDelta(mockT, "", nil, 1), "Expected non numerals to fail")
- False(t, InDelta(mockT, 42, math.NaN(), 0.01), "Expected NaN for actual to fail")
- False(t, InDelta(mockT, math.NaN(), 42, 0.01), "Expected NaN for expected to fail")
-
- cases := []struct {
- a, b interface{}
- delta float64
- }{
- {uint8(2), uint8(1), 1},
- {uint16(2), uint16(1), 1},
- {uint32(2), uint32(1), 1},
- {uint64(2), uint64(1), 1},
-
- {int(2), int(1), 1},
- {int8(2), int8(1), 1},
- {int16(2), int16(1), 1},
- {int32(2), int32(1), 1},
- {int64(2), int64(1), 1},
-
- {float32(2), float32(1), 1},
- {float64(2), float64(1), 1},
- }
-
- for _, tc := range cases {
- True(t, InDelta(mockT, tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta)
- }
-}
-
-func TestInDeltaSlice(t *testing.T) {
- mockT := new(testing.T)
-
- True(t, InDeltaSlice(mockT,
- []float64{1.001, 0.999},
- []float64{1, 1},
- 0.1), "{1.001, 0.009} is element-wise close to {1, 1} in delta=0.1")
-
- True(t, InDeltaSlice(mockT,
- []float64{1, 2},
- []float64{0, 3},
- 1), "{1, 2} is element-wise close to {0, 3} in delta=1")
-
- False(t, InDeltaSlice(mockT,
- []float64{1, 2},
- []float64{0, 3},
- 0.1), "{1, 2} is not element-wise close to {0, 3} in delta=0.1")
-
- False(t, InDeltaSlice(mockT, "", nil, 1), "Expected non numeral slices to fail")
-}
-
-func TestInEpsilon(t *testing.T) {
- mockT := new(testing.T)
-
- cases := []struct {
- a, b interface{}
- epsilon float64
- }{
- {uint8(2), uint16(2), .001},
- {2.1, 2.2, 0.1},
- {2.2, 2.1, 0.1},
- {-2.1, -2.2, 0.1},
- {-2.2, -2.1, 0.1},
- {uint64(100), uint8(101), 0.01},
- {0.1, -0.1, 2},
- }
-
- for _, tc := range cases {
- True(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
- }
-
- cases = []struct {
- a, b interface{}
- epsilon float64
- }{
- {uint8(2), int16(-2), .001},
- {uint64(100), uint8(102), 0.01},
- {2.1, 2.2, 0.001},
- {2.2, 2.1, 0.001},
- {2.1, -2.2, 1},
- {2.1, "bla-bla", 0},
- {0.1, -0.1, 1.99},
- }
-
- for _, tc := range cases {
- False(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
- }
-
-}
-
-func TestInEpsilonSlice(t *testing.T) {
- mockT := new(testing.T)
-
- True(t, InEpsilonSlice(mockT,
- []float64{2.2, 2.0},
- []float64{2.1, 2.1},
- 0.06), "{2.2, 2.0} is element-wise close to {2.1, 2.1} in espilon=0.06")
-
- False(t, InEpsilonSlice(mockT,
- []float64{2.2, 2.0},
- []float64{2.1, 2.1},
- 0.04), "{2.2, 2.0} is not element-wise close to {2.1, 2.1} in espilon=0.04")
-
- False(t, InEpsilonSlice(mockT, "", nil, 1), "Expected non numeral slices to fail")
-}
-
-func TestRegexp(t *testing.T) {
- mockT := new(testing.T)
-
- cases := []struct {
- rx, str string
- }{
- {"^start", "start of the line"},
- {"end$", "in the end"},
- {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"},
- }
-
- for _, tc := range cases {
- True(t, Regexp(mockT, tc.rx, tc.str))
- True(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str))
- False(t, NotRegexp(mockT, tc.rx, tc.str))
- False(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str))
- }
-
- cases = []struct {
- rx, str string
- }{
- {"^asdfastart", "Not the start of the line"},
- {"end$", "in the end."},
- {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"},
- }
-
- for _, tc := range cases {
- False(t, Regexp(mockT, tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str)
- False(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str))
- True(t, NotRegexp(mockT, tc.rx, tc.str))
- True(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str))
- }
-}
-
-func testAutogeneratedFunction() {
- defer func() {
- if err := recover(); err == nil {
- panic("did not panic")
- }
- CallerInfo()
- }()
- t := struct {
- io.Closer
- }{}
- var c io.Closer
- c = t
- c.Close()
-}
-
-func TestCallerInfoWithAutogeneratedFunctions(t *testing.T) {
- NotPanics(t, func() {
- testAutogeneratedFunction()
- })
-}
-
-func TestZero(t *testing.T) {
- mockT := new(testing.T)
-
- for _, test := range zeros {
- True(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
- }
-
- for _, test := range nonZeros {
- False(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
- }
-}
-
-func TestNotZero(t *testing.T) {
- mockT := new(testing.T)
-
- for _, test := range zeros {
- False(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
- }
-
- for _, test := range nonZeros {
- True(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
- }
-}
-
-func TestJSONEq_EqualSONString(t *testing.T) {
- mockT := new(testing.T)
- True(t, JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`))
-}
-
-func TestJSONEq_EquivalentButNotEqual(t *testing.T) {
- mockT := new(testing.T)
- True(t, JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`))
-}
-
-func TestJSONEq_HashOfArraysAndHashes(t *testing.T) {
- mockT := new(testing.T)
- True(t, JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}",
- "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}"))
-}
-
-func TestJSONEq_Array(t *testing.T) {
- mockT := new(testing.T)
- True(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`))
-}
-
-func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) {
- mockT := new(testing.T)
- False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`))
-}
-
-func TestJSONEq_HashesNotEquivalent(t *testing.T) {
- mockT := new(testing.T)
- False(t, JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`))
-}
-
-func TestJSONEq_ActualIsNotJSON(t *testing.T) {
- mockT := new(testing.T)
- False(t, JSONEq(mockT, `{"foo": "bar"}`, "Not JSON"))
-}
-
-func TestJSONEq_ExpectedIsNotJSON(t *testing.T) {
- mockT := new(testing.T)
- False(t, JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`))
-}
-
-func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) {
- mockT := new(testing.T)
- False(t, JSONEq(mockT, "Not JSON", "Not JSON"))
-}
-
-func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) {
- mockT := new(testing.T)
- False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`))
-}
-
-func TestDiff(t *testing.T) {
- expected := `
-
-Diff:
---- Expected
-+++ Actual
-@@ -1,3 +1,3 @@
- (struct { foo string }) {
-- foo: (string) (len=5) "hello"
-+ foo: (string) (len=3) "bar"
- }
-`
- actual := diff(
- struct{ foo string }{"hello"},
- struct{ foo string }{"bar"},
- )
- Equal(t, expected, actual)
-
- expected = `
-
-Diff:
---- Expected
-+++ Actual
-@@ -2,5 +2,5 @@
- (int) 1,
-- (int) 2,
- (int) 3,
-- (int) 4
-+ (int) 5,
-+ (int) 7
- }
-`
- actual = diff(
- []int{1, 2, 3, 4},
- []int{1, 3, 5, 7},
- )
- Equal(t, expected, actual)
-
- expected = `
-
-Diff:
---- Expected
-+++ Actual
-@@ -2,4 +2,4 @@
- (int) 1,
-- (int) 2,
-- (int) 3
-+ (int) 3,
-+ (int) 5
- }
-`
- actual = diff(
- []int{1, 2, 3, 4}[0:3],
- []int{1, 3, 5, 7}[0:3],
- )
- Equal(t, expected, actual)
-
- expected = `
-
-Diff:
---- Expected
-+++ Actual
-@@ -1,6 +1,6 @@
- (map[string]int) (len=4) {
-- (string) (len=4) "four": (int) 4,
-+ (string) (len=4) "five": (int) 5,
- (string) (len=3) "one": (int) 1,
-- (string) (len=5) "three": (int) 3,
-- (string) (len=3) "two": (int) 2
-+ (string) (len=5) "seven": (int) 7,
-+ (string) (len=5) "three": (int) 3
- }
-`
-
- actual = diff(
- map[string]int{"one": 1, "two": 2, "three": 3, "four": 4},
- map[string]int{"one": 1, "three": 3, "five": 5, "seven": 7},
- )
- Equal(t, expected, actual)
-}
-
-func TestDiffEmptyCases(t *testing.T) {
- Equal(t, "", diff(nil, nil))
- Equal(t, "", diff(struct{ foo string }{}, nil))
- Equal(t, "", diff(nil, struct{ foo string }{}))
- Equal(t, "", diff(1, 2))
- Equal(t, "", diff(1, 2))
- Equal(t, "", diff([]int{1}, []bool{true}))
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go
deleted file mode 100644
index c9dccc4d6..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
-//
-// Example Usage
-//
-// The following is a complete example using assert in a standard test function:
-// import (
-// "testing"
-// "github.com/stretchr/testify/assert"
-// )
-//
-// func TestSomething(t *testing.T) {
-//
-// var a string = "Hello"
-// var b string = "Hello"
-//
-// assert.Equal(t, a, b, "The two words should be the same.")
-//
-// }
-//
-// if you assert many times, use the format below:
-//
-// import (
-// "testing"
-// "github.com/stretchr/testify/assert"
-// )
-//
-// func TestSomething(t *testing.T) {
-// assert := assert.New(t)
-//
-// var a string = "Hello"
-// var b string = "Hello"
-//
-// assert.Equal(a, b, "The two words should be the same.")
-// }
-//
-// Assertions
-//
-// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
-// All assertion functions take, as the first argument, the `*testing.T` object provided by the
-// testing framework. This allows the assertion funcs to write the failings and other details to
-// the correct place.
-//
-// Every assertion function also takes an optional string message as the final argument,
-// allowing custom error messages to be appended to the message the assertion method outputs.
-package assert
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/errors.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/errors.go
deleted file mode 100644
index ac9dc9d1d..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/errors.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package assert
-
-import (
- "errors"
-)
-
-// AnError is an error instance useful for testing. If the code does not care
-// about error specifics, and only needs to return the error for example, this
-// error should be used to make the test code more readable.
-var AnError = errors.New("assert.AnError general error for testing")
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go
deleted file mode 100644
index cab3aa2ac..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go
+++ /dev/null
@@ -1,284 +0,0 @@
-package assert
-
-import "time"
-
-// Assertions provides assertion methods around the
-// TestingT interface.
-type Assertions struct {
- t TestingT
-}
-
-// New makes a new Assertions object for the specified TestingT.
-func New(t TestingT) *Assertions {
- return &Assertions{
- t: t,
- }
-}
-
-// Fail reports a failure through
-func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
- return Fail(a.t, failureMessage, msgAndArgs...)
-}
-
-// Implements asserts that an object is implemented by the specified interface.
-//
-// assert.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
-func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
- return Implements(a.t, interfaceObject, object, msgAndArgs...)
-}
-
-// IsType asserts that the specified objects are of the same type.
-func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
- return IsType(a.t, expectedType, object, msgAndArgs...)
-}
-
-// Equal asserts that two objects are equal.
-//
-// assert.Equal(123, 123, "123 and 123 should be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Equal(expected, actual interface{}, msgAndArgs ...interface{}) bool {
- return Equal(a.t, expected, actual, msgAndArgs...)
-}
-
-// EqualValues asserts that two objects are equal or convertable to the same types
-// and equal.
-//
-// assert.EqualValues(uint32(123), int32(123), "123 and 123 should be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) EqualValues(expected, actual interface{}, msgAndArgs ...interface{}) bool {
- return EqualValues(a.t, expected, actual, msgAndArgs...)
-}
-
-// Exactly asserts that two objects are equal is value and type.
-//
-// assert.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Exactly(expected, actual interface{}, msgAndArgs ...interface{}) bool {
- return Exactly(a.t, expected, actual, msgAndArgs...)
-}
-
-// NotNil asserts that the specified object is not nil.
-//
-// assert.NotNil(err, "err should be something")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
- return NotNil(a.t, object, msgAndArgs...)
-}
-
-// Nil asserts that the specified object is nil.
-//
-// assert.Nil(err, "err should be nothing")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
- return Nil(a.t, object, msgAndArgs...)
-}
-
-// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or a
-// slice with len == 0.
-//
-// assert.Empty(obj)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
- return Empty(a.t, object, msgAndArgs...)
-}
-
-// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or a
-// slice with len == 0.
-//
-// if assert.NotEmpty(obj) {
-// assert.Equal("two", obj[1])
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
- return NotEmpty(a.t, object, msgAndArgs...)
-}
-
-// Len asserts that the specified object has specific length.
-// Len also fails if the object has a type that len() not accept.
-//
-// assert.Len(mySlice, 3, "The size of slice is not 3")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
- return Len(a.t, object, length, msgAndArgs...)
-}
-
-// True asserts that the specified value is true.
-//
-// assert.True(myBool, "myBool should be true")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
- return True(a.t, value, msgAndArgs...)
-}
-
-// False asserts that the specified value is true.
-//
-// assert.False(myBool, "myBool should be false")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
- return False(a.t, value, msgAndArgs...)
-}
-
-// NotEqual asserts that the specified values are NOT equal.
-//
-// assert.NotEqual(obj1, obj2, "two objects shouldn't be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotEqual(expected, actual interface{}, msgAndArgs ...interface{}) bool {
- return NotEqual(a.t, expected, actual, msgAndArgs...)
-}
-
-// Contains asserts that the specified string contains the specified substring.
-//
-// assert.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Contains(s, contains interface{}, msgAndArgs ...interface{}) bool {
- return Contains(a.t, s, contains, msgAndArgs...)
-}
-
-// NotContains asserts that the specified string does NOT contain the specified substring.
-//
-// assert.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotContains(s, contains interface{}, msgAndArgs ...interface{}) bool {
- return NotContains(a.t, s, contains, msgAndArgs...)
-}
-
-// Condition uses a Comparison to assert a complex condition.
-func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
- return Condition(a.t, comp, msgAndArgs...)
-}
-
-// Panics asserts that the code inside the specified PanicTestFunc panics.
-//
-// assert.Panics(func(){
-// GoCrazy()
-// }, "Calling GoCrazy() should panic")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
- return Panics(a.t, f, msgAndArgs...)
-}
-
-// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
-//
-// assert.NotPanics(func(){
-// RemainCalm()
-// }, "Calling RemainCalm() should NOT panic")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
- return NotPanics(a.t, f, msgAndArgs...)
-}
-
-// WithinDuration asserts that the two times are within duration delta of each other.
-//
-// assert.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
- return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
-}
-
-// InDelta asserts that the two numerals are within delta of each other.
-//
-// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
- return InDelta(a.t, expected, actual, delta, msgAndArgs...)
-}
-
-// InEpsilon asserts that expected and actual have a relative error less than epsilon
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) InEpsilon(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
- return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
-}
-
-// NoError asserts that a function returned no error (i.e. `nil`).
-//
-// actualObj, err := SomeFunction()
-// if assert.NoError(err) {
-// assert.Equal(actualObj, expectedObj)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NoError(theError error, msgAndArgs ...interface{}) bool {
- return NoError(a.t, theError, msgAndArgs...)
-}
-
-// Error asserts that a function returned an error (i.e. not `nil`).
-//
-// actualObj, err := SomeFunction()
-// if assert.Error(err, "An error was expected") {
-// assert.Equal(err, expectedError)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Error(theError error, msgAndArgs ...interface{}) bool {
- return Error(a.t, theError, msgAndArgs...)
-}
-
-// EqualError asserts that a function returned an error (i.e. not `nil`)
-// and that it is equal to the provided error.
-//
-// actualObj, err := SomeFunction()
-// if assert.Error(err, "An error was expected") {
-// assert.Equal(err, expectedError)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
- return EqualError(a.t, theError, errString, msgAndArgs...)
-}
-
-// Regexp asserts that a specified regexp matches a string.
-//
-// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
-// assert.Regexp(t, "start...$", "it's not starting")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
- return Regexp(a.t, rx, str, msgAndArgs...)
-}
-
-// NotRegexp asserts that a specified regexp does not match a string.
-//
-// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
-// assert.NotRegexp(t, "^start", "it's not starting")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
- return NotRegexp(a.t, rx, str, msgAndArgs...)
-}
-
-// Zero asserts that i is the zero value for its type and returns the truth.
-func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
- return Zero(a.t, i, msgAndArgs...)
-}
-
-// NotZero asserts that i is not the zero value for its type and returns the truth.
-func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
- return NotZero(a.t, i, msgAndArgs...)
-}
-
-// JSONEq asserts that two JSON strings are equivalent.
-//
-// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
- return JSONEq(a.t, expected, actual, msgAndArgs...)
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go
deleted file mode 100644
index 22e1df1d9..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go
+++ /dev/null
@@ -1,611 +0,0 @@
-package assert
-
-import (
- "errors"
- "regexp"
- "testing"
- "time"
-)
-
-func TestImplementsWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) {
- t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface")
- }
- if assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) {
- t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface")
- }
-}
-
-func TestIsTypeWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) {
- t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject")
- }
- if assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) {
- t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject")
- }
-
-}
-
-func TestEqualWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.Equal("Hello World", "Hello World") {
- t.Error("Equal should return true")
- }
- if !assert.Equal(123, 123) {
- t.Error("Equal should return true")
- }
- if !assert.Equal(123.5, 123.5) {
- t.Error("Equal should return true")
- }
- if !assert.Equal([]byte("Hello World"), []byte("Hello World")) {
- t.Error("Equal should return true")
- }
- if !assert.Equal(nil, nil) {
- t.Error("Equal should return true")
- }
-}
-
-func TestEqualValuesWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.EqualValues(uint32(10), int32(10)) {
- t.Error("EqualValues should return true")
- }
-}
-
-func TestNotNilWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.NotNil(new(AssertionTesterConformingObject)) {
- t.Error("NotNil should return true: object is not nil")
- }
- if assert.NotNil(nil) {
- t.Error("NotNil should return false: object is nil")
- }
-
-}
-
-func TestNilWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.Nil(nil) {
- t.Error("Nil should return true: object is nil")
- }
- if assert.Nil(new(AssertionTesterConformingObject)) {
- t.Error("Nil should return false: object is not nil")
- }
-
-}
-
-func TestTrueWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.True(true) {
- t.Error("True should return true")
- }
- if assert.True(false) {
- t.Error("True should return false")
- }
-
-}
-
-func TestFalseWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.False(false) {
- t.Error("False should return true")
- }
- if assert.False(true) {
- t.Error("False should return false")
- }
-
-}
-
-func TestExactlyWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- a := float32(1)
- b := float64(1)
- c := float32(1)
- d := float32(2)
-
- if assert.Exactly(a, b) {
- t.Error("Exactly should return false")
- }
- if assert.Exactly(a, d) {
- t.Error("Exactly should return false")
- }
- if !assert.Exactly(a, c) {
- t.Error("Exactly should return true")
- }
-
- if assert.Exactly(nil, a) {
- t.Error("Exactly should return false")
- }
- if assert.Exactly(a, nil) {
- t.Error("Exactly should return false")
- }
-
-}
-
-func TestNotEqualWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
-
- if !assert.NotEqual("Hello World", "Hello World!") {
- t.Error("NotEqual should return true")
- }
- if !assert.NotEqual(123, 1234) {
- t.Error("NotEqual should return true")
- }
- if !assert.NotEqual(123.5, 123.55) {
- t.Error("NotEqual should return true")
- }
- if !assert.NotEqual([]byte("Hello World"), []byte("Hello World!")) {
- t.Error("NotEqual should return true")
- }
- if !assert.NotEqual(nil, new(AssertionTesterConformingObject)) {
- t.Error("NotEqual should return true")
- }
-}
-
-func TestContainsWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
- list := []string{"Foo", "Bar"}
-
- if !assert.Contains("Hello World", "Hello") {
- t.Error("Contains should return true: \"Hello World\" contains \"Hello\"")
- }
- if assert.Contains("Hello World", "Salut") {
- t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"")
- }
-
- if !assert.Contains(list, "Foo") {
- t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
- }
- if assert.Contains(list, "Salut") {
- t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"")
- }
-
-}
-
-func TestNotContainsWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
- list := []string{"Foo", "Bar"}
-
- if !assert.NotContains("Hello World", "Hello!") {
- t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"")
- }
- if assert.NotContains("Hello World", "Hello") {
- t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"")
- }
-
- if !assert.NotContains(list, "Foo!") {
- t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"")
- }
- if assert.NotContains(list, "Foo") {
- t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
- }
-
-}
-
-func TestConditionWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
-
- if !assert.Condition(func() bool { return true }, "Truth") {
- t.Error("Condition should return true")
- }
-
- if assert.Condition(func() bool { return false }, "Lie") {
- t.Error("Condition should return false")
- }
-
-}
-
-func TestDidPanicWrapper(t *testing.T) {
-
- if funcDidPanic, _ := didPanic(func() {
- panic("Panic!")
- }); !funcDidPanic {
- t.Error("didPanic should return true")
- }
-
- if funcDidPanic, _ := didPanic(func() {
- }); funcDidPanic {
- t.Error("didPanic should return false")
- }
-
-}
-
-func TestPanicsWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
-
- if !assert.Panics(func() {
- panic("Panic!")
- }) {
- t.Error("Panics should return true")
- }
-
- if assert.Panics(func() {
- }) {
- t.Error("Panics should return false")
- }
-
-}
-
-func TestNotPanicsWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
-
- if !assert.NotPanics(func() {
- }) {
- t.Error("NotPanics should return true")
- }
-
- if assert.NotPanics(func() {
- panic("Panic!")
- }) {
- t.Error("NotPanics should return false")
- }
-
-}
-
-func TestNoErrorWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- // start with a nil error
- var err error
-
- assert.True(mockAssert.NoError(err), "NoError should return True for nil arg")
-
- // now set an error
- err = errors.New("Some error")
-
- assert.False(mockAssert.NoError(err), "NoError with error should return False")
-
-}
-
-func TestErrorWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- // start with a nil error
- var err error
-
- assert.False(mockAssert.Error(err), "Error should return False for nil arg")
-
- // now set an error
- err = errors.New("Some error")
-
- assert.True(mockAssert.Error(err), "Error with error should return True")
-
-}
-
-func TestEqualErrorWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- // start with a nil error
- var err error
- assert.False(mockAssert.EqualError(err, ""),
- "EqualError should return false for nil arg")
-
- // now set an error
- err = errors.New("some error")
- assert.False(mockAssert.EqualError(err, "Not some error"),
- "EqualError should return false for different error string")
- assert.True(mockAssert.EqualError(err, "some error"),
- "EqualError should return true")
-}
-
-func TestEmptyWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- assert.True(mockAssert.Empty(""), "Empty string is empty")
- assert.True(mockAssert.Empty(nil), "Nil is empty")
- assert.True(mockAssert.Empty([]string{}), "Empty string array is empty")
- assert.True(mockAssert.Empty(0), "Zero int value is empty")
- assert.True(mockAssert.Empty(false), "False value is empty")
-
- assert.False(mockAssert.Empty("something"), "Non Empty string is not empty")
- assert.False(mockAssert.Empty(errors.New("something")), "Non nil object is not empty")
- assert.False(mockAssert.Empty([]string{"something"}), "Non empty string array is not empty")
- assert.False(mockAssert.Empty(1), "Non-zero int value is not empty")
- assert.False(mockAssert.Empty(true), "True value is not empty")
-
-}
-
-func TestNotEmptyWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- assert.False(mockAssert.NotEmpty(""), "Empty string is empty")
- assert.False(mockAssert.NotEmpty(nil), "Nil is empty")
- assert.False(mockAssert.NotEmpty([]string{}), "Empty string array is empty")
- assert.False(mockAssert.NotEmpty(0), "Zero int value is empty")
- assert.False(mockAssert.NotEmpty(false), "False value is empty")
-
- assert.True(mockAssert.NotEmpty("something"), "Non Empty string is not empty")
- assert.True(mockAssert.NotEmpty(errors.New("something")), "Non nil object is not empty")
- assert.True(mockAssert.NotEmpty([]string{"something"}), "Non empty string array is not empty")
- assert.True(mockAssert.NotEmpty(1), "Non-zero int value is not empty")
- assert.True(mockAssert.NotEmpty(true), "True value is not empty")
-
-}
-
-func TestLenWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- assert.False(mockAssert.Len(nil, 0), "nil does not have length")
- assert.False(mockAssert.Len(0, 0), "int does not have length")
- assert.False(mockAssert.Len(true, 0), "true does not have length")
- assert.False(mockAssert.Len(false, 0), "false does not have length")
- assert.False(mockAssert.Len('A', 0), "Rune does not have length")
- assert.False(mockAssert.Len(struct{}{}, 0), "Struct does not have length")
-
- ch := make(chan int, 5)
- ch <- 1
- ch <- 2
- ch <- 3
-
- cases := []struct {
- v interface{}
- l int
- }{
- {[]int{1, 2, 3}, 3},
- {[...]int{1, 2, 3}, 3},
- {"ABC", 3},
- {map[int]int{1: 2, 2: 4, 3: 6}, 3},
- {ch, 3},
-
- {[]int{}, 0},
- {map[int]int{}, 0},
- {make(chan int), 0},
-
- {[]int(nil), 0},
- {map[int]int(nil), 0},
- {(chan int)(nil), 0},
- }
-
- for _, c := range cases {
- assert.True(mockAssert.Len(c.v, c.l), "%#v have %d items", c.v, c.l)
- }
-}
-
-func TestWithinDurationWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
- a := time.Now()
- b := a.Add(10 * time.Second)
-
- assert.True(mockAssert.WithinDuration(a, b, 10*time.Second), "A 10s difference is within a 10s time difference")
- assert.True(mockAssert.WithinDuration(b, a, 10*time.Second), "A 10s difference is within a 10s time difference")
-
- assert.False(mockAssert.WithinDuration(a, b, 9*time.Second), "A 10s difference is not within a 9s time difference")
- assert.False(mockAssert.WithinDuration(b, a, 9*time.Second), "A 10s difference is not within a 9s time difference")
-
- assert.False(mockAssert.WithinDuration(a, b, -9*time.Second), "A 10s difference is not within a 9s time difference")
- assert.False(mockAssert.WithinDuration(b, a, -9*time.Second), "A 10s difference is not within a 9s time difference")
-
- assert.False(mockAssert.WithinDuration(a, b, -11*time.Second), "A 10s difference is not within a 9s time difference")
- assert.False(mockAssert.WithinDuration(b, a, -11*time.Second), "A 10s difference is not within a 9s time difference")
-}
-
-func TestInDeltaWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- True(t, assert.InDelta(1.001, 1, 0.01), "|1.001 - 1| <= 0.01")
- True(t, assert.InDelta(1, 1.001, 0.01), "|1 - 1.001| <= 0.01")
- True(t, assert.InDelta(1, 2, 1), "|1 - 2| <= 1")
- False(t, assert.InDelta(1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail")
- False(t, assert.InDelta(2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail")
- False(t, assert.InDelta("", nil, 1), "Expected non numerals to fail")
-
- cases := []struct {
- a, b interface{}
- delta float64
- }{
- {uint8(2), uint8(1), 1},
- {uint16(2), uint16(1), 1},
- {uint32(2), uint32(1), 1},
- {uint64(2), uint64(1), 1},
-
- {int(2), int(1), 1},
- {int8(2), int8(1), 1},
- {int16(2), int16(1), 1},
- {int32(2), int32(1), 1},
- {int64(2), int64(1), 1},
-
- {float32(2), float32(1), 1},
- {float64(2), float64(1), 1},
- }
-
- for _, tc := range cases {
- True(t, assert.InDelta(tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta)
- }
-}
-
-func TestInEpsilonWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- cases := []struct {
- a, b interface{}
- epsilon float64
- }{
- {uint8(2), uint16(2), .001},
- {2.1, 2.2, 0.1},
- {2.2, 2.1, 0.1},
- {-2.1, -2.2, 0.1},
- {-2.2, -2.1, 0.1},
- {uint64(100), uint8(101), 0.01},
- {0.1, -0.1, 2},
- }
-
- for _, tc := range cases {
- True(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
- }
-
- cases = []struct {
- a, b interface{}
- epsilon float64
- }{
- {uint8(2), int16(-2), .001},
- {uint64(100), uint8(102), 0.01},
- {2.1, 2.2, 0.001},
- {2.2, 2.1, 0.001},
- {2.1, -2.2, 1},
- {2.1, "bla-bla", 0},
- {0.1, -0.1, 1.99},
- }
-
- for _, tc := range cases {
- False(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
- }
-}
-
-func TestRegexpWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
-
- cases := []struct {
- rx, str string
- }{
- {"^start", "start of the line"},
- {"end$", "in the end"},
- {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"},
- }
-
- for _, tc := range cases {
- True(t, assert.Regexp(tc.rx, tc.str))
- True(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str))
- False(t, assert.NotRegexp(tc.rx, tc.str))
- False(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
- }
-
- cases = []struct {
- rx, str string
- }{
- {"^asdfastart", "Not the start of the line"},
- {"end$", "in the end."},
- {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"},
- }
-
- for _, tc := range cases {
- False(t, assert.Regexp(tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str)
- False(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str))
- True(t, assert.NotRegexp(tc.rx, tc.str))
- True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
- }
-}
-
-func TestZeroWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- for _, test := range zeros {
- assert.True(mockAssert.Zero(test), "Zero should return true for %v", test)
- }
-
- for _, test := range nonZeros {
- assert.False(mockAssert.Zero(test), "Zero should return false for %v", test)
- }
-}
-
-func TestNotZeroWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- for _, test := range zeros {
- assert.False(mockAssert.NotZero(test), "Zero should return true for %v", test)
- }
-
- for _, test := range nonZeros {
- assert.True(mockAssert.NotZero(test), "Zero should return false for %v", test)
- }
-}
-
-func TestJSONEqWrapper_EqualSONString(t *testing.T) {
- assert := New(new(testing.T))
- if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) {
- t.Error("JSONEq should return true")
- }
-
-}
-
-func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) {
- assert := New(new(testing.T))
- if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) {
- t.Error("JSONEq should return true")
- }
-
-}
-
-func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) {
- assert := New(new(testing.T))
- if !assert.JSONEq("{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}",
- "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") {
- t.Error("JSONEq should return true")
- }
-}
-
-func TestJSONEqWrapper_Array(t *testing.T) {
- assert := New(new(testing.T))
- if !assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) {
- t.Error("JSONEq should return true")
- }
-
-}
-
-func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) {
- assert := New(new(testing.T))
- if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) {
- t.Error("JSONEq should return false")
- }
-}
-
-func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) {
- assert := New(new(testing.T))
- if assert.JSONEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) {
- t.Error("JSONEq should return false")
- }
-}
-
-func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) {
- assert := New(new(testing.T))
- if assert.JSONEq(`{"foo": "bar"}`, "Not JSON") {
- t.Error("JSONEq should return false")
- }
-}
-
-func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) {
- assert := New(new(testing.T))
- if assert.JSONEq("Not JSON", `{"foo": "bar", "hello": "world"}`) {
- t.Error("JSONEq should return false")
- }
-}
-
-func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) {
- assert := New(new(testing.T))
- if assert.JSONEq("Not JSON", "Not JSON") {
- t.Error("JSONEq should return false")
- }
-}
-
-func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) {
- assert := New(new(testing.T))
- if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) {
- t.Error("JSONEq should return false")
- }
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go
deleted file mode 100644
index 437a86ce4..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go
+++ /dev/null
@@ -1,157 +0,0 @@
-package assert
-
-import (
- "fmt"
- "net/http"
- "net/http/httptest"
- "net/url"
- "strings"
-)
-
-// httpCode is a helper that returns HTTP code of the response. It returns -1
-// if building a new request fails.
-func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int {
- w := httptest.NewRecorder()
- req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
- if err != nil {
- return -1
- }
- handler(w, req)
- return w.Code
-}
-
-// HTTPSuccess asserts that a specified handler returns a success status code.
-//
-// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
- code := httpCode(handler, method, url, values)
- if code == -1 {
- return false
- }
- return code >= http.StatusOK && code <= http.StatusPartialContent
-}
-
-// HTTPRedirect asserts that a specified handler returns a redirect status code.
-//
-// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
-func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
- code := httpCode(handler, method, url, values)
- if code == -1 {
- return false
- }
- return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
-}
-
-// HTTPError asserts that a specified handler returns an error status code.
-//
-// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
-func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
- code := httpCode(handler, method, url, values)
- if code == -1 {
- return false
- }
- return code >= http.StatusBadRequest
-}
-
-// HTTPBody is a helper that returns HTTP body of the response. It returns
-// empty string if building a new request fails.
-func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
- w := httptest.NewRecorder()
- req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
- if err != nil {
- return ""
- }
- handler(w, req)
- return w.Body.String()
-}
-
-// HTTPBodyContains asserts that a specified handler returns a
-// body that contains a string.
-//
-// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
- body := HTTPBody(handler, method, url, values)
-
- contains := strings.Contains(body, fmt.Sprint(str))
- if !contains {
- Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
- }
-
- return contains
-}
-
-// HTTPBodyNotContains asserts that a specified handler returns a
-// body that does not contain a string.
-//
-// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
- body := HTTPBody(handler, method, url, values)
-
- contains := strings.Contains(body, fmt.Sprint(str))
- if contains {
- Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)
- }
-
- return !contains
-}
-
-//
-// Assertions Wrappers
-//
-
-// HTTPSuccess asserts that a specified handler returns a success status code.
-//
-// assert.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method, url string, values url.Values) bool {
- return HTTPSuccess(a.t, handler, method, url, values)
-}
-
-// HTTPRedirect asserts that a specified handler returns a redirect status code.
-//
-// assert.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method, url string, values url.Values) bool {
- return HTTPRedirect(a.t, handler, method, url, values)
-}
-
-// HTTPError asserts that a specified handler returns an error status code.
-//
-// assert.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) HTTPError(handler http.HandlerFunc, method, url string, values url.Values) bool {
- return HTTPError(a.t, handler, method, url, values)
-}
-
-// HTTPBodyContains asserts that a specified handler returns a
-// body that contains a string.
-//
-// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
- return HTTPBodyContains(a.t, handler, method, url, values, str)
-}
-
-// HTTPBodyNotContains asserts that a specified handler returns a
-// body that does not contain a string.
-//
-// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
- return HTTPBodyNotContains(a.t, handler, method, url, values, str)
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go
deleted file mode 100644
index 684c2d5d1..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package assert
-
-import (
- "fmt"
- "net/http"
- "net/url"
- "testing"
-)
-
-func httpOK(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusOK)
-}
-
-func httpRedirect(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusTemporaryRedirect)
-}
-
-func httpError(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusInternalServerError)
-}
-
-func TestHTTPStatuses(t *testing.T) {
- assert := New(t)
- mockT := new(testing.T)
-
- assert.Equal(HTTPSuccess(mockT, httpOK, "GET", "/", nil), true)
- assert.Equal(HTTPSuccess(mockT, httpRedirect, "GET", "/", nil), false)
- assert.Equal(HTTPSuccess(mockT, httpError, "GET", "/", nil), false)
-
- assert.Equal(HTTPRedirect(mockT, httpOK, "GET", "/", nil), false)
- assert.Equal(HTTPRedirect(mockT, httpRedirect, "GET", "/", nil), true)
- assert.Equal(HTTPRedirect(mockT, httpError, "GET", "/", nil), false)
-
- assert.Equal(HTTPError(mockT, httpOK, "GET", "/", nil), false)
- assert.Equal(HTTPError(mockT, httpRedirect, "GET", "/", nil), false)
- assert.Equal(HTTPError(mockT, httpError, "GET", "/", nil), true)
-}
-
-func TestHTTPStatusesWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- assert.Equal(mockAssert.HTTPSuccess(httpOK, "GET", "/", nil), true)
- assert.Equal(mockAssert.HTTPSuccess(httpRedirect, "GET", "/", nil), false)
- assert.Equal(mockAssert.HTTPSuccess(httpError, "GET", "/", nil), false)
-
- assert.Equal(mockAssert.HTTPRedirect(httpOK, "GET", "/", nil), false)
- assert.Equal(mockAssert.HTTPRedirect(httpRedirect, "GET", "/", nil), true)
- assert.Equal(mockAssert.HTTPRedirect(httpError, "GET", "/", nil), false)
-
- assert.Equal(mockAssert.HTTPError(httpOK, "GET", "/", nil), false)
- assert.Equal(mockAssert.HTTPError(httpRedirect, "GET", "/", nil), false)
- assert.Equal(mockAssert.HTTPError(httpError, "GET", "/", nil), true)
-}
-
-func httpHelloName(w http.ResponseWriter, r *http.Request) {
- name := r.FormValue("name")
- w.Write([]byte(fmt.Sprintf("Hello, %s!", name)))
-}
-
-func TestHttpBody(t *testing.T) {
- assert := New(t)
- mockT := new(testing.T)
-
- assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
- assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
- assert.False(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
-
- assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
- assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
- assert.True(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
-}
-
-func TestHttpBodyWrappers(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
- assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
- assert.False(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
-
- assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
- assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
- assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
-
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go
deleted file mode 100644
index dd385074b..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Provides a system by which it is possible to mock your objects and verify calls are happening as expected.
-//
-// Example Usage
-//
-// The mock package provides an object, Mock, that tracks activity on another object. It is usually
-// embedded into a test object as shown below:
-//
-// type MyTestObject struct {
-// // add a Mock object instance
-// mock.Mock
-//
-// // other fields go here as normal
-// }
-//
-// When implementing the methods of an interface, you wire your functions up
-// to call the Mock.Called(args...) method, and return the appropriate values.
-//
-// For example, to mock a method that saves the name and age of a person and returns
-// the year of their birth or an error, you might write this:
-//
-// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) {
-// args := o.Called(firstname, lastname, age)
-// return args.Int(0), args.Error(1)
-// }
-//
-// The Int, Error and Bool methods are examples of strongly typed getters that take the argument
-// index position. Given this argument list:
-//
-// (12, true, "Something")
-//
-// You could read them out strongly typed like this:
-//
-// args.Int(0)
-// args.Bool(1)
-// args.String(2)
-//
-// For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion:
-//
-// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine)
-//
-// This may cause a panic if the object you are getting is nil (the type assertion will fail), in those
-// cases you should check for nil first.
-package mock
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go
deleted file mode 100644
index 111a281b4..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go
+++ /dev/null
@@ -1,624 +0,0 @@
-package mock
-
-import (
- "fmt"
- "reflect"
- "regexp"
- "runtime"
- "strings"
- "sync"
- "time"
-
- "github.com/stretchr/objx"
- "github.com/stretchr/testify/assert"
-)
-
-// TestingT is an interface wrapper around *testing.T
-type TestingT interface {
- Logf(format string, args ...interface{})
- Errorf(format string, args ...interface{})
-}
-
-/*
- Call
-*/
-
-// Call represents a method call and is used for setting expectations,
-// as well as recording activity.
-type Call struct {
- Parent *Mock
-
- // The name of the method that was or will be called.
- Method string
-
- // Holds the arguments of the method.
- Arguments Arguments
-
- // Holds the arguments that should be returned when
- // this method is called.
- ReturnArguments Arguments
-
- // The number of times to return the return arguments when setting
- // expectations. 0 means to always return the value.
- Repeatability int
-
- // Holds a channel that will be used to block the Return until it either
- // recieves a message or is closed. nil means it returns immediately.
- WaitFor <-chan time.Time
-
- // Holds a handler used to manipulate arguments content that are passed by
- // reference. It's useful when mocking methods such as unmarshalers or
- // decoders.
- RunFn func(Arguments)
-}
-
-func newCall(parent *Mock, methodName string, methodArguments ...interface{}) *Call {
- return &Call{
- Parent: parent,
- Method: methodName,
- Arguments: methodArguments,
- ReturnArguments: make([]interface{}, 0),
- Repeatability: 0,
- WaitFor: nil,
- RunFn: nil,
- }
-}
-
-func (self *Call) lock() {
- self.Parent.mutex.Lock()
-}
-
-func (self *Call) unlock() {
- self.Parent.mutex.Unlock()
-}
-
-func (self *Call) Return(returnArguments ...interface{}) *Call {
- self.lock()
- defer self.unlock()
-
- self.ReturnArguments = returnArguments
-
- return self
-}
-
-// Once indicates that that the mock should only return the value once.
-//
-// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once()
-func (self *Call) Once() *Call {
- return self.Times(1)
-}
-
-// Twice indicates that that the mock should only return the value twice.
-//
-// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice()
-func (self *Call) Twice() *Call {
- return self.Times(2)
-}
-
-// Times indicates that that the mock should only return the indicated number
-// of times.
-//
-// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
-func (self *Call) Times(i int) *Call {
- self.lock()
- defer self.unlock()
- self.Repeatability = i
- return self
-}
-
-// WaitUntil sets the channel that will block the mock's return until its closed
-// or a message is received.
-//
-// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second))
-func (self *Call) WaitUntil(w <-chan time.Time) *Call {
- self.lock()
- defer self.unlock()
- self.WaitFor = w
- return self
-}
-
-// After sets how long to block until the call returns
-//
-// Mock.On("MyMethod", arg1, arg2).After(time.Second)
-func (self *Call) After(d time.Duration) *Call {
- return self.WaitUntil(time.After(d))
-}
-
-// Run sets a handler to be called before returning. It can be used when
-// mocking a method such as unmarshalers that takes a pointer to a struct and
-// sets properties in such struct
-//
-// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(function(args Arguments) {
-// arg := args.Get(0).(*map[string]interface{})
-// arg["foo"] = "bar"
-// })
-func (self *Call) Run(fn func(Arguments)) *Call {
- self.lock()
- defer self.unlock()
- self.RunFn = fn
- return self
-}
-
-// On chains a new expectation description onto the mocked interface. This
-// allows syntax like.
-//
-// Mock.
-// On("MyMethod", 1).Return(nil).
-// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error"))
-func (self *Call) On(methodName string, arguments ...interface{}) *Call {
- return self.Parent.On(methodName, arguments...)
-}
-
-// Mock is the workhorse used to track activity on another object.
-// For an example of its usage, refer to the "Example Usage" section at the top
-// of this document.
-type Mock struct {
- // Represents the calls that are expected of
- // an object.
- ExpectedCalls []*Call
-
- // Holds the calls that were made to this mocked object.
- Calls []Call
-
- // TestData holds any data that might be useful for testing. Testify ignores
- // this data completely allowing you to do whatever you like with it.
- testData objx.Map
-
- mutex sync.Mutex
-}
-
-// TestData holds any data that might be useful for testing. Testify ignores
-// this data completely allowing you to do whatever you like with it.
-func (m *Mock) TestData() objx.Map {
-
- if m.testData == nil {
- m.testData = make(objx.Map)
- }
-
- return m.testData
-}
-
-/*
- Setting expectations
-*/
-
-// On starts a description of an expectation of the specified method
-// being called.
-//
-// Mock.On("MyMethod", arg1, arg2)
-func (self *Mock) On(methodName string, arguments ...interface{}) *Call {
- for _, arg := range arguments {
- if v := reflect.ValueOf(arg); v.Kind() == reflect.Func {
- panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg))
- }
- }
-
- self.mutex.Lock()
- defer self.mutex.Unlock()
- c := newCall(self, methodName, arguments...)
- self.ExpectedCalls = append(self.ExpectedCalls, c)
- return c
-}
-
-// /*
-// Recording and responding to activity
-// */
-
-func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) {
- m.mutex.Lock()
- defer m.mutex.Unlock()
- for i, call := range m.ExpectedCalls {
- if call.Method == method && call.Repeatability > -1 {
-
- _, diffCount := call.Arguments.Diff(arguments)
- if diffCount == 0 {
- return i, call
- }
-
- }
- }
- return -1, nil
-}
-
-func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) {
- diffCount := 0
- var closestCall *Call = nil
-
- for _, call := range m.expectedCalls() {
- if call.Method == method {
-
- _, tempDiffCount := call.Arguments.Diff(arguments)
- if tempDiffCount < diffCount || diffCount == 0 {
- diffCount = tempDiffCount
- closestCall = call
- }
-
- }
- }
-
- if closestCall == nil {
- return false, nil
- }
-
- return true, closestCall
-}
-
-func callString(method string, arguments Arguments, includeArgumentValues bool) string {
-
- var argValsString string = ""
- if includeArgumentValues {
- var argVals []string
- for argIndex, arg := range arguments {
- argVals = append(argVals, fmt.Sprintf("%d: %#v", argIndex, arg))
- }
- argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t"))
- }
-
- return fmt.Sprintf("%s(%s)%s", method, arguments.String(), argValsString)
-}
-
-// Called tells the mock object that a method has been called, and gets an array
-// of arguments to return. Panics if the call is unexpected (i.e. not preceeded by
-// appropriate .On .Return() calls)
-// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
-func (m *Mock) Called(arguments ...interface{}) Arguments {
- // get the calling function's name
- pc, _, _, ok := runtime.Caller(1)
- if !ok {
- panic("Couldn't get the caller information")
- }
- functionPath := runtime.FuncForPC(pc).Name()
- //Next four lines are required to use GCCGO function naming conventions.
- //For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock
- //uses inteface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree
- //With GCCGO we need to remove interface information starting from pN<dd>.
- re := regexp.MustCompile("\\.pN\\d+_")
- if re.MatchString(functionPath) {
- functionPath = re.Split(functionPath, -1)[0]
- }
- parts := strings.Split(functionPath, ".")
- functionName := parts[len(parts)-1]
-
- found, call := m.findExpectedCall(functionName, arguments...)
-
- if found < 0 {
- // we have to fail here - because we don't know what to do
- // as the return arguments. This is because:
- //
- // a) this is a totally unexpected call to this method,
- // b) the arguments are not what was expected, or
- // c) the developer has forgotten to add an accompanying On...Return pair.
-
- closestFound, closestCall := m.findClosestCall(functionName, arguments...)
-
- if closestFound {
- panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n", callString(functionName, arguments, true), callString(functionName, closestCall.Arguments, true)))
- } else {
- panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", functionName, functionName, callString(functionName, arguments, true), assert.CallerInfo()))
- }
- } else {
- m.mutex.Lock()
- switch {
- case call.Repeatability == 1:
- call.Repeatability = -1
-
- case call.Repeatability > 1:
- call.Repeatability -= 1
- }
- m.mutex.Unlock()
- }
-
- // add the call
- m.mutex.Lock()
- m.Calls = append(m.Calls, *newCall(m, functionName, arguments...))
- m.mutex.Unlock()
-
- // block if specified
- if call.WaitFor != nil {
- <-call.WaitFor
- }
-
- if call.RunFn != nil {
- call.RunFn(arguments)
- }
-
- return call.ReturnArguments
-}
-
-/*
- Assertions
-*/
-
-// AssertExpectationsForObjects asserts that everything specified with On and Return
-// of the specified objects was in fact called as expected.
-//
-// Calls may have occurred in any order.
-func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
- var success bool = true
- for _, obj := range testObjects {
- mockObj := obj.(Mock)
- success = success && mockObj.AssertExpectations(t)
- }
- return success
-}
-
-// AssertExpectations asserts that everything specified with On and Return was
-// in fact called as expected. Calls may have occurred in any order.
-func (m *Mock) AssertExpectations(t TestingT) bool {
- var somethingMissing bool = false
- var failedExpectations int = 0
-
- // iterate through each expectation
- expectedCalls := m.expectedCalls()
- for _, expectedCall := range expectedCalls {
- if !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) {
- somethingMissing = true
- failedExpectations++
- t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
- } else {
- m.mutex.Lock()
- if expectedCall.Repeatability > 0 {
- somethingMissing = true
- failedExpectations++
- } else {
- t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
- }
- m.mutex.Unlock()
- }
- }
-
- if somethingMissing {
- t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo())
- }
-
- return !somethingMissing
-}
-
-// AssertNumberOfCalls asserts that the method was called expectedCalls times.
-func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
- var actualCalls int = 0
- for _, call := range m.calls() {
- if call.Method == methodName {
- actualCalls++
- }
- }
- return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls))
-}
-
-// AssertCalled asserts that the method was called.
-func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool {
- if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) {
- t.Logf("%v", m.expectedCalls())
- return false
- }
- return true
-}
-
-// AssertNotCalled asserts that the method was not called.
-func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool {
- if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) {
- t.Logf("%v", m.expectedCalls())
- return false
- }
- return true
-}
-
-func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool {
- for _, call := range m.calls() {
- if call.Method == methodName {
-
- _, differences := Arguments(expected).Diff(call.Arguments)
-
- if differences == 0 {
- // found the expected call
- return true
- }
-
- }
- }
- // we didn't find the expected call
- return false
-}
-
-func (m *Mock) expectedCalls() []*Call {
- m.mutex.Lock()
- defer m.mutex.Unlock()
- return append([]*Call{}, m.ExpectedCalls...)
-}
-
-func (m *Mock) calls() []Call {
- m.mutex.Lock()
- defer m.mutex.Unlock()
- return append([]Call{}, m.Calls...)
-}
-
-/*
- Arguments
-*/
-
-// Arguments holds an array of method arguments or return values.
-type Arguments []interface{}
-
-const (
- // The "any" argument. Used in Diff and Assert when
- // the argument being tested shouldn't be taken into consideration.
- Anything string = "mock.Anything"
-)
-
-// AnythingOfTypeArgument is a string that contains the type of an argument
-// for use when type checking. Used in Diff and Assert.
-type AnythingOfTypeArgument string
-
-// AnythingOfType returns an AnythingOfTypeArgument object containing the
-// name of the type to check for. Used in Diff and Assert.
-//
-// For example:
-// Assert(t, AnythingOfType("string"), AnythingOfType("int"))
-func AnythingOfType(t string) AnythingOfTypeArgument {
- return AnythingOfTypeArgument(t)
-}
-
-// Get Returns the argument at the specified index.
-func (args Arguments) Get(index int) interface{} {
- if index+1 > len(args) {
- panic(fmt.Sprintf("assert: arguments: Cannot call Get(%d) because there are %d argument(s).", index, len(args)))
- }
- return args[index]
-}
-
-// Is gets whether the objects match the arguments specified.
-func (args Arguments) Is(objects ...interface{}) bool {
- for i, obj := range args {
- if obj != objects[i] {
- return false
- }
- }
- return true
-}
-
-// Diff gets a string describing the differences between the arguments
-// and the specified objects.
-//
-// Returns the diff string and number of differences found.
-func (args Arguments) Diff(objects []interface{}) (string, int) {
-
- var output string = "\n"
- var differences int
-
- var maxArgCount int = len(args)
- if len(objects) > maxArgCount {
- maxArgCount = len(objects)
- }
-
- for i := 0; i < maxArgCount; i++ {
- var actual, expected interface{}
-
- if len(objects) <= i {
- actual = "(Missing)"
- } else {
- actual = objects[i]
- }
-
- if len(args) <= i {
- expected = "(Missing)"
- } else {
- expected = args[i]
- }
-
- if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
-
- // type checking
- if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
- // not match
- differences++
- output = fmt.Sprintf("%s\t%d: \u274C type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actual)
- }
-
- } else {
-
- // normal checking
-
- if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
- // match
- output = fmt.Sprintf("%s\t%d: \u2705 %s == %s\n", output, i, actual, expected)
- } else {
- // not match
- differences++
- output = fmt.Sprintf("%s\t%d: \u274C %s != %s\n", output, i, actual, expected)
- }
- }
-
- }
-
- if differences == 0 {
- return "No differences.", differences
- }
-
- return output, differences
-
-}
-
-// Assert compares the arguments with the specified objects and fails if
-// they do not exactly match.
-func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
-
- // get the differences
- diff, diffCount := args.Diff(objects)
-
- if diffCount == 0 {
- return true
- }
-
- // there are differences... report them...
- t.Logf(diff)
- t.Errorf("%sArguments do not match.", assert.CallerInfo())
-
- return false
-
-}
-
-// String gets the argument at the specified index. Panics if there is no argument, or
-// if the argument is of the wrong type.
-//
-// If no index is provided, String() returns a complete string representation
-// of the arguments.
-func (args Arguments) String(indexOrNil ...int) string {
-
- if len(indexOrNil) == 0 {
- // normal String() method - return a string representation of the args
- var argsStr []string
- for _, arg := range args {
- argsStr = append(argsStr, fmt.Sprintf("%s", reflect.TypeOf(arg)))
- }
- return strings.Join(argsStr, ",")
- } else if len(indexOrNil) == 1 {
- // Index has been specified - get the argument at that index
- var index int = indexOrNil[0]
- var s string
- var ok bool
- if s, ok = args.Get(index).(string); !ok {
- panic(fmt.Sprintf("assert: arguments: String(%d) failed because object wasn't correct type: %s", index, args.Get(index)))
- }
- return s
- }
-
- panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil)))
-
-}
-
-// Int gets the argument at the specified index. Panics if there is no argument, or
-// if the argument is of the wrong type.
-func (args Arguments) Int(index int) int {
- var s int
- var ok bool
- if s, ok = args.Get(index).(int); !ok {
- panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
- }
- return s
-}
-
-// Error gets the argument at the specified index. Panics if there is no argument, or
-// if the argument is of the wrong type.
-func (args Arguments) Error(index int) error {
- obj := args.Get(index)
- var s error
- var ok bool
- if obj == nil {
- return nil
- }
- if s, ok = obj.(error); !ok {
- panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
- }
- return s
-}
-
-// Bool gets the argument at the specified index. Panics if there is no argument, or
-// if the argument is of the wrong type.
-func (args Arguments) Bool(index int) bool {
- var s bool
- var ok bool
- if s, ok = args.Get(index).(bool); !ok {
- panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
- }
- return s
-}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go
deleted file mode 100644
index 1315ceccb..000000000
--- a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go
+++ /dev/null
@@ -1,989 +0,0 @@
-package mock
-
-import (
- "errors"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "testing"
- "time"
-)
-
-/*
- Test objects
-*/
-
-// ExampleInterface represents an example interface.
-type ExampleInterface interface {
- TheExampleMethod(a, b, c int) (int, error)
-}
-
-// TestExampleImplementation is a test implementation of ExampleInterface
-type TestExampleImplementation struct {
- Mock
-}
-
-func (i *TestExampleImplementation) TheExampleMethod(a, b, c int) (int, error) {
- args := i.Called(a, b, c)
- return args.Int(0), errors.New("Whoops")
-}
-
-func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) {
- i.Called(yesorno)
-}
-
-type ExampleType struct {
- ran bool
-}
-
-func (i *TestExampleImplementation) TheExampleMethod3(et *ExampleType) error {
- args := i.Called(et)
- return args.Error(0)
-}
-
-func (i *TestExampleImplementation) TheExampleMethodFunc(fn func(string) error) error {
- args := i.Called(fn)
- return args.Error(0)
-}
-
-func (i *TestExampleImplementation) TheExampleMethodVariadic(a ...int) error {
- args := i.Called(a)
- return args.Error(0)
-}
-
-func (i *TestExampleImplementation) TheExampleMethodVariadicInterface(a ...interface{}) error {
- args := i.Called(a)
- return args.Error(0)
-}
-
-type ExampleFuncType func(string) error
-
-func (i *TestExampleImplementation) TheExampleMethodFuncType(fn ExampleFuncType) error {
- args := i.Called(fn)
- return args.Error(0)
-}
-
-/*
- Mock
-*/
-
-func Test_Mock_TestData(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- if assert.NotNil(t, mockedService.TestData()) {
-
- mockedService.TestData().Set("something", 123)
- assert.Equal(t, 123, mockedService.TestData().Get("something").Data())
- }
-}
-
-func Test_Mock_On(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.On("TheExampleMethod")
- assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
- assert.Equal(t, "TheExampleMethod", c.Method)
-}
-
-func Test_Mock_Chained_On(t *testing.T) {
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.
- On("TheExampleMethod", 1, 2, 3).
- Return(0).
- On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).
- Return(nil)
-
- expectedCalls := []*Call{
- &Call{
- Parent: &mockedService.Mock,
- Method: "TheExampleMethod",
- Arguments: []interface{}{1, 2, 3},
- ReturnArguments: []interface{}{0},
- },
- &Call{
- Parent: &mockedService.Mock,
- Method: "TheExampleMethod3",
- Arguments: []interface{}{AnythingOfType("*mock.ExampleType")},
- ReturnArguments: []interface{}{nil},
- },
- }
- assert.Equal(t, expectedCalls, mockedService.ExpectedCalls)
-}
-
-func Test_Mock_On_WithArgs(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.On("TheExampleMethod", 1, 2, 3, 4)
-
- assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
- assert.Equal(t, "TheExampleMethod", c.Method)
- assert.Equal(t, Arguments{1, 2, 3, 4}, c.Arguments)
-}
-
-func Test_Mock_On_WithFuncArg(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.
- On("TheExampleMethodFunc", AnythingOfType("func(string) error")).
- Return(nil)
-
- assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
- assert.Equal(t, "TheExampleMethodFunc", c.Method)
- assert.Equal(t, 1, len(c.Arguments))
- assert.Equal(t, AnythingOfType("func(string) error"), c.Arguments[0])
-
- fn := func(string) error { return nil }
-
- assert.NotPanics(t, func() {
- mockedService.TheExampleMethodFunc(fn)
- })
-}
-
-func Test_Mock_On_WithVariadicFunc(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.
- On("TheExampleMethodVariadic", []int{1, 2, 3}).
- Return(nil)
-
- assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
- assert.Equal(t, 1, len(c.Arguments))
- assert.Equal(t, []int{1, 2, 3}, c.Arguments[0])
-
- assert.NotPanics(t, func() {
- mockedService.TheExampleMethodVariadic(1, 2, 3)
- })
- assert.Panics(t, func() {
- mockedService.TheExampleMethodVariadic(1, 2)
- })
-
-}
-
-func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.On("TheExampleMethodVariadicInterface", []interface{}{1, 2, 3}).
- Return(nil)
-
- assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
- assert.Equal(t, 1, len(c.Arguments))
- assert.Equal(t, []interface{}{1, 2, 3}, c.Arguments[0])
-
- assert.NotPanics(t, func() {
- mockedService.TheExampleMethodVariadicInterface(1, 2, 3)
- })
- assert.Panics(t, func() {
- mockedService.TheExampleMethodVariadicInterface(1, 2)
- })
-
-}
-
-func Test_Mock_On_WithVariadicFuncWithEmptyInterfaceArray(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- var expected []interface{}
- c := mockedService.
- On("TheExampleMethodVariadicInterface", expected).
- Return(nil)
-
- assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
- assert.Equal(t, 1, len(c.Arguments))
- assert.Equal(t, expected, c.Arguments[0])
-
- assert.NotPanics(t, func() {
- mockedService.TheExampleMethodVariadicInterface()
- })
- assert.Panics(t, func() {
- mockedService.TheExampleMethodVariadicInterface(1, 2)
- })
-
-}
-
-func Test_Mock_On_WithFuncPanics(t *testing.T) {
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- assert.Panics(t, func() {
- mockedService.On("TheExampleMethodFunc", func(string) error { return nil })
- })
-}
-
-func Test_Mock_On_WithFuncTypeArg(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.
- On("TheExampleMethodFuncType", AnythingOfType("mock.ExampleFuncType")).
- Return(nil)
-
- assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
- assert.Equal(t, 1, len(c.Arguments))
- assert.Equal(t, AnythingOfType("mock.ExampleFuncType"), c.Arguments[0])
-
- fn := func(string) error { return nil }
- assert.NotPanics(t, func() {
- mockedService.TheExampleMethodFuncType(fn)
- })
-}
-
-func Test_Mock_Return(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.
- On("TheExampleMethod", "A", "B", true).
- Return(1, "two", true)
-
- require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
-
- call := mockedService.ExpectedCalls[0]
-
- assert.Equal(t, "TheExampleMethod", call.Method)
- assert.Equal(t, "A", call.Arguments[0])
- assert.Equal(t, "B", call.Arguments[1])
- assert.Equal(t, true, call.Arguments[2])
- assert.Equal(t, 1, call.ReturnArguments[0])
- assert.Equal(t, "two", call.ReturnArguments[1])
- assert.Equal(t, true, call.ReturnArguments[2])
- assert.Equal(t, 0, call.Repeatability)
- assert.Nil(t, call.WaitFor)
-}
-
-func Test_Mock_Return_WaitUntil(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
- ch := time.After(time.Second)
-
- c := mockedService.Mock.
- On("TheExampleMethod", "A", "B", true).
- WaitUntil(ch).
- Return(1, "two", true)
-
- // assert that the call was created
- require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
-
- call := mockedService.ExpectedCalls[0]
-
- assert.Equal(t, "TheExampleMethod", call.Method)
- assert.Equal(t, "A", call.Arguments[0])
- assert.Equal(t, "B", call.Arguments[1])
- assert.Equal(t, true, call.Arguments[2])
- assert.Equal(t, 1, call.ReturnArguments[0])
- assert.Equal(t, "two", call.ReturnArguments[1])
- assert.Equal(t, true, call.ReturnArguments[2])
- assert.Equal(t, 0, call.Repeatability)
- assert.Equal(t, ch, call.WaitFor)
-}
-
-func Test_Mock_Return_After(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.Mock.
- On("TheExampleMethod", "A", "B", true).
- Return(1, "two", true).
- After(time.Second)
-
- require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
-
- call := mockedService.Mock.ExpectedCalls[0]
-
- assert.Equal(t, "TheExampleMethod", call.Method)
- assert.Equal(t, "A", call.Arguments[0])
- assert.Equal(t, "B", call.Arguments[1])
- assert.Equal(t, true, call.Arguments[2])
- assert.Equal(t, 1, call.ReturnArguments[0])
- assert.Equal(t, "two", call.ReturnArguments[1])
- assert.Equal(t, true, call.ReturnArguments[2])
- assert.Equal(t, 0, call.Repeatability)
- assert.NotEqual(t, nil, call.WaitFor)
-
-}
-
-func Test_Mock_Return_Run(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- fn := func(args Arguments) {
- arg := args.Get(0).(*ExampleType)
- arg.ran = true
- }
-
- c := mockedService.Mock.
- On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).
- Return(nil).
- Run(fn)
-
- require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
-
- call := mockedService.Mock.ExpectedCalls[0]
-
- assert.Equal(t, "TheExampleMethod3", call.Method)
- assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0])
- assert.Equal(t, nil, call.ReturnArguments[0])
- assert.Equal(t, 0, call.Repeatability)
- assert.NotEqual(t, nil, call.WaitFor)
- assert.NotNil(t, call.Run)
-
- et := ExampleType{}
- assert.Equal(t, false, et.ran)
- mockedService.TheExampleMethod3(&et)
- assert.Equal(t, true, et.ran)
-}
-
-func Test_Mock_Return_Run_Out_Of_Order(t *testing.T) {
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
- f := func(args Arguments) {
- arg := args.Get(0).(*ExampleType)
- arg.ran = true
- }
-
- c := mockedService.Mock.
- On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).
- Run(f).
- Return(nil)
-
- require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
-
- call := mockedService.Mock.ExpectedCalls[0]
-
- assert.Equal(t, "TheExampleMethod3", call.Method)
- assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0])
- assert.Equal(t, nil, call.ReturnArguments[0])
- assert.Equal(t, 0, call.Repeatability)
- assert.NotEqual(t, nil, call.WaitFor)
- assert.NotNil(t, call.Run)
-}
-
-func Test_Mock_Return_Once(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.On("TheExampleMethod", "A", "B", true).
- Return(1, "two", true).
- Once()
-
- require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
-
- call := mockedService.ExpectedCalls[0]
-
- assert.Equal(t, "TheExampleMethod", call.Method)
- assert.Equal(t, "A", call.Arguments[0])
- assert.Equal(t, "B", call.Arguments[1])
- assert.Equal(t, true, call.Arguments[2])
- assert.Equal(t, 1, call.ReturnArguments[0])
- assert.Equal(t, "two", call.ReturnArguments[1])
- assert.Equal(t, true, call.ReturnArguments[2])
- assert.Equal(t, 1, call.Repeatability)
- assert.Nil(t, call.WaitFor)
-}
-
-func Test_Mock_Return_Twice(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.
- On("TheExampleMethod", "A", "B", true).
- Return(1, "two", true).
- Twice()
-
- require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
-
- call := mockedService.ExpectedCalls[0]
-
- assert.Equal(t, "TheExampleMethod", call.Method)
- assert.Equal(t, "A", call.Arguments[0])
- assert.Equal(t, "B", call.Arguments[1])
- assert.Equal(t, true, call.Arguments[2])
- assert.Equal(t, 1, call.ReturnArguments[0])
- assert.Equal(t, "two", call.ReturnArguments[1])
- assert.Equal(t, true, call.ReturnArguments[2])
- assert.Equal(t, 2, call.Repeatability)
- assert.Nil(t, call.WaitFor)
-}
-
-func Test_Mock_Return_Times(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.
- On("TheExampleMethod", "A", "B", true).
- Return(1, "two", true).
- Times(5)
-
- require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
-
- call := mockedService.ExpectedCalls[0]
-
- assert.Equal(t, "TheExampleMethod", call.Method)
- assert.Equal(t, "A", call.Arguments[0])
- assert.Equal(t, "B", call.Arguments[1])
- assert.Equal(t, true, call.Arguments[2])
- assert.Equal(t, 1, call.ReturnArguments[0])
- assert.Equal(t, "two", call.ReturnArguments[1])
- assert.Equal(t, true, call.ReturnArguments[2])
- assert.Equal(t, 5, call.Repeatability)
- assert.Nil(t, call.WaitFor)
-}
-
-func Test_Mock_Return_Nothing(t *testing.T) {
-
- // make a test impl object
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- c := mockedService.
- On("TheExampleMethod", "A", "B", true).
- Return()
-
- require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
-
- call := mockedService.ExpectedCalls[0]
-
- assert.Equal(t, "TheExampleMethod", call.Method)
- assert.Equal(t, "A", call.Arguments[0])
- assert.Equal(t, "B", call.Arguments[1])
- assert.Equal(t, true, call.Arguments[2])
- assert.Equal(t, 0, len(call.ReturnArguments))
-}
-
-func Test_Mock_findExpectedCall(t *testing.T) {
-
- m := new(Mock)
- m.On("One", 1).Return("one")
- m.On("Two", 2).Return("two")
- m.On("Two", 3).Return("three")
-
- f, c := m.findExpectedCall("Two", 3)
-
- if assert.Equal(t, 2, f) {
- if assert.NotNil(t, c) {
- assert.Equal(t, "Two", c.Method)
- assert.Equal(t, 3, c.Arguments[0])
- assert.Equal(t, "three", c.ReturnArguments[0])
- }
- }
-
-}
-
-func Test_Mock_findExpectedCall_For_Unknown_Method(t *testing.T) {
-
- m := new(Mock)
- m.On("One", 1).Return("one")
- m.On("Two", 2).Return("two")
- m.On("Two", 3).Return("three")
-
- f, _ := m.findExpectedCall("Two")
-
- assert.Equal(t, -1, f)
-
-}
-
-func Test_Mock_findExpectedCall_Respects_Repeatability(t *testing.T) {
-
- m := new(Mock)
- m.On("One", 1).Return("one")
- m.On("Two", 2).Return("two").Once()
- m.On("Two", 3).Return("three").Twice()
- m.On("Two", 3).Return("three").Times(8)
-
- f, c := m.findExpectedCall("Two", 3)
-
- if assert.Equal(t, 2, f) {
- if assert.NotNil(t, c) {
- assert.Equal(t, "Two", c.Method)
- assert.Equal(t, 3, c.Arguments[0])
- assert.Equal(t, "three", c.ReturnArguments[0])
- }
- }
-
-}
-
-func Test_callString(t *testing.T) {
-
- assert.Equal(t, `Method(int,bool,string)`, callString("Method", []interface{}{1, true, "something"}, false))
-
-}
-
-func Test_Mock_Called(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("Test_Mock_Called", 1, 2, 3).Return(5, "6", true)
-
- returnArguments := mockedService.Called(1, 2, 3)
-
- if assert.Equal(t, 1, len(mockedService.Calls)) {
- assert.Equal(t, "Test_Mock_Called", mockedService.Calls[0].Method)
- assert.Equal(t, 1, mockedService.Calls[0].Arguments[0])
- assert.Equal(t, 2, mockedService.Calls[0].Arguments[1])
- assert.Equal(t, 3, mockedService.Calls[0].Arguments[2])
- }
-
- if assert.Equal(t, 3, len(returnArguments)) {
- assert.Equal(t, 5, returnArguments[0])
- assert.Equal(t, "6", returnArguments[1])
- assert.Equal(t, true, returnArguments[2])
- }
-
-}
-
-func asyncCall(m *Mock, ch chan Arguments) {
- ch <- m.Called(1, 2, 3)
-}
-
-func Test_Mock_Called_blocks(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.Mock.On("asyncCall", 1, 2, 3).Return(5, "6", true).After(2 * time.Millisecond)
-
- ch := make(chan Arguments)
-
- go asyncCall(&mockedService.Mock, ch)
-
- select {
- case <-ch:
- t.Fatal("should have waited")
- case <-time.After(1 * time.Millisecond):
- }
-
- returnArguments := <-ch
-
- if assert.Equal(t, 1, len(mockedService.Mock.Calls)) {
- assert.Equal(t, "asyncCall", mockedService.Mock.Calls[0].Method)
- assert.Equal(t, 1, mockedService.Mock.Calls[0].Arguments[0])
- assert.Equal(t, 2, mockedService.Mock.Calls[0].Arguments[1])
- assert.Equal(t, 3, mockedService.Mock.Calls[0].Arguments[2])
- }
-
- if assert.Equal(t, 3, len(returnArguments)) {
- assert.Equal(t, 5, returnArguments[0])
- assert.Equal(t, "6", returnArguments[1])
- assert.Equal(t, true, returnArguments[2])
- }
-
-}
-
-func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.
- On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).
- Return(5, "6", true).
- Once()
- mockedService.
- On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).
- Return(-1, "hi", false)
-
- returnArguments1 := mockedService.Called(1, 2, 3)
- returnArguments2 := mockedService.Called(1, 2, 3)
-
- if assert.Equal(t, 2, len(mockedService.Calls)) {
- assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Calls[0].Method)
- assert.Equal(t, 1, mockedService.Calls[0].Arguments[0])
- assert.Equal(t, 2, mockedService.Calls[0].Arguments[1])
- assert.Equal(t, 3, mockedService.Calls[0].Arguments[2])
-
- assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Calls[1].Method)
- assert.Equal(t, 1, mockedService.Calls[1].Arguments[0])
- assert.Equal(t, 2, mockedService.Calls[1].Arguments[1])
- assert.Equal(t, 3, mockedService.Calls[1].Arguments[2])
- }
-
- if assert.Equal(t, 3, len(returnArguments1)) {
- assert.Equal(t, 5, returnArguments1[0])
- assert.Equal(t, "6", returnArguments1[1])
- assert.Equal(t, true, returnArguments1[2])
- }
-
- if assert.Equal(t, 3, len(returnArguments2)) {
- assert.Equal(t, -1, returnArguments2[0])
- assert.Equal(t, "hi", returnArguments2[1])
- assert.Equal(t, false, returnArguments2[2])
- }
-
-}
-
-func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("TheExampleMethod", 1, 2, 3).Return(5, "6", true).Times(4)
-
- mockedService.TheExampleMethod(1, 2, 3)
- mockedService.TheExampleMethod(1, 2, 3)
- mockedService.TheExampleMethod(1, 2, 3)
- mockedService.TheExampleMethod(1, 2, 3)
- assert.Panics(t, func() {
- mockedService.TheExampleMethod(1, 2, 3)
- })
-
-}
-
-func Test_Mock_Called_Unexpected(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- // make sure it panics if no expectation was made
- assert.Panics(t, func() {
- mockedService.Called(1, 2, 3)
- }, "Calling unexpected method should panic")
-
-}
-
-func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
-
- var mockedService1 *TestExampleImplementation = new(TestExampleImplementation)
- var mockedService2 *TestExampleImplementation = new(TestExampleImplementation)
- var mockedService3 *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService1.On("Test_AssertExpectationsForObjects_Helper", 1).Return()
- mockedService2.On("Test_AssertExpectationsForObjects_Helper", 2).Return()
- mockedService3.On("Test_AssertExpectationsForObjects_Helper", 3).Return()
-
- mockedService1.Called(1)
- mockedService2.Called(2)
- mockedService3.Called(3)
-
- assert.True(t, AssertExpectationsForObjects(t, mockedService1.Mock, mockedService2.Mock, mockedService3.Mock))
-
-}
-
-func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) {
-
- var mockedService1 *TestExampleImplementation = new(TestExampleImplementation)
- var mockedService2 *TestExampleImplementation = new(TestExampleImplementation)
- var mockedService3 *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService1.On("Test_AssertExpectationsForObjects_Helper_Failed", 1).Return()
- mockedService2.On("Test_AssertExpectationsForObjects_Helper_Failed", 2).Return()
- mockedService3.On("Test_AssertExpectationsForObjects_Helper_Failed", 3).Return()
-
- mockedService1.Called(1)
- mockedService3.Called(3)
-
- tt := new(testing.T)
- assert.False(t, AssertExpectationsForObjects(tt, mockedService1.Mock, mockedService2.Mock, mockedService3.Mock))
-
-}
-
-func Test_Mock_AssertExpectations(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("Test_Mock_AssertExpectations", 1, 2, 3).Return(5, 6, 7)
-
- tt := new(testing.T)
- assert.False(t, mockedService.AssertExpectations(tt))
-
- // make the call now
- mockedService.Called(1, 2, 3)
-
- // now assert expectations
- assert.True(t, mockedService.AssertExpectations(tt))
-
-}
-
-func Test_Mock_AssertExpectationsCustomType(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).Return(nil).Once()
-
- tt := new(testing.T)
- assert.False(t, mockedService.AssertExpectations(tt))
-
- // make the call now
- mockedService.TheExampleMethod3(&ExampleType{})
-
- // now assert expectations
- assert.True(t, mockedService.AssertExpectations(tt))
-
-}
-
-func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("Test_Mock_AssertExpectations_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Twice()
-
- tt := new(testing.T)
- assert.False(t, mockedService.AssertExpectations(tt))
-
- // make the call now
- mockedService.Called(1, 2, 3)
-
- assert.False(t, mockedService.AssertExpectations(tt))
-
- mockedService.Called(1, 2, 3)
-
- // now assert expectations
- assert.True(t, mockedService.AssertExpectations(tt))
-
-}
-
-func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 1, 2, 3).Return(5, 6, 7)
- mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 4, 5, 6).Return(5, 6, 7)
-
- args1 := mockedService.Called(1, 2, 3)
- assert.Equal(t, 5, args1.Int(0))
- assert.Equal(t, 6, args1.Int(1))
- assert.Equal(t, 7, args1.Int(2))
-
- args2 := mockedService.Called(4, 5, 6)
- assert.Equal(t, 5, args2.Int(0))
- assert.Equal(t, 6, args2.Int(1))
- assert.Equal(t, 7, args2.Int(2))
-
-}
-
-func Test_Mock_AssertNumberOfCalls(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("Test_Mock_AssertNumberOfCalls", 1, 2, 3).Return(5, 6, 7)
-
- mockedService.Called(1, 2, 3)
- assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 1))
-
- mockedService.Called(1, 2, 3)
- assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 2))
-
-}
-
-func Test_Mock_AssertCalled(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("Test_Mock_AssertCalled", 1, 2, 3).Return(5, 6, 7)
-
- mockedService.Called(1, 2, 3)
-
- assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled", 1, 2, 3))
-
-}
-
-func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.
- On("Test_Mock_AssertCalled_WithAnythingOfTypeArgument", Anything, Anything, Anything).
- Return()
-
- mockedService.Called(1, "two", []uint8("three"))
-
- assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled_WithAnythingOfTypeArgument", AnythingOfType("int"), AnythingOfType("string"), AnythingOfType("[]uint8")))
-
-}
-
-func Test_Mock_AssertCalled_WithArguments(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("Test_Mock_AssertCalled_WithArguments", 1, 2, 3).Return(5, 6, 7)
-
- mockedService.Called(1, 2, 3)
-
- tt := new(testing.T)
- assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 1, 2, 3))
- assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 2, 3, 4))
-
-}
-
-func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Once()
- mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4).Return(5, 6, 7).Once()
-
- mockedService.Called(1, 2, 3)
- mockedService.Called(2, 3, 4)
-
- tt := new(testing.T)
- assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3))
- assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4))
- assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 3, 4, 5))
-
-}
-
-func Test_Mock_AssertNotCalled(t *testing.T) {
-
- var mockedService *TestExampleImplementation = new(TestExampleImplementation)
-
- mockedService.On("Test_Mock_AssertNotCalled", 1, 2, 3).Return(5, 6, 7)
-
- mockedService.Called(1, 2, 3)
-
- assert.True(t, mockedService.AssertNotCalled(t, "Test_Mock_NotCalled"))
-
-}
-
-/*
- Arguments helper methods
-*/
-func Test_Arguments_Get(t *testing.T) {
-
- var args Arguments = []interface{}{"string", 123, true}
-
- assert.Equal(t, "string", args.Get(0).(string))
- assert.Equal(t, 123, args.Get(1).(int))
- assert.Equal(t, true, args.Get(2).(bool))
-
-}
-
-func Test_Arguments_Is(t *testing.T) {
-
- var args Arguments = []interface{}{"string", 123, true}
-
- assert.True(t, args.Is("string", 123, true))
- assert.False(t, args.Is("wrong", 456, false))
-
-}
-
-func Test_Arguments_Diff(t *testing.T) {
-
- var args Arguments = []interface{}{"Hello World", 123, true}
- var diff string
- var count int
- diff, count = args.Diff([]interface{}{"Hello World", 456, "false"})
-
- assert.Equal(t, 2, count)
- assert.Contains(t, diff, `%!s(int=456) != %!s(int=123)`)
- assert.Contains(t, diff, `false != %!s(bool=true)`)
-
-}
-
-func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) {
-
- var args Arguments = []interface{}{"string", 123, true}
- var diff string
- var count int
- diff, count = args.Diff([]interface{}{"string", 456, "false", "extra"})
-
- assert.Equal(t, 3, count)
- assert.Contains(t, diff, `extra != (Missing)`)
-
-}
-
-func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) {
-
- var args Arguments = []interface{}{"string", 123, true}
- var count int
- _, count = args.Diff([]interface{}{"string", Anything, true})
-
- assert.Equal(t, 0, count)
-
-}
-
-func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) {
-
- var args Arguments = []interface{}{"string", Anything, true}
- var count int
- _, count = args.Diff([]interface{}{"string", 123, true})
-
- assert.Equal(t, 0, count)
-
-}
-
-func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) {
-
- var args Arguments = []interface{}{"string", AnythingOfType("int"), true}
- var count int
- _, count = args.Diff([]interface{}{"string", 123, true})
-
- assert.Equal(t, 0, count)
-
-}
-
-func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
-
- var args Arguments = []interface{}{"string", AnythingOfType("string"), true}
- var count int
- var diff string
- diff, count = args.Diff([]interface{}{"string", 123, true})
-
- assert.Equal(t, 1, count)
- assert.Contains(t, diff, `string != type int - %!s(int=123)`)
-
-}
-
-func Test_Arguments_Assert(t *testing.T) {
-
- var args Arguments = []interface{}{"string", 123, true}
-
- assert.True(t, args.Assert(t, "string", 123, true))
-
-}
-
-func Test_Arguments_String_Representation(t *testing.T) {
-
- var args Arguments = []interface{}{"string", 123, true}
- assert.Equal(t, `string,int,bool`, args.String())
-
-}
-
-func Test_Arguments_String(t *testing.T) {
-
- var args Arguments = []interface{}{"string", 123, true}
- assert.Equal(t, "string", args.String(0))
-
-}
-
-func Test_Arguments_Error(t *testing.T) {
-
- var err error = errors.New("An Error")
- var args Arguments = []interface{}{"string", 123, true, err}
- assert.Equal(t, err, args.Error(3))
-
-}
-
-func Test_Arguments_Error_Nil(t *testing.T) {
-
- var args Arguments = []interface{}{"string", 123, true, nil}
- assert.Equal(t, nil, args.Error(3))
-
-}
-
-func Test_Arguments_Int(t *testing.T) {
-
- var args Arguments = []interface{}{"string", 123, true}
- assert.Equal(t, 123, args.Int(1))
-
-}
-
-func Test_Arguments_Bool(t *testing.T) {
-
- var args Arguments = []interface{}{"string", 123, true}
- assert.Equal(t, true, args.Bool(2))
-
-}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/.travis.yml b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/.travis.yml
new file mode 100644
index 000000000..44aa48b87
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/.travis.yml
@@ -0,0 +1,15 @@
+language: go
+go:
+ - 1.2
+ - 1.3
+ - 1.4
+ - 1.5
+ - tip
+go_import_path: gopkg.in/asn-ber.v1
+install:
+ - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
+ - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
+ - go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover
+ - go build -v ./...
+script:
+ - go test -v -cover ./...
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/LICENSE b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/LICENSE
new file mode 100644
index 000000000..744875676
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/README.md b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/README.md
new file mode 100644
index 000000000..e3a9560d6
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/README.md
@@ -0,0 +1,24 @@
+[![GoDoc](https://godoc.org/gopkg.in/asn1-ber.v1?status.svg)](https://godoc.org/gopkg.in/asn1-ber.v1) [![Build Status](https://travis-ci.org/go-asn1-ber/asn1-ber.svg)](https://travis-ci.org/go-asn1-ber/asn1-ber)
+
+
+ASN1 BER Encoding / Decoding Library for the GO programming language.
+---------------------------------------------------------------------
+
+Required libraries:
+ None
+
+Working:
+ Very basic encoding / decoding needed for LDAP protocol
+
+Tests Implemented:
+ A few
+
+TODO:
+ Fix all encoding / decoding to conform to ASN1 BER spec
+ Implement Tests / Benchmarks
+
+---
+
+The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
+The design is licensed under the Creative Commons 3.0 Attributions license.
+Read this article for more details: http://blog.golang.org/gopher
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/ber.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/ber.go
new file mode 100644
index 000000000..25cc921be
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/ber.go
@@ -0,0 +1,504 @@
+package ber
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+)
+
+type Packet struct {
+ Identifier
+ Value interface{}
+ ByteValue []byte
+ Data *bytes.Buffer
+ Children []*Packet
+ Description string
+}
+
+type Identifier struct {
+ ClassType Class
+ TagType Type
+ Tag Tag
+}
+
+type Tag uint64
+
+const (
+ TagEOC Tag = 0x00
+ TagBoolean Tag = 0x01
+ TagInteger Tag = 0x02
+ TagBitString Tag = 0x03
+ TagOctetString Tag = 0x04
+ TagNULL Tag = 0x05
+ TagObjectIdentifier Tag = 0x06
+ TagObjectDescriptor Tag = 0x07
+ TagExternal Tag = 0x08
+ TagRealFloat Tag = 0x09
+ TagEnumerated Tag = 0x0a
+ TagEmbeddedPDV Tag = 0x0b
+ TagUTF8String Tag = 0x0c
+ TagRelativeOID Tag = 0x0d
+ TagSequence Tag = 0x10
+ TagSet Tag = 0x11
+ TagNumericString Tag = 0x12
+ TagPrintableString Tag = 0x13
+ TagT61String Tag = 0x14
+ TagVideotexString Tag = 0x15
+ TagIA5String Tag = 0x16
+ TagUTCTime Tag = 0x17
+ TagGeneralizedTime Tag = 0x18
+ TagGraphicString Tag = 0x19
+ TagVisibleString Tag = 0x1a
+ TagGeneralString Tag = 0x1b
+ TagUniversalString Tag = 0x1c
+ TagCharacterString Tag = 0x1d
+ TagBMPString Tag = 0x1e
+ TagBitmask Tag = 0x1f // xxx11111b
+
+ // HighTag indicates the start of a high-tag byte sequence
+ HighTag Tag = 0x1f // xxx11111b
+ // HighTagContinueBitmask indicates the high-tag byte sequence should continue
+ HighTagContinueBitmask Tag = 0x80 // 10000000b
+ // HighTagValueBitmask obtains the tag value from a high-tag byte sequence byte
+ HighTagValueBitmask Tag = 0x7f // 01111111b
+)
+
+const (
+ // LengthLongFormBitmask is the mask to apply to the length byte to see if a long-form byte sequence is used
+ LengthLongFormBitmask = 0x80
+ // LengthValueBitmask is the mask to apply to the length byte to get the number of bytes in the long-form byte sequence
+ LengthValueBitmask = 0x7f
+
+ // LengthIndefinite is returned from readLength to indicate an indefinite length
+ LengthIndefinite = -1
+)
+
+var tagMap = map[Tag]string{
+ TagEOC: "EOC (End-of-Content)",
+ TagBoolean: "Boolean",
+ TagInteger: "Integer",
+ TagBitString: "Bit String",
+ TagOctetString: "Octet String",
+ TagNULL: "NULL",
+ TagObjectIdentifier: "Object Identifier",
+ TagObjectDescriptor: "Object Descriptor",
+ TagExternal: "External",
+ TagRealFloat: "Real (float)",
+ TagEnumerated: "Enumerated",
+ TagEmbeddedPDV: "Embedded PDV",
+ TagUTF8String: "UTF8 String",
+ TagRelativeOID: "Relative-OID",
+ TagSequence: "Sequence and Sequence of",
+ TagSet: "Set and Set OF",
+ TagNumericString: "Numeric String",
+ TagPrintableString: "Printable String",
+ TagT61String: "T61 String",
+ TagVideotexString: "Videotex String",
+ TagIA5String: "IA5 String",
+ TagUTCTime: "UTC Time",
+ TagGeneralizedTime: "Generalized Time",
+ TagGraphicString: "Graphic String",
+ TagVisibleString: "Visible String",
+ TagGeneralString: "General String",
+ TagUniversalString: "Universal String",
+ TagCharacterString: "Character String",
+ TagBMPString: "BMP String",
+}
+
+type Class uint8
+
+const (
+ ClassUniversal Class = 0 // 00xxxxxxb
+ ClassApplication Class = 64 // 01xxxxxxb
+ ClassContext Class = 128 // 10xxxxxxb
+ ClassPrivate Class = 192 // 11xxxxxxb
+ ClassBitmask Class = 192 // 11xxxxxxb
+)
+
+var ClassMap = map[Class]string{
+ ClassUniversal: "Universal",
+ ClassApplication: "Application",
+ ClassContext: "Context",
+ ClassPrivate: "Private",
+}
+
+type Type uint8
+
+const (
+ TypePrimitive Type = 0 // xx0xxxxxb
+ TypeConstructed Type = 32 // xx1xxxxxb
+ TypeBitmask Type = 32 // xx1xxxxxb
+)
+
+var TypeMap = map[Type]string{
+ TypePrimitive: "Primitive",
+ TypeConstructed: "Constructed",
+}
+
+var Debug bool = false
+
+func PrintBytes(out io.Writer, buf []byte, indent string) {
+ data_lines := make([]string, (len(buf)/30)+1)
+ num_lines := make([]string, (len(buf)/30)+1)
+
+ for i, b := range buf {
+ data_lines[i/30] += fmt.Sprintf("%02x ", b)
+ num_lines[i/30] += fmt.Sprintf("%02d ", (i+1)%100)
+ }
+
+ for i := 0; i < len(data_lines); i++ {
+ out.Write([]byte(indent + data_lines[i] + "\n"))
+ out.Write([]byte(indent + num_lines[i] + "\n\n"))
+ }
+}
+
+func PrintPacket(p *Packet) {
+ printPacket(os.Stdout, p, 0, false)
+}
+
+func printPacket(out io.Writer, p *Packet, indent int, printBytes bool) {
+ indent_str := ""
+
+ for len(indent_str) != indent {
+ indent_str += " "
+ }
+
+ class_str := ClassMap[p.ClassType]
+
+ tagtype_str := TypeMap[p.TagType]
+
+ tag_str := fmt.Sprintf("0x%02X", p.Tag)
+
+ if p.ClassType == ClassUniversal {
+ tag_str = tagMap[p.Tag]
+ }
+
+ value := fmt.Sprint(p.Value)
+ description := ""
+
+ if p.Description != "" {
+ description = p.Description + ": "
+ }
+
+ fmt.Fprintf(out, "%s%s(%s, %s, %s) Len=%d %q\n", indent_str, description, class_str, tagtype_str, tag_str, p.Data.Len(), value)
+
+ if printBytes {
+ PrintBytes(out, p.Bytes(), indent_str)
+ }
+
+ for _, child := range p.Children {
+ printPacket(out, child, indent+1, printBytes)
+ }
+}
+
+// ReadPacket reads a single Packet from the reader
+func ReadPacket(reader io.Reader) (*Packet, error) {
+ p, _, err := readPacket(reader)
+ if err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+func DecodeString(data []byte) string {
+ return string(data)
+}
+
+func parseInt64(bytes []byte) (ret int64, err error) {
+ if len(bytes) > 8 {
+ // We'll overflow an int64 in this case.
+ err = fmt.Errorf("integer too large")
+ return
+ }
+ for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
+ ret <<= 8
+ ret |= int64(bytes[bytesRead])
+ }
+
+ // Shift up and down in order to sign extend the result.
+ ret <<= 64 - uint8(len(bytes))*8
+ ret >>= 64 - uint8(len(bytes))*8
+ return
+}
+
+func encodeInteger(i int64) []byte {
+ n := int64Length(i)
+ out := make([]byte, n)
+
+ var j int
+ for ; n > 0; n-- {
+ out[j] = (byte(i >> uint((n-1)*8)))
+ j++
+ }
+
+ return out
+}
+
+func int64Length(i int64) (numBytes int) {
+ numBytes = 1
+
+ for i > 127 {
+ numBytes++
+ i >>= 8
+ }
+
+ for i < -128 {
+ numBytes++
+ i >>= 8
+ }
+
+ return
+}
+
+// DecodePacket decodes the given bytes into a single Packet
+// If a decode error is encountered, nil is returned.
+func DecodePacket(data []byte) *Packet {
+ p, _, _ := readPacket(bytes.NewBuffer(data))
+
+ return p
+}
+
+// DecodePacketErr decodes the given bytes into a single Packet
+// If a decode error is encountered, nil is returned
+func DecodePacketErr(data []byte) (*Packet, error) {
+ p, _, err := readPacket(bytes.NewBuffer(data))
+ if err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+// readPacket reads a single Packet from the reader, returning the number of bytes read
+func readPacket(reader io.Reader) (*Packet, int, error) {
+ identifier, length, read, err := readHeader(reader)
+ if err != nil {
+ return nil, read, err
+ }
+
+ p := &Packet{
+ Identifier: identifier,
+ }
+
+ p.Data = new(bytes.Buffer)
+ p.Children = make([]*Packet, 0, 2)
+ p.Value = nil
+
+ if p.TagType == TypeConstructed {
+ // TODO: if universal, ensure tag type is allowed to be constructed
+
+ // Track how much content we've read
+ contentRead := 0
+ for {
+ if length != LengthIndefinite {
+ // End if we've read what we've been told to
+ if contentRead == length {
+ break
+ }
+ // Detect if a packet boundary didn't fall on the expected length
+ if contentRead > length {
+ return nil, read, fmt.Errorf("expected to read %d bytes, read %d", length, contentRead)
+ }
+ }
+
+ // Read the next packet
+ child, r, err := readPacket(reader)
+ if err != nil {
+ return nil, read, err
+ }
+ contentRead += r
+ read += r
+
+ // Test is this is the EOC marker for our packet
+ if isEOCPacket(child) {
+ if length == LengthIndefinite {
+ break
+ }
+ return nil, read, errors.New("eoc child not allowed with definite length")
+ }
+
+ // Append and continue
+ p.AppendChild(child)
+ }
+ return p, read, nil
+ }
+
+ if length == LengthIndefinite {
+ return nil, read, errors.New("indefinite length used with primitive type")
+ }
+
+ // Read definite-length content
+ content := make([]byte, length, length)
+ if length > 0 {
+ _, err := io.ReadFull(reader, content)
+ if err != nil {
+ if err == io.EOF {
+ return nil, read, io.ErrUnexpectedEOF
+ }
+ return nil, read, err
+ }
+ read += length
+ }
+
+ if p.ClassType == ClassUniversal {
+ p.Data.Write(content)
+ p.ByteValue = content
+
+ switch p.Tag {
+ case TagEOC:
+ case TagBoolean:
+ val, _ := parseInt64(content)
+
+ p.Value = val != 0
+ case TagInteger:
+ p.Value, _ = parseInt64(content)
+ case TagBitString:
+ case TagOctetString:
+ // the actual string encoding is not known here
+ // (e.g. for LDAP content is already an UTF8-encoded
+ // string). Return the data without further processing
+ p.Value = DecodeString(content)
+ case TagNULL:
+ case TagObjectIdentifier:
+ case TagObjectDescriptor:
+ case TagExternal:
+ case TagRealFloat:
+ case TagEnumerated:
+ p.Value, _ = parseInt64(content)
+ case TagEmbeddedPDV:
+ case TagUTF8String:
+ p.Value = DecodeString(content)
+ case TagRelativeOID:
+ case TagSequence:
+ case TagSet:
+ case TagNumericString:
+ case TagPrintableString:
+ p.Value = DecodeString(content)
+ case TagT61String:
+ case TagVideotexString:
+ case TagIA5String:
+ case TagUTCTime:
+ case TagGeneralizedTime:
+ case TagGraphicString:
+ case TagVisibleString:
+ case TagGeneralString:
+ case TagUniversalString:
+ case TagCharacterString:
+ case TagBMPString:
+ }
+ } else {
+ p.Data.Write(content)
+ }
+
+ return p, read, nil
+}
+
+func (p *Packet) Bytes() []byte {
+ var out bytes.Buffer
+
+ out.Write(encodeIdentifier(p.Identifier))
+ out.Write(encodeLength(p.Data.Len()))
+ out.Write(p.Data.Bytes())
+
+ return out.Bytes()
+}
+
+func (p *Packet) AppendChild(child *Packet) {
+ p.Data.Write(child.Bytes())
+ p.Children = append(p.Children, child)
+}
+
+func Encode(ClassType Class, TagType Type, Tag Tag, Value interface{}, Description string) *Packet {
+ p := new(Packet)
+
+ p.ClassType = ClassType
+ p.TagType = TagType
+ p.Tag = Tag
+ p.Data = new(bytes.Buffer)
+
+ p.Children = make([]*Packet, 0, 2)
+
+ p.Value = Value
+ p.Description = Description
+
+ if Value != nil {
+ v := reflect.ValueOf(Value)
+
+ if ClassType == ClassUniversal {
+ switch Tag {
+ case TagOctetString:
+ sv, ok := v.Interface().(string)
+
+ if ok {
+ p.Data.Write([]byte(sv))
+ }
+ }
+ }
+ }
+
+ return p
+}
+
+func NewSequence(Description string) *Packet {
+ return Encode(ClassUniversal, TypeConstructed, TagSequence, nil, Description)
+}
+
+func NewBoolean(ClassType Class, TagType Type, Tag Tag, Value bool, Description string) *Packet {
+ intValue := int64(0)
+
+ if Value {
+ intValue = 1
+ }
+
+ p := Encode(ClassType, TagType, Tag, nil, Description)
+
+ p.Value = Value
+ p.Data.Write(encodeInteger(intValue))
+
+ return p
+}
+
+func NewInteger(ClassType Class, TagType Type, Tag Tag, Value interface{}, Description string) *Packet {
+ p := Encode(ClassType, TagType, Tag, nil, Description)
+
+ p.Value = Value
+ switch v := Value.(type) {
+ case int:
+ p.Data.Write(encodeInteger(int64(v)))
+ case uint:
+ p.Data.Write(encodeInteger(int64(v)))
+ case int64:
+ p.Data.Write(encodeInteger(v))
+ case uint64:
+ // TODO : check range or add encodeUInt...
+ p.Data.Write(encodeInteger(int64(v)))
+ case int32:
+ p.Data.Write(encodeInteger(int64(v)))
+ case uint32:
+ p.Data.Write(encodeInteger(int64(v)))
+ case int16:
+ p.Data.Write(encodeInteger(int64(v)))
+ case uint16:
+ p.Data.Write(encodeInteger(int64(v)))
+ case int8:
+ p.Data.Write(encodeInteger(int64(v)))
+ case uint8:
+ p.Data.Write(encodeInteger(int64(v)))
+ default:
+ // TODO : add support for big.Int ?
+ panic(fmt.Sprintf("Invalid type %T, expected {u|}int{64|32|16|8}", v))
+ }
+
+ return p
+}
+
+func NewString(ClassType Class, TagType Type, Tag Tag, Value, Description string) *Packet {
+ p := Encode(ClassType, TagType, Tag, nil, Description)
+
+ p.Value = Value
+ p.Data.Write([]byte(Value))
+
+ return p
+}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/ber_test.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/ber_test.go
new file mode 100644
index 000000000..bbd22db6d
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/ber_test.go
@@ -0,0 +1,168 @@
+package ber
+
+import (
+ "bytes"
+ "math"
+
+ "io"
+ "testing"
+)
+
+func TestEncodeDecodeInteger(t *testing.T) {
+ for _, v := range []int64{0, 10, 128, 1024, math.MaxInt64, -1, -100, -128, -1024, math.MinInt64} {
+ enc := encodeInteger(v)
+ dec, err := parseInt64(enc)
+ if err != nil {
+ t.Fatalf("Error decoding %d : %s", v, err)
+ }
+ if v != dec {
+ t.Error("TestEncodeDecodeInteger failed for %d (got %d)", v, dec)
+ }
+
+ }
+}
+
+func TestBoolean(t *testing.T) {
+ var value bool = true
+
+ packet := NewBoolean(ClassUniversal, TypePrimitive, TagBoolean, value, "first Packet, True")
+
+ newBoolean, ok := packet.Value.(bool)
+ if !ok || newBoolean != value {
+ t.Error("error during creating packet")
+ }
+
+ encodedPacket := packet.Bytes()
+
+ newPacket := DecodePacket(encodedPacket)
+
+ newBoolean, ok = newPacket.Value.(bool)
+ if !ok || newBoolean != value {
+ t.Error("error during decoding packet")
+ }
+
+}
+
+func TestInteger(t *testing.T) {
+ var value int64 = 10
+
+ packet := NewInteger(ClassUniversal, TypePrimitive, TagInteger, value, "Integer, 10")
+
+ {
+ newInteger, ok := packet.Value.(int64)
+ if !ok || newInteger != value {
+ t.Error("error creating packet")
+ }
+ }
+
+ encodedPacket := packet.Bytes()
+
+ newPacket := DecodePacket(encodedPacket)
+
+ {
+ newInteger, ok := newPacket.Value.(int64)
+ if !ok || int64(newInteger) != value {
+ t.Error("error decoding packet")
+ }
+ }
+}
+
+func TestString(t *testing.T) {
+ var value string = "Hic sunt dracones"
+
+ packet := NewString(ClassUniversal, TypePrimitive, TagOctetString, value, "String")
+
+ newValue, ok := packet.Value.(string)
+ if !ok || newValue != value {
+ t.Error("error during creating packet")
+ }
+
+ encodedPacket := packet.Bytes()
+
+ newPacket := DecodePacket(encodedPacket)
+
+ newValue, ok = newPacket.Value.(string)
+ if !ok || newValue != value {
+ t.Error("error during decoding packet")
+ }
+
+}
+
+func TestSequenceAndAppendChild(t *testing.T) {
+
+ values := []string{
+ "HIC SVNT LEONES",
+ "Iñtërnâtiônàlizætiøn",
+ "Terra Incognita",
+ }
+
+ sequence := NewSequence("a sequence")
+ for _, s := range values {
+ sequence.AppendChild(NewString(ClassUniversal, TypePrimitive, TagOctetString, s, "String"))
+ }
+
+ if len(sequence.Children) != len(values) {
+ t.Errorf("wrong length for children array should be %d, got %d", len(values), len(sequence.Children))
+ }
+
+ encodedSequence := sequence.Bytes()
+
+ decodedSequence := DecodePacket(encodedSequence)
+ if len(decodedSequence.Children) != len(values) {
+ t.Errorf("wrong length for children array should be %d => %d", len(values), len(decodedSequence.Children))
+ }
+
+ for i, s := range values {
+ if decodedSequence.Children[i].Value.(string) != s {
+ t.Errorf("expected %d to be %q, got %q", i, s, decodedSequence.Children[i].Value.(string))
+ }
+ }
+}
+
+func TestReadPacket(t *testing.T) {
+ packet := NewString(ClassUniversal, TypePrimitive, TagOctetString, "Ad impossibilia nemo tenetur", "string")
+ var buffer io.ReadWriter
+ buffer = new(bytes.Buffer)
+
+ buffer.Write(packet.Bytes())
+
+ newPacket, err := ReadPacket(buffer)
+ if err != nil {
+ t.Error("error during ReadPacket", err)
+ }
+ newPacket.ByteValue = nil
+ if !bytes.Equal(newPacket.ByteValue, packet.ByteValue) {
+ t.Error("packets should be the same")
+ }
+}
+
+func TestBinaryInteger(t *testing.T) {
+ // data src : http://luca.ntop.org/Teaching/Appunti/asn1.html 5.7
+ var data = []struct {
+ v int64
+ e []byte
+ }{
+ {v: 0, e: []byte{0x02, 0x01, 0x00}},
+ {v: 127, e: []byte{0x02, 0x01, 0x7F}},
+ {v: 128, e: []byte{0x02, 0x02, 0x00, 0x80}},
+ {v: 256, e: []byte{0x02, 0x02, 0x01, 0x00}},
+ {v: -128, e: []byte{0x02, 0x01, 0x80}},
+ {v: -129, e: []byte{0x02, 0x02, 0xFF, 0x7F}},
+ {v: math.MaxInt64, e: []byte{0x02, 0x08, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
+ {v: math.MinInt64, e: []byte{0x02, 0x08, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ }
+
+ for _, d := range data {
+ if b := NewInteger(ClassUniversal, TypePrimitive, TagInteger, int64(d.v), "").Bytes(); !bytes.Equal(d.e, b) {
+ t.Errorf("Wrong binary generated for %d : got % X, expected % X", d.v, b, d.e)
+ }
+ }
+}
+
+func TestBinaryOctetString(t *testing.T) {
+ // data src : http://luca.ntop.org/Teaching/Appunti/asn1.html 5.10
+
+ if !bytes.Equal([]byte{0x04, 0x08, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, NewString(ClassUniversal, TypePrimitive, TagOctetString, "\x01\x23\x45\x67\x89\xab\xcd\xef", "").Bytes()) {
+ t.Error("wrong binary generated")
+ }
+}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/content_int.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/content_int.go
new file mode 100644
index 000000000..1858b74b6
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/content_int.go
@@ -0,0 +1,25 @@
+package ber
+
+func encodeUnsignedInteger(i uint64) []byte {
+ n := uint64Length(i)
+ out := make([]byte, n)
+
+ var j int
+ for ; n > 0; n-- {
+ out[j] = (byte(i >> uint((n-1)*8)))
+ j++
+ }
+
+ return out
+}
+
+func uint64Length(i uint64) (numBytes int) {
+ numBytes = 1
+
+ for i > 255 {
+ numBytes++
+ i >>= 8
+ }
+
+ return
+}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/header.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/header.go
new file mode 100644
index 000000000..123744e9b
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/header.go
@@ -0,0 +1,29 @@
+package ber
+
+import (
+ "errors"
+ "io"
+)
+
+func readHeader(reader io.Reader) (identifier Identifier, length int, read int, err error) {
+ if i, c, err := readIdentifier(reader); err != nil {
+ return Identifier{}, 0, read, err
+ } else {
+ identifier = i
+ read += c
+ }
+
+ if l, c, err := readLength(reader); err != nil {
+ return Identifier{}, 0, read, err
+ } else {
+ length = l
+ read += c
+ }
+
+ // Validate length type with identifier (x.600, 8.1.3.2.a)
+ if length == LengthIndefinite && identifier.TagType == TypePrimitive {
+ return Identifier{}, 0, read, errors.New("indefinite length used with primitive type")
+ }
+
+ return identifier, length, read, nil
+}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/header_test.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/header_test.go
new file mode 100644
index 000000000..cac1e2e2b
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/header_test.go
@@ -0,0 +1,135 @@
+package ber
+
+import (
+ "bytes"
+ "io"
+ "testing"
+)
+
+func TestReadHeader(t *testing.T) {
+ testcases := map[string]struct {
+ Data []byte
+ ExpectedIdentifier Identifier
+ ExpectedLength int
+ ExpectedBytesRead int
+ ExpectedError string
+ }{
+ "empty": {
+ Data: []byte{},
+ ExpectedIdentifier: Identifier{},
+ ExpectedLength: 0,
+ ExpectedBytesRead: 0,
+ ExpectedError: io.ErrUnexpectedEOF.Error(),
+ },
+
+ "valid short form": {
+ Data: []byte{
+ byte(ClassUniversal) | byte(TypePrimitive) | byte(TagCharacterString),
+ 127,
+ },
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypePrimitive,
+ Tag: TagCharacterString,
+ },
+ ExpectedLength: 127,
+ ExpectedBytesRead: 2,
+ ExpectedError: "",
+ },
+
+ "valid long form": {
+ Data: []byte{
+ // 2-byte encoding of tag
+ byte(ClassUniversal) | byte(TypePrimitive) | byte(HighTag),
+ byte(TagCharacterString),
+
+ // 2-byte encoding of length
+ LengthLongFormBitmask | 1,
+ 127,
+ },
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypePrimitive,
+ Tag: TagCharacterString,
+ },
+ ExpectedLength: 127,
+ ExpectedBytesRead: 4,
+ ExpectedError: "",
+ },
+
+ "valid indefinite length": {
+ Data: []byte{
+ byte(ClassUniversal) | byte(TypeConstructed) | byte(TagCharacterString),
+ LengthLongFormBitmask,
+ },
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: TagCharacterString,
+ },
+ ExpectedLength: LengthIndefinite,
+ ExpectedBytesRead: 2,
+ ExpectedError: "",
+ },
+
+ "invalid indefinite length": {
+ Data: []byte{
+ byte(ClassUniversal) | byte(TypePrimitive) | byte(TagCharacterString),
+ LengthLongFormBitmask,
+ },
+ ExpectedIdentifier: Identifier{},
+ ExpectedLength: 0,
+ ExpectedBytesRead: 2,
+ ExpectedError: "indefinite length used with primitive type",
+ },
+ }
+
+ for k, tc := range testcases {
+ reader := bytes.NewBuffer(tc.Data)
+ identifier, length, read, err := readHeader(reader)
+
+ if err != nil {
+ if tc.ExpectedError == "" {
+ t.Errorf("%s: unexpected error: %v", k, err)
+ } else if err.Error() != tc.ExpectedError {
+ t.Errorf("%s: expected error %v, got %v", k, tc.ExpectedError, err)
+ }
+ } else if tc.ExpectedError != "" {
+ t.Errorf("%s: expected error %v, got none", k, tc.ExpectedError)
+ continue
+ }
+
+ if read != tc.ExpectedBytesRead {
+ t.Errorf("%s: expected read %d, got %d", k, tc.ExpectedBytesRead, read)
+ }
+
+ if identifier.ClassType != tc.ExpectedIdentifier.ClassType {
+ t.Errorf("%s: expected class type %d (%s), got %d (%s)", k,
+ tc.ExpectedIdentifier.ClassType,
+ ClassMap[tc.ExpectedIdentifier.ClassType],
+ identifier.ClassType,
+ ClassMap[identifier.ClassType],
+ )
+ }
+ if identifier.TagType != tc.ExpectedIdentifier.TagType {
+ t.Errorf("%s: expected tag type %d (%s), got %d (%s)", k,
+ tc.ExpectedIdentifier.TagType,
+ TypeMap[tc.ExpectedIdentifier.TagType],
+ identifier.TagType,
+ TypeMap[identifier.TagType],
+ )
+ }
+ if identifier.Tag != tc.ExpectedIdentifier.Tag {
+ t.Errorf("%s: expected tag %d (%s), got %d (%s)", k,
+ tc.ExpectedIdentifier.Tag,
+ tagMap[tc.ExpectedIdentifier.Tag],
+ identifier.Tag,
+ tagMap[identifier.Tag],
+ )
+ }
+
+ if length != tc.ExpectedLength {
+ t.Errorf("%s: expected length %d, got %d", k, tc.ExpectedLength, length)
+ }
+ }
+}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/identifier.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/identifier.go
new file mode 100644
index 000000000..f7672a844
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/identifier.go
@@ -0,0 +1,103 @@
+package ber
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "math"
+)
+
+func readIdentifier(reader io.Reader) (Identifier, int, error) {
+ identifier := Identifier{}
+ read := 0
+
+ // identifier byte
+ b, err := readByte(reader)
+ if err != nil {
+ if Debug {
+ fmt.Printf("error reading identifier byte: %v\n", err)
+ }
+ return Identifier{}, read, err
+ }
+ read++
+
+ identifier.ClassType = Class(b) & ClassBitmask
+ identifier.TagType = Type(b) & TypeBitmask
+
+ if tag := Tag(b) & TagBitmask; tag != HighTag {
+ // short-form tag
+ identifier.Tag = tag
+ return identifier, read, nil
+ }
+
+ // high-tag-number tag
+ tagBytes := 0
+ for {
+ b, err := readByte(reader)
+ if err != nil {
+ if Debug {
+ fmt.Printf("error reading high-tag-number tag byte %d: %v\n", tagBytes, err)
+ }
+ return Identifier{}, read, err
+ }
+ tagBytes++
+ read++
+
+ // Lowest 7 bits get appended to the tag value (x.690, 8.1.2.4.2.b)
+ identifier.Tag <<= 7
+ identifier.Tag |= Tag(b) & HighTagValueBitmask
+
+ // First byte may not be all zeros (x.690, 8.1.2.4.2.c)
+ if tagBytes == 1 && identifier.Tag == 0 {
+ return Identifier{}, read, errors.New("invalid first high-tag-number tag byte")
+ }
+ // Overflow of int64
+ // TODO: support big int tags?
+ if tagBytes > 9 {
+ return Identifier{}, read, errors.New("high-tag-number tag overflow")
+ }
+
+ // Top bit of 0 means this is the last byte in the high-tag-number tag (x.690, 8.1.2.4.2.a)
+ if Tag(b)&HighTagContinueBitmask == 0 {
+ break
+ }
+ }
+
+ return identifier, read, nil
+}
+
+func encodeIdentifier(identifier Identifier) []byte {
+ b := []byte{0x0}
+ b[0] |= byte(identifier.ClassType)
+ b[0] |= byte(identifier.TagType)
+
+ if identifier.Tag < HighTag {
+ // Short-form
+ b[0] |= byte(identifier.Tag)
+ } else {
+ // high-tag-number
+ b[0] |= byte(HighTag)
+
+ tag := identifier.Tag
+
+ highBit := uint(63)
+ for {
+ if tag&(1<<highBit) != 0 {
+ break
+ }
+ highBit--
+ }
+
+ tagBytes := int(math.Ceil(float64(highBit) / 7.0))
+ for i := tagBytes - 1; i >= 0; i-- {
+ offset := uint(i) * 7
+ mask := Tag(0x7f) << offset
+ tagByte := (tag & mask) >> offset
+ if i != 0 {
+ tagByte |= 0x80
+ }
+ b = append(b, byte(tagByte))
+ }
+ }
+ return b
+}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/identifier_test.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/identifier_test.go
new file mode 100644
index 000000000..7169362e2
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/identifier_test.go
@@ -0,0 +1,344 @@
+package ber
+
+import (
+ "bytes"
+ "io"
+ "math"
+ "testing"
+)
+
+func TestReadIdentifier(t *testing.T) {
+ testcases := map[string]struct {
+ Data []byte
+
+ ExpectedIdentifier Identifier
+ ExpectedBytesRead int
+ ExpectedError string
+ }{
+ "empty": {
+ Data: []byte{},
+ ExpectedBytesRead: 0,
+ ExpectedError: io.ErrUnexpectedEOF.Error(),
+ },
+
+ "universal primitive eoc": {
+ Data: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagEOC)},
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypePrimitive,
+ Tag: TagEOC,
+ },
+ ExpectedBytesRead: 1,
+ },
+ "universal primitive character string": {
+ Data: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagCharacterString)},
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypePrimitive,
+ Tag: TagCharacterString,
+ },
+ ExpectedBytesRead: 1,
+ },
+
+ "universal constructed bit string": {
+ Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagBitString)},
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: TagBitString,
+ },
+ ExpectedBytesRead: 1,
+ },
+ "universal constructed character string": {
+ Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagCharacterString)},
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: TagCharacterString,
+ },
+ ExpectedBytesRead: 1,
+ },
+
+ "application constructed object descriptor": {
+ Data: []byte{byte(ClassApplication) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassApplication,
+ TagType: TypeConstructed,
+ Tag: TagObjectDescriptor,
+ },
+ ExpectedBytesRead: 1,
+ },
+ "context constructed object descriptor": {
+ Data: []byte{byte(ClassContext) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassContext,
+ TagType: TypeConstructed,
+ Tag: TagObjectDescriptor,
+ },
+ ExpectedBytesRead: 1,
+ },
+ "private constructed object descriptor": {
+ Data: []byte{byte(ClassPrivate) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassPrivate,
+ TagType: TypeConstructed,
+ Tag: TagObjectDescriptor,
+ },
+ ExpectedBytesRead: 1,
+ },
+
+ "high-tag-number tag missing bytes": {
+ Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag)},
+ ExpectedError: io.ErrUnexpectedEOF.Error(),
+ ExpectedBytesRead: 1,
+ },
+ "high-tag-number tag invalid first byte": {
+ Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag), 0x0},
+ ExpectedError: "invalid first high-tag-number tag byte",
+ ExpectedBytesRead: 2,
+ },
+ "high-tag-number tag invalid first byte with continue bit": {
+ Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag), byte(HighTagContinueBitmask)},
+ ExpectedError: "invalid first high-tag-number tag byte",
+ ExpectedBytesRead: 2,
+ },
+ "high-tag-number tag continuation missing bytes": {
+ Data: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag), byte(HighTagContinueBitmask | 0x1)},
+ ExpectedError: io.ErrUnexpectedEOF.Error(),
+ ExpectedBytesRead: 2,
+ },
+ "high-tag-number tag overflow": {
+ Data: []byte{
+ byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
+ byte(HighTagContinueBitmask | 0x1),
+ byte(HighTagContinueBitmask | 0x1),
+ byte(HighTagContinueBitmask | 0x1),
+ byte(HighTagContinueBitmask | 0x1),
+ byte(HighTagContinueBitmask | 0x1),
+ byte(HighTagContinueBitmask | 0x1),
+ byte(HighTagContinueBitmask | 0x1),
+ byte(HighTagContinueBitmask | 0x1),
+ byte(HighTagContinueBitmask | 0x1),
+ byte(0x1),
+ },
+ ExpectedError: "high-tag-number tag overflow",
+ ExpectedBytesRead: 11,
+ },
+ "max high-tag-number tag": {
+ Data: []byte{
+ byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(0x7f),
+ },
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: Tag(0x7FFFFFFFFFFFFFFF), // 01111111...(63)...11111b
+ },
+ ExpectedBytesRead: 10,
+ },
+ "high-tag-number encoding of low-tag value": {
+ Data: []byte{
+ byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
+ byte(TagObjectDescriptor),
+ },
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: TagObjectDescriptor,
+ },
+ ExpectedBytesRead: 2,
+ },
+ "max high-tag-number tag ignores extra data": {
+ Data: []byte{
+ byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(0x7f),
+ byte(0x01), // extra data, shouldn't be read
+ byte(0x02), // extra data, shouldn't be read
+ byte(0x03), // extra data, shouldn't be read
+ },
+ ExpectedIdentifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: Tag(0x7FFFFFFFFFFFFFFF), // 01111111...(63)...11111b
+ },
+ ExpectedBytesRead: 10,
+ },
+ }
+
+ for k, tc := range testcases {
+ reader := bytes.NewBuffer(tc.Data)
+ identifier, read, err := readIdentifier(reader)
+
+ if err != nil {
+ if tc.ExpectedError == "" {
+ t.Errorf("%s: unexpected error: %v", k, err)
+ } else if err.Error() != tc.ExpectedError {
+ t.Errorf("%s: expected error %v, got %v", k, tc.ExpectedError, err)
+ }
+ } else if tc.ExpectedError != "" {
+ t.Errorf("%s: expected error %v, got none", k, tc.ExpectedError)
+ continue
+ }
+
+ if read != tc.ExpectedBytesRead {
+ t.Errorf("%s: expected read %d, got %d", k, tc.ExpectedBytesRead, read)
+ }
+
+ if identifier.ClassType != tc.ExpectedIdentifier.ClassType {
+ t.Errorf("%s: expected class type %d (%s), got %d (%s)", k,
+ tc.ExpectedIdentifier.ClassType,
+ ClassMap[tc.ExpectedIdentifier.ClassType],
+ identifier.ClassType,
+ ClassMap[identifier.ClassType],
+ )
+ }
+ if identifier.TagType != tc.ExpectedIdentifier.TagType {
+ t.Errorf("%s: expected tag type %d (%s), got %d (%s)", k,
+ tc.ExpectedIdentifier.TagType,
+ TypeMap[tc.ExpectedIdentifier.TagType],
+ identifier.TagType,
+ TypeMap[identifier.TagType],
+ )
+ }
+ if identifier.Tag != tc.ExpectedIdentifier.Tag {
+ t.Errorf("%s: expected tag %d (%s), got %d (%s)", k,
+ tc.ExpectedIdentifier.Tag,
+ tagMap[tc.ExpectedIdentifier.Tag],
+ identifier.Tag,
+ tagMap[identifier.Tag],
+ )
+ }
+ }
+}
+
+func TestEncodeIdentifier(t *testing.T) {
+ testcases := map[string]struct {
+ Identifier Identifier
+ ExpectedBytes []byte
+ }{
+ "universal primitive eoc": {
+ Identifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypePrimitive,
+ Tag: TagEOC,
+ },
+ ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagEOC)},
+ },
+ "universal primitive character string": {
+ Identifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypePrimitive,
+ Tag: TagCharacterString,
+ },
+ ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypePrimitive) | byte(TagCharacterString)},
+ },
+
+ "universal constructed bit string": {
+ Identifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: TagBitString,
+ },
+ ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagBitString)},
+ },
+ "universal constructed character string": {
+ Identifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: TagCharacterString,
+ },
+ ExpectedBytes: []byte{byte(ClassUniversal) | byte(TypeConstructed) | byte(TagCharacterString)},
+ },
+
+ "application constructed object descriptor": {
+ Identifier: Identifier{
+ ClassType: ClassApplication,
+ TagType: TypeConstructed,
+ Tag: TagObjectDescriptor,
+ },
+ ExpectedBytes: []byte{byte(ClassApplication) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
+ },
+ "context constructed object descriptor": {
+ Identifier: Identifier{
+ ClassType: ClassContext,
+ TagType: TypeConstructed,
+ Tag: TagObjectDescriptor,
+ },
+ ExpectedBytes: []byte{byte(ClassContext) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
+ },
+ "private constructed object descriptor": {
+ Identifier: Identifier{
+ ClassType: ClassPrivate,
+ TagType: TypeConstructed,
+ Tag: TagObjectDescriptor,
+ },
+ ExpectedBytes: []byte{byte(ClassPrivate) | byte(TypeConstructed) | byte(TagObjectDescriptor)},
+ },
+
+ "max low-tag-number tag": {
+ Identifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: TagBMPString,
+ },
+ ExpectedBytes: []byte{
+ byte(ClassUniversal) | byte(TypeConstructed) | byte(TagBMPString),
+ },
+ },
+
+ "min high-tag-number tag": {
+ Identifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: TagBMPString + 1,
+ },
+ ExpectedBytes: []byte{
+ byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
+ byte(TagBMPString + 1),
+ },
+ },
+
+ "max high-tag-number tag": {
+ Identifier: Identifier{
+ ClassType: ClassUniversal,
+ TagType: TypeConstructed,
+ Tag: Tag(math.MaxInt64),
+ },
+ ExpectedBytes: []byte{
+ byte(ClassUniversal) | byte(TypeConstructed) | byte(HighTag),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(HighTagContinueBitmask | 0x7f),
+ byte(0x7f),
+ },
+ },
+ }
+
+ for k, tc := range testcases {
+ b := encodeIdentifier(tc.Identifier)
+ if bytes.Compare(tc.ExpectedBytes, b) != 0 {
+ t.Errorf("%s: Expected\n\t%#v\ngot\n\t%#v", k, tc.ExpectedBytes, b)
+ }
+ }
+}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/length.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/length.go
new file mode 100644
index 000000000..8e2ae4ddd
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/length.go
@@ -0,0 +1,71 @@
+package ber
+
+import (
+ "errors"
+ "fmt"
+ "io"
+)
+
+func readLength(reader io.Reader) (length int, read int, err error) {
+ // length byte
+ b, err := readByte(reader)
+ if err != nil {
+ if Debug {
+ fmt.Printf("error reading length byte: %v\n", err)
+ }
+ return 0, 0, err
+ }
+ read++
+
+ switch {
+ case b == 0xFF:
+ // Invalid 0xFF (x.600, 8.1.3.5.c)
+ return 0, read, errors.New("invalid length byte 0xff")
+
+ case b == LengthLongFormBitmask:
+ // Indefinite form, we have to decode packets until we encounter an EOC packet (x.600, 8.1.3.6)
+ length = LengthIndefinite
+
+ case b&LengthLongFormBitmask == 0:
+ // Short definite form, extract the length from the bottom 7 bits (x.600, 8.1.3.4)
+ length = int(b) & LengthValueBitmask
+
+ case b&LengthLongFormBitmask != 0:
+ // Long definite form, extract the number of length bytes to follow from the bottom 7 bits (x.600, 8.1.3.5.b)
+ lengthBytes := int(b) & LengthValueBitmask
+ // Protect against overflow
+ // TODO: support big int length?
+ if lengthBytes > 8 {
+ return 0, read, errors.New("long-form length overflow")
+ }
+ for i := 0; i < lengthBytes; i++ {
+ b, err = readByte(reader)
+ if err != nil {
+ if Debug {
+ fmt.Printf("error reading long-form length byte %d: %v\n", i, err)
+ }
+ return 0, read, err
+ }
+ read++
+
+ // x.600, 8.1.3.5
+ length <<= 8
+ length |= int(b)
+ }
+
+ default:
+ return 0, read, errors.New("invalid length byte")
+ }
+
+ return length, read, nil
+}
+
+func encodeLength(length int) []byte {
+ length_bytes := encodeUnsignedInteger(uint64(length))
+ if length > 127 || len(length_bytes) > 1 {
+ longFormBytes := []byte{(LengthLongFormBitmask | byte(len(length_bytes)))}
+ longFormBytes = append(longFormBytes, length_bytes...)
+ length_bytes = longFormBytes
+ }
+ return length_bytes
+}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/length_test.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/length_test.go
new file mode 100644
index 000000000..afe0e8037
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/length_test.go
@@ -0,0 +1,158 @@
+package ber
+
+import (
+ "bytes"
+ "io"
+ "math"
+ "testing"
+)
+
+func TestReadLength(t *testing.T) {
+ testcases := map[string]struct {
+ Data []byte
+
+ ExpectedLength int
+ ExpectedBytesRead int
+ ExpectedError string
+ }{
+ "empty": {
+ Data: []byte{},
+ ExpectedBytesRead: 0,
+ ExpectedError: io.ErrUnexpectedEOF.Error(),
+ },
+ "invalid first byte": {
+ Data: []byte{0xFF},
+ ExpectedBytesRead: 1,
+ ExpectedError: "invalid length byte 0xff",
+ },
+
+ "indefinite form": {
+ Data: []byte{LengthLongFormBitmask},
+ ExpectedLength: LengthIndefinite,
+ ExpectedBytesRead: 1,
+ },
+
+ "short-definite-form zero length": {
+ Data: []byte{0},
+ ExpectedLength: 0,
+ ExpectedBytesRead: 1,
+ },
+ "short-definite-form length 1": {
+ Data: []byte{1},
+ ExpectedLength: 1,
+ ExpectedBytesRead: 1,
+ },
+ "short-definite-form max length": {
+ Data: []byte{127},
+ ExpectedLength: 127,
+ ExpectedBytesRead: 1,
+ },
+
+ "long-definite-form missing bytes": {
+ Data: []byte{LengthLongFormBitmask | 1},
+ ExpectedBytesRead: 1,
+ ExpectedError: io.ErrUnexpectedEOF.Error(),
+ },
+ "long-definite-form overflow": {
+ Data: []byte{LengthLongFormBitmask | 9},
+ ExpectedBytesRead: 1,
+ ExpectedError: "long-form length overflow",
+ },
+ "long-definite-form zero length": {
+ Data: []byte{LengthLongFormBitmask | 1, 0x0},
+ ExpectedLength: 0,
+ ExpectedBytesRead: 2,
+ },
+ "long-definite-form length 127": {
+ Data: []byte{LengthLongFormBitmask | 1, 127},
+ ExpectedLength: 127,
+ ExpectedBytesRead: 2,
+ },
+ "long-definite-form max length": {
+ Data: []byte{
+ LengthLongFormBitmask | 8,
+ 0x7F,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ },
+ ExpectedLength: math.MaxInt64,
+ ExpectedBytesRead: 9,
+ },
+ }
+
+ for k, tc := range testcases {
+ reader := bytes.NewBuffer(tc.Data)
+ length, read, err := readLength(reader)
+
+ if err != nil {
+ if tc.ExpectedError == "" {
+ t.Errorf("%s: unexpected error: %v", k, err)
+ } else if err.Error() != tc.ExpectedError {
+ t.Errorf("%s: expected error %v, got %v", k, tc.ExpectedError, err)
+ }
+ } else if tc.ExpectedError != "" {
+ t.Errorf("%s: expected error %v, got none", k, tc.ExpectedError)
+ continue
+ }
+
+ if read != tc.ExpectedBytesRead {
+ t.Errorf("%s: expected read %d, got %d", k, tc.ExpectedBytesRead, read)
+ }
+
+ if length != tc.ExpectedLength {
+ t.Errorf("%s: expected length %d, got %d", k, tc.ExpectedLength, length)
+ }
+ }
+}
+
+func TestEncodeLength(t *testing.T) {
+ testcases := map[string]struct {
+ Length int
+ ExpectedBytes []byte
+ }{
+ "0": {
+ Length: 0,
+ ExpectedBytes: []byte{0},
+ },
+ "1": {
+ Length: 1,
+ ExpectedBytes: []byte{1},
+ },
+
+ "max short-form length": {
+ Length: 127,
+ ExpectedBytes: []byte{127},
+ },
+ "min long-form length": {
+ Length: 128,
+ ExpectedBytes: []byte{LengthLongFormBitmask | 1, 128},
+ },
+
+ "max long-form length": {
+ Length: math.MaxInt64,
+ ExpectedBytes: []byte{
+ LengthLongFormBitmask | 8,
+ 0x7F,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ },
+ },
+ }
+
+ for k, tc := range testcases {
+ b := encodeLength(tc.Length)
+ if bytes.Compare(tc.ExpectedBytes, b) != 0 {
+ t.Errorf("%s: Expected\n\t%#v\ngot\n\t%#v", k, tc.ExpectedBytes, b)
+ }
+ }
+}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/suite_test.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/suite_test.go
new file mode 100644
index 000000000..ace8e6705
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/suite_test.go
@@ -0,0 +1,182 @@
+package ber
+
+import (
+ "bytes"
+ "io"
+ "io/ioutil"
+ "testing"
+)
+
+var errEOF = io.ErrUnexpectedEOF.Error()
+
+// Tests from http://www.strozhevsky.com/free_docs/free_asn1_testsuite_descr.pdf
+// Source files and descriptions at http://www.strozhevsky.com/free_docs/TEST_SUITE.zip
+var testcases = []struct {
+ // File contains the path to the BER-encoded file
+ File string
+ // Error indicates whether a decoding error is expected
+ Error string
+ // AbnormalEncoding indicates whether a normalized re-encoding is expected to differ from the original source
+ AbnormalEncoding bool
+ // IndefiniteEncoding indicates the source file used indefinite-length encoding, so the re-encoding is expected to differ (since the length is known)
+ IndefiniteEncoding bool
+}{
+ // Common blocks
+ {File: "tests/tc1.ber", Error: "high-tag-number tag overflow"},
+ {File: "tests/tc2.ber", Error: errEOF},
+ {File: "tests/tc3.ber", Error: errEOF},
+ {File: "tests/tc4.ber", Error: "invalid length byte 0xff"},
+ {File: "tests/tc5.ber", Error: "", AbnormalEncoding: true},
+ // Real numbers (some expected failures are disabled until support is added)
+ {File: "tests/tc6.ber", Error: ""}, // Error: "REAL value +0 must be encoded with zero-length value block"},
+ {File: "tests/tc7.ber", Error: ""}, // Error: "REAL value -0 must be encoded as a special value"},
+ {File: "tests/tc8.ber", Error: ""},
+ {File: "tests/tc9.ber", Error: ""}, // Error: "Bits 6 and 5 of information octet for REAL are equal to 11"
+ {File: "tests/tc10.ber", Error: ""},
+ {File: "tests/tc11.ber", Error: ""}, // Error: "Incorrect NR form"
+ {File: "tests/tc12.ber", Error: ""}, // Error: "Encoding of "special value" not from ASN.1 standard"
+ {File: "tests/tc13.ber", Error: errEOF},
+ {File: "tests/tc14.ber", Error: errEOF},
+ {File: "tests/tc15.ber", Error: ""}, // Error: "Too big value of exponent"
+ {File: "tests/tc16.ber", Error: ""}, // Error: "Too big value of mantissa"
+ {File: "tests/tc17.ber", Error: ""}, // Error: "Too big values for exponent and mantissa + using of "scaling factor" value"
+ // Integers
+ {File: "tests/tc18.ber", Error: ""},
+ {File: "tests/tc19.ber", Error: errEOF},
+ {File: "tests/tc20.ber", Error: ""},
+ // Object identifiers
+ {File: "tests/tc21.ber", Error: ""},
+ {File: "tests/tc22.ber", Error: ""},
+ {File: "tests/tc23.ber", Error: errEOF},
+ {File: "tests/tc24.ber", Error: ""},
+ // Booleans
+ {File: "tests/tc25.ber", Error: ""},
+ {File: "tests/tc26.ber", Error: ""},
+ {File: "tests/tc27.ber", Error: errEOF},
+ {File: "tests/tc28.ber", Error: ""},
+ {File: "tests/tc29.ber", Error: ""},
+ // Null
+ {File: "tests/tc30.ber", Error: ""},
+ {File: "tests/tc31.ber", Error: errEOF},
+ {File: "tests/tc32.ber", Error: ""},
+ // Bitstring (some expected failures are disabled until support is added)
+ {File: "tests/tc33.ber", Error: ""}, // Error: "Too big value for "unused bits""
+ {File: "tests/tc34.ber", Error: errEOF},
+ {File: "tests/tc35.ber", Error: "", IndefiniteEncoding: true}, // Error: "Using of different from BIT STRING types as internal types for constructive encoding"
+ {File: "tests/tc36.ber", Error: "", IndefiniteEncoding: true}, // Error: "Using of "unused bits" in internal BIT STRINGs with constructive form of encoding"
+ {File: "tests/tc37.ber", Error: ""},
+ {File: "tests/tc38.ber", Error: "", IndefiniteEncoding: true},
+ {File: "tests/tc39.ber", Error: ""},
+ {File: "tests/tc40.ber", Error: ""},
+ // Octet string (some expected failures are disabled until support is added)
+ {File: "tests/tc41.ber", Error: "", IndefiniteEncoding: true}, // Error: "Using of different from OCTET STRING types as internal types for constructive encoding"
+ {File: "tests/tc42.ber", Error: errEOF},
+ {File: "tests/tc43.ber", Error: errEOF},
+ {File: "tests/tc44.ber", Error: ""},
+ {File: "tests/tc45.ber", Error: ""},
+ // Bitstring
+ {File: "tests/tc46.ber", Error: "indefinite length used with primitive type"},
+ {File: "tests/tc47.ber", Error: "eoc child not allowed with definite length"},
+ {File: "tests/tc48.ber", Error: "", IndefiniteEncoding: true}, // Error: "Using of more than 7 "unused bits" in BIT STRING with constrictive encoding form"
+}
+
+func TestSuiteDecodePacket(t *testing.T) {
+ // Debug = true
+ for _, tc := range testcases {
+ file := tc.File
+
+ dataIn, err := ioutil.ReadFile(file)
+ if err != nil {
+ t.Errorf("%s: %v", file, err)
+ continue
+ }
+
+ // fmt.Printf("%s: decode %d\n", file, len(dataIn))
+ packet, err := DecodePacketErr(dataIn)
+ if err != nil {
+ if tc.Error == "" {
+ t.Errorf("%s: unexpected error during DecodePacket: %v", file, err)
+ } else if tc.Error != err.Error() {
+ t.Errorf("%s: expected error %q during DecodePacket, got %q", file, tc.Error, err)
+ }
+ continue
+ }
+ if tc.Error != "" {
+ t.Errorf("%s: expected error %q, got none", file, tc.Error)
+ continue
+ }
+
+ dataOut := packet.Bytes()
+ if tc.AbnormalEncoding || tc.IndefiniteEncoding {
+ // Abnormal encodings and encodings that used indefinite length should re-encode differently
+ if bytes.Equal(dataOut, dataIn) {
+ t.Errorf("%s: data should have been re-encoded differently", file)
+ }
+ } else if !bytes.Equal(dataOut, dataIn) {
+ // Make sure the serialized data matches the source
+ t.Errorf("%s: data should be the same", file)
+ }
+
+ packet, err = DecodePacketErr(dataOut)
+ if err != nil {
+ t.Errorf("%s: unexpected error: %v", file, err)
+ continue
+ }
+
+ // Make sure the re-serialized data matches our original serialization
+ dataOut2 := packet.Bytes()
+ if !bytes.Equal(dataOut, dataOut2) {
+ t.Errorf("%s: data should be the same", file)
+ }
+ }
+}
+
+func TestSuiteReadPacket(t *testing.T) {
+ for _, tc := range testcases {
+ file := tc.File
+
+ dataIn, err := ioutil.ReadFile(file)
+ if err != nil {
+ t.Errorf("%s: %v", file, err)
+ continue
+ }
+
+ buffer := bytes.NewBuffer(dataIn)
+ packet, err := ReadPacket(buffer)
+ if err != nil {
+ if tc.Error == "" {
+ t.Errorf("%s: unexpected error during ReadPacket: %v", file, err)
+ } else if tc.Error != err.Error() {
+ t.Errorf("%s: expected error %q during ReadPacket, got %q", file, tc.Error, err)
+ }
+ continue
+ }
+ if tc.Error != "" {
+ t.Errorf("%s: expected error %q, got none", file, tc.Error)
+ continue
+ }
+
+ dataOut := packet.Bytes()
+ if tc.AbnormalEncoding || tc.IndefiniteEncoding {
+ // Abnormal encodings and encodings that used indefinite length should re-encode differently
+ if bytes.Equal(dataOut, dataIn) {
+ t.Errorf("%s: data should have been re-encoded differently", file)
+ }
+ } else if !bytes.Equal(dataOut, dataIn) {
+ // Make sure the serialized data matches the source
+ t.Errorf("%s: data should be the same", file)
+ }
+
+ packet, err = DecodePacketErr(dataOut)
+ if err != nil {
+ t.Errorf("%s: unexpected error: %v", file, err)
+ continue
+ }
+
+ // Make sure the re-serialized data matches our original serialization
+ dataOut2 := packet.Bytes()
+ if !bytes.Equal(dataOut, dataOut2) {
+ t.Errorf("%s: data should be the same", file)
+ }
+ }
+}
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc1.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc1.ber
new file mode 100644
index 000000000..5c6ba1c6a
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc1.ber
@@ -0,0 +1 @@
+Ÿÿÿÿÿÿÿÿÿÿ@ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc10.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc10.ber
new file mode 100644
index 000000000..f733125d4
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc10.ber
@@ -0,0 +1 @@
+ ƒÿÿÿû \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc11.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc11.ber
new file mode 100644
index 000000000..cc4a609c8
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc11.ber
@@ -0,0 +1 @@
+  015625 \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc12.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc12.ber
new file mode 100644
index 000000000..dbb538d69
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc12.ber
@@ -0,0 +1 @@
+ I \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc13.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc13.ber
new file mode 100644
index 000000000..f4f438e0d
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc13.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc14.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc14.ber
new file mode 100644
index 000000000..b6f2fd3a4
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc14.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc15.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc15.ber
new file mode 100644
index 000000000..3d6da6764
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc15.ber
@@ -0,0 +1 @@
+ ƒ ÿÿÿÿÿÿÿû \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc16.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc16.ber
new file mode 100644
index 000000000..68634f5f3
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc16.ber
@@ -0,0 +1 @@
+ €û \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc17.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc17.ber
new file mode 100644
index 000000000..adb9e3320
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc17.ber
@@ -0,0 +1 @@
+ ¯ þÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc18.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc18.ber
new file mode 100644
index 000000000..fb6843f7f
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc18.ber
@@ -0,0 +1 @@
+ÿð \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc19.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc19.ber
new file mode 100644
index 000000000..03afaa5de
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc19.ber
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc2.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc2.ber
new file mode 100644
index 000000000..7e785773c
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc2.ber
@@ -0,0 +1 @@
+Ÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc20.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc20.ber
new file mode 100644
index 000000000..a976464b9
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc20.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc21.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc21.ber
new file mode 100644
index 000000000..d6c2f9aa7
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc21.ber
@@ -0,0 +1 @@
+€€Q€€ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc22.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc22.ber
new file mode 100644
index 000000000..d1d70afab
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc22.ber
@@ -0,0 +1 @@
+ÿÿÿÿÿÿÿÿÿÿ… \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc23.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc23.ber
new file mode 100644
index 000000000..0e8d18f62
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc23.ber
@@ -0,0 +1 @@
+ÿÿÿÿÿ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc24.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc24.ber
new file mode 100644
index 000000000..10565aefa
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc24.ber
@@ -0,0 +1 @@
+Î`†HˆŸO …îåJ…ä¿c‹Û/ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc25.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc25.ber
new file mode 100644
index 000000000..1e1140524
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc25.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc26.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc26.ber
new file mode 100644
index 000000000..d28653b3b
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc26.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc27.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc27.ber
new file mode 100644
index 000000000..c8c781144
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc27.ber
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc28.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc28.ber
new file mode 100644
index 000000000..415fe23ed
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc28.ber
@@ -0,0 +1 @@
+ÿ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc29.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc29.ber
new file mode 100644
index 000000000..4076f4487
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc29.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc3.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc3.ber
new file mode 100644
index 000000000..c05c900b6
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc3.ber
@@ -0,0 +1 @@
+Ÿÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc30.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc30.ber
new file mode 100644
index 000000000..72bcf80f4
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc30.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc31.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc31.ber
new file mode 100644
index 000000000..1fcc4f254
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc31.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc32.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc32.ber
new file mode 100644
index 000000000..19b3e940a
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc32.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc33.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc33.ber
new file mode 100644
index 000000000..6ea70c4d2
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc33.ber
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc34.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc34.ber
new file mode 100644
index 000000000..61337095d
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc34.ber
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc35.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc35.ber
new file mode 100644
index 000000000..d27eb301a
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc35.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc36.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc36.ber
new file mode 100644
index 000000000..e5baaeacd
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc36.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc37.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc37.ber
new file mode 100644
index 000000000..d0b1cfbe1
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc37.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc38.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc38.ber
new file mode 100644
index 000000000..090bce74b
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc38.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc39.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc39.ber
new file mode 100644
index 000000000..d9d01199b
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc39.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc4.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc4.ber
new file mode 100644
index 000000000..2b888baac
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc4.ber
@@ -0,0 +1 @@
+Ÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc40.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc40.ber
new file mode 100644
index 000000000..15294a501
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc40.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc41.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc41.ber
new file mode 100644
index 000000000..276836b65
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc41.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc42.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc42.ber
new file mode 100644
index 000000000..21cbfd10f
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc42.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc43.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc43.ber
new file mode 100644
index 000000000..98dbd7419
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc43.ber
@@ -0,0 +1 @@
+$ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc44.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc44.ber
new file mode 100644
index 000000000..d825e1ad7
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc44.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc45.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc45.ber
new file mode 100644
index 000000000..7b861b02c
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc45.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc46.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc46.ber
new file mode 100644
index 000000000..e78deee34
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc46.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc47.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc47.ber
new file mode 100644
index 000000000..190bb86f6
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc47.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc48.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc48.ber
new file mode 100644
index 000000000..f7f111ae6
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc48.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc5.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc5.ber
new file mode 100644
index 000000000..45e0a0093
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc5.ber
@@ -0,0 +1 @@
+Ÿÿÿÿÿÿÿÿÿ@ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc6.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc6.ber
new file mode 100644
index 000000000..cee1aaf0c
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc6.ber
@@ -0,0 +1 @@
+ +0.E-5 \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc7.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc7.ber
new file mode 100644
index 000000000..d5ae68572
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc7.ber
@@ -0,0 +1 @@
+ -0.E-5 \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc8.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc8.ber
new file mode 100644
index 000000000..cb32a09cb
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc8.ber
Binary files differ
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc9.ber b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc9.ber
new file mode 100644
index 000000000..50b43a510
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/tests/tc9.ber
@@ -0,0 +1 @@
+ ¼þ \ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/util.go b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/util.go
new file mode 100644
index 000000000..3e56b66c8
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/asn1-ber.v1/util.go
@@ -0,0 +1,24 @@
+package ber
+
+import "io"
+
+func readByte(reader io.Reader) (byte, error) {
+ bytes := make([]byte, 1, 1)
+ _, err := io.ReadFull(reader, bytes)
+ if err != nil {
+ if err == io.EOF {
+ return 0, io.ErrUnexpectedEOF
+ }
+ return 0, err
+ }
+ return bytes[0], nil
+}
+
+func isEOCPacket(p *Packet) bool {
+ return p != nil &&
+ p.Tag == TagEOC &&
+ p.ClassType == ClassUniversal &&
+ p.TagType == TypePrimitive &&
+ len(p.ByteValue) == 0 &&
+ len(p.Children) == 0
+}
diff --git a/Makefile b/Makefile
index 3d08909ad..9fd74b959 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,9 @@ BUILD_NUMBER ?= $(BUILD_NUMBER:)
BUILD_DATE = $(shell date -u)
BUILD_HASH = $(shell git rev-parse HEAD)
+ENTERPRISE_DIR ?= ../enterprise
+BUILD_ENTERPRISE ?= true
+
GO=$(GOPATH)/bin/godep go
ESLINT=node_modules/eslint/bin/eslint.js
@@ -31,6 +34,10 @@ all: dist-local
dist: | build-server build-client go-test package
mv ./model/version.go.bak ./model/version.go
+ @if [ "$(BUILD_ENTERPRISE)" = "true" ] && [ -d "$(ENTERPRISE_DIR)" ]; then \
+ mv ./mattermost.go.bak ./mattermost.go; \
+ mv ./config/config.json.bak ./config/config.json 2> /dev/null || true; \
+ fi
dist-local: | start-docker dist
@@ -79,9 +86,21 @@ build-server:
sed -i'.make_mac_work' 's|_BUILD_NUMBER_|$(BUILD_NUMBER)|g' ./model/version.go
sed -i'.make_mac_work' 's|_BUILD_DATE_|$(BUILD_DATE)|g' ./model/version.go
sed -i'.make_mac_work' 's|_BUILD_HASH_|$(BUILD_HASH)|g' ./model/version.go
+
+ @if [ "$(BUILD_ENTERPRISE)" = "true" ] && [ -d "$(ENTERPRISE_DIR)" ]; then \
+ cp ./config/config.json ./config/config.json.bak; \
+ jq -s '.[0] * .[1]' ./config/config.json $(ENTERPRISE_DIR)/config/enterprise-config-additions.json > config.json.tmp; \
+ mv config.json.tmp ./config/config.json; \
+ sed -e '/\/\/ENTERPRISE_IMPORTS/ {' -e 'r $(ENTERPRISE_DIR)/imports' -e 'd' -e '}' -i'.bak' mattermost.go; \
+ sed -i'.make_mac_work' 's|_BUILD_ENTERPRISE_READY_|true|g' ./model/version.go; \
+ else \
+ sed -i'.make_mac_work' 's|_BUILD_ENTERPRISE_READY_|false|g' ./model/version.go; \
+ fi
+
rm ./model/version.go.make_mac_work
$(GO) build $(GOFLAGS) ./...
+ $(GO) generate $(GOFLAGS) ./...
$(GO) install $(GOFLAGS) ./...
package:
@@ -242,6 +261,13 @@ run: start-docker .prepare-go .prepare-jsx
@echo Starting react processo
cd web/react && npm start &
+ @if [ "$(BUILD_ENTERPRISE)" = "true" ] && [ -d "$(ENTERPRISE_DIR)" ]; then \
+ cp ./config/config.json ./config/config.json.bak; \
+ jq -s '.[0] * .[1]' ./config/config.json $(ENTERPRISE_DIR)/config/enterprise-config-additions.json > config.json.tmp; \
+ mv config.json.tmp ./config/config.json; \
+ sed -e '/\/\/ENTERPRISE_IMPORTS/ {' -e 'r $(ENTERPRISE_DIR)/imports' -e 'd' -e '}' -i'.bak' mattermost.go; \
+ fi
+
@echo Starting go web server
$(GO) run $(GOFLAGS) mattermost.go -config=config.json &
@@ -270,6 +296,11 @@ stop:
docker rm -v ${DOCKER_CONTAINER_NAME} > /dev/null; \
fi
+ @if [ "$(BUILD_ENTERPRISE)" = "true" ] && [ -d "$(ENTERPRISE_DIR)" ]; then \
+ mv ./config/config.json.bak ./config/config.json 2> /dev/null || true; \
+ mv ./mattermost.go.bak ./mattermost.go 2> /dev/null || true; \
+ fi
+
setup-mac:
echo $$(boot2docker ip 2> /dev/null) dockerhost | sudo tee -a /etc/hosts
diff --git a/api/file.go b/api/file.go
index 4339e610b..d31abfb1d 100644
--- a/api/file.go
+++ b/api/file.go
@@ -23,7 +23,6 @@ import (
"image/jpeg"
"io"
"io/ioutil"
- "mime"
"net/http"
"net/url"
"os"
@@ -323,25 +322,22 @@ func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) {
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId)
path := "teams/" + c.Session.TeamId + "/channels/" + channelId + "/users/" + userId + "/" + filename
- size := ""
+ var info *model.FileInfo
- if s, ok := fileInfoCache.Get(path); ok {
- size = s.(string)
+ if cached, ok := fileInfoCache.Get(path); ok {
+ info = cached.(*model.FileInfo)
} else {
-
fileData := make(chan []byte)
getFileAndForget(path, fileData)
- f := <-fileData
-
- if f == nil {
- c.Err = model.NewAppError("getFileInfo", "Could not find file.", "path="+path)
- c.Err.StatusCode = http.StatusNotFound
+ newInfo, err := model.GetInfoForBytes(filename, <-fileData)
+ if err != nil {
+ c.Err = err
return
+ } else {
+ fileInfoCache.Add(path, newInfo)
+ info = newInfo
}
-
- size = strconv.Itoa(len(f))
- fileInfoCache.Add(path, size)
}
if !c.HasPermissionsToChannel(cchan, "getFileInfo") {
@@ -350,19 +346,7 @@ func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=2592000, public")
- var mimeType string
- ext := filepath.Ext(filename)
- if model.IsFileExtImage(ext) {
- mimeType = model.GetImageMimeType(ext)
- } else {
- mimeType = mime.TypeByExtension(ext)
- }
-
- result := make(map[string]string)
- result["filename"] = filename
- result["size"] = size
- result["mime"] = mimeType
- w.Write([]byte(model.MapToJson(result)))
+ w.Write([]byte(info.ToJson()))
}
func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
diff --git a/api/file_test.go b/api/file_test.go
index b5501e4bd..b3fbd2a27 100644
--- a/api/file_test.go
+++ b/api/file_test.go
@@ -152,7 +152,6 @@ func TestGetFile(t *testing.T) {
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
if utils.Cfg.FileSettings.DriverName != "" {
-
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("files", "test.png")
@@ -204,9 +203,9 @@ func TestGetFile(t *testing.T) {
if resp, downErr := Client.GetFileInfo(filenames[0]); downErr != nil {
t.Fatal(downErr)
} else {
- m := resp.Data.(map[string]string)
- if len(m["size"]) == 0 {
- t.Fail()
+ info := resp.Data.(*model.FileInfo)
+ if info.Size == 0 {
+ t.Fatal("No file size returned")
}
}
diff --git a/api/team.go b/api/team.go
index 0918b40e2..dd9bd0bac 100644
--- a/api/team.go
+++ b/api/team.go
@@ -221,8 +221,9 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
teamSignup.User.TeamId = rteam.Id
teamSignup.User.EmailVerified = true
- ruser := CreateUser(c, rteam, &teamSignup.User)
- if c.Err != nil {
+ ruser, err := CreateUser(rteam, &teamSignup.User)
+ if err != nil {
+ c.Err = err
return
}
diff --git a/api/user.go b/api/user.go
index 886e38c91..1df8fff73 100644
--- a/api/user.go
+++ b/api/user.go
@@ -11,6 +11,7 @@ import (
"github.com/disintegration/imaging"
"github.com/golang/freetype"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -44,6 +45,7 @@ func InitUser(r *mux.Router) {
sr.Handle("/reset_password", ApiAppHandler(resetPassword)).Methods("POST")
sr.Handle("/login", ApiAppHandler(login)).Methods("POST")
sr.Handle("/logout", ApiUserRequired(logout)).Methods("POST")
+ sr.Handle("/login_ldap", ApiAppHandler(loginLdap)).Methods("POST")
sr.Handle("/revoke_session", ApiUserRequired(revokeSession)).Methods("POST")
sr.Handle("/newimage", ApiUserRequired(uploadProfileImage)).Methods("POST")
@@ -59,7 +61,7 @@ func InitUser(r *mux.Router) {
}
func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.EmailSettings.EnableSignUpWithEmail {
+ if !utils.Cfg.EmailSettings.EnableSignUpWithEmail || !utils.Cfg.TeamSettings.EnableUserCreation {
c.Err = model.NewAppError("signupTeam", "User sign-up with email is disabled.", "")
c.Err.StatusCode = http.StatusNotImplemented
return
@@ -118,8 +120,9 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
user.EmailVerified = true
}
- ruser := CreateUser(c, team, user)
- if c.Err != nil {
+ ruser, err := CreateUser(team, user)
+ if err != nil {
+ c.Err = err
return
}
@@ -163,12 +166,7 @@ func IsVerifyHashRequired(user *model.User, team *model.Team, hash string) bool
return shouldVerifyHash
}
-func CreateUser(c *Context, team *model.Team, user *model.User) *model.User {
-
- if !utils.Cfg.TeamSettings.EnableUserCreation {
- c.Err = model.NewAppError("CreateUser", "User creation has been disabled. Please ask your systems administrator for details.", "")
- return nil
- }
+func CreateUser(team *model.Team, user *model.User) (*model.User, *model.AppError) {
channelRole := ""
if team.Email == user.Email {
@@ -178,8 +176,7 @@ func CreateUser(c *Context, team *model.Team, user *model.User) *model.User {
// Below is a speical case where the first user in the entire
// system is granted the system_admin role instead of admin
if result := <-Srv.Store.User().GetTotalUsersCount(); result.Err != nil {
- c.Err = result.Err
- return nil
+ return nil, result.Err
} else {
count := result.Data.(int64)
if count <= 0 {
@@ -194,9 +191,8 @@ func CreateUser(c *Context, team *model.Team, user *model.User) *model.User {
user.MakeNonNil()
if result := <-Srv.Store.User().Save(user); result.Err != nil {
- c.Err = result.Err
l4g.Error("Couldn't save the user err=%v", result.Err)
- return nil
+ return nil, result.Err
} else {
ruser := result.Data.(*model.User)
@@ -225,7 +221,7 @@ func CreateUser(c *Context, team *model.Team, user *model.User) *model.User {
PublishAndForget(message)
- return ruser
+ return ruser, nil
}
}
@@ -313,7 +309,7 @@ func LoginById(c *Context, w http.ResponseWriter, r *http.Request, userId, passw
return nil
} else {
user := result.Data.(*model.User)
- if checkUserPassword(c, user, password) {
+ if checkUserLoginAttempts(c, user) && checkUserPassword(c, user, password) {
Login(c, w, r, user, deviceId)
return user
}
@@ -339,7 +335,7 @@ func LoginByEmail(c *Context, w http.ResponseWriter, r *http.Request, email, nam
} else {
user := result.Data.(*model.User)
- if checkUserPassword(c, user, password) {
+ if checkUserLoginAttempts(c, user) && checkUserPassword(c, user, password) {
Login(c, w, r, user, deviceId)
return user
}
@@ -348,8 +344,7 @@ func LoginByEmail(c *Context, w http.ResponseWriter, r *http.Request, email, nam
return nil
}
-func checkUserPassword(c *Context, user *model.User, password string) bool {
-
+func checkUserLoginAttempts(c *Context, user *model.User) bool {
if user.FailedAttempts >= utils.Cfg.ServiceSettings.MaximumLoginAttempts {
c.LogAuditWithUserId(user.Id, "fail")
c.Err = model.NewAppError("checkUserPassword", "Your account is locked because of too many failed password attempts. Please reset your password.", "user_id="+user.Id)
@@ -357,6 +352,11 @@ func checkUserPassword(c *Context, user *model.User, password string) bool {
return false
}
+ return true
+}
+
+func checkUserPassword(c *Context, user *model.User, password string) bool {
+
if !model.ComparePassword(user.Password, password) {
c.LogAuditWithUserId(user.Id, "fail")
c.Err = model.NewAppError("checkUserPassword", "Login failed because of invalid password", "user_id="+user.Id)
@@ -500,6 +500,70 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(user.ToJson()))
}
+func loginLdap(c *Context, w http.ResponseWriter, r *http.Request) {
+ if !*utils.Cfg.LdapSettings.Enable {
+ c.Err = model.NewAppError("loginLdap", "LDAP not enabled on this server", "")
+ c.Err.StatusCode = http.StatusNotImplemented
+ return
+ }
+
+ props := model.MapFromJson(r.Body)
+
+ password := props["password"]
+ id := props["id"]
+ teamName := props["teamName"]
+
+ if len(password) == 0 {
+ c.Err = model.NewAppError("loginLdap", "Password field must not be blank", "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
+ }
+
+ if len(id) == 0 {
+ c.Err = model.NewAppError("loginLdap", "Need an ID", "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
+ }
+
+ teamc := Srv.Store.Team().GetByName(teamName)
+
+ ldapInterface := einterfaces.GetLdapInterface()
+ if ldapInterface == nil {
+ c.Err = model.NewAppError("loginLdap", "LDAP not available on this server", "")
+ c.Err.StatusCode = http.StatusNotImplemented
+ return
+ }
+
+ var team *model.Team
+ if result := <-teamc; result.Err != nil {
+ c.Err = result.Err
+ return
+ } else {
+ team = result.Data.(*model.Team)
+ }
+
+ user, err := ldapInterface.DoLogin(team, id, password)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ if !checkUserLoginAttempts(c, user) {
+ return
+ }
+
+ // User is authenticated at this point
+
+ Login(c, w, r, user, props["device_id"])
+
+ if user != nil {
+ user.Sanitize(map[string]bool{})
+ } else {
+ user = &model.User{}
+ }
+ w.Write([]byte(user.ToJson()))
+}
+
func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
id := props["id"]
diff --git a/doc/developer/tests/test-markdown-lists.md b/doc/developer/tests/test-markdown-lists.md
index d5bbd82ac..7d080526a 100644
--- a/doc/developer/tests/test-markdown-lists.md
+++ b/doc/developer/tests/test-markdown-lists.md
@@ -195,6 +195,25 @@ This text should be on a new line.
- Two
This text should be on a new line.
+**Expected:**
+```
+List:
+
+- One
+- Two
+
+This line should have a line break above it.
+```
+
+**Actual:**
+
+List:
+
+- One
+- Two
+
+This line should have a line break above it.
+
### Task Lists
**Expected:**
diff --git a/doc/help/Creating-Teams.md b/doc/help/Creating-Teams.md
new file mode 100644
index 000000000..598f38e75
--- /dev/null
+++ b/doc/help/Creating-Teams.md
@@ -0,0 +1,38 @@
+# Creating Teams
+___
+New teams can be created if the System Administrator has *Enable Team Creation* set to true from the system console.
+
+## Methods to Create a Team
+Teams can be created from the main menu, system home page or team sign in page.
+
+#### Main Menu
+Click the **Three-Dot** menu in Mattermost, then select **Create a New Team**. If this option is not visible in the menu, then the System Administrator has *Enable Team Creation* set to false.
+
+
+#### System Home Page
+Navigate to the web address of your system, `https://domain.com/`. Enter a valid email address and click **Create Team** to be guided through the rest of the set up steps. If this option is not visible on the web page, then the System Administrator has *Enable Team Creation* set to false. It is not necessary to have an existing account on the system in order to create a team from the system home page.
+
+#### Team Sign In Page
+Navigate to the web address of your team, `https://domain.com/teamurl/`. If you are logged in, the web address will open Mattermost and you can create a new team from the main menu. If you are logged out, the web address will direct you to the sign in page where you can click **Create a New Team**. If this option is not visible on the web page, then the System Administrator has *Enable Team Creation* set to false. It is not necessary to have an existing account on the system in order to create a team from the sign in page.
+
+## Team Name and URL Selection
+There are a few details and restrictions to consider when selecting a team name and team URL.
+
+#### Team Name
+This is the display name of your team that appears in menus and headings.
+
+- It can contain any letters, numbers or symbols.
+- It is case sensitive.
+- It must be 4 - 15 characters in length.
+
+#### Team URL
+The team URL is part of the web address that navigates to your team on the system domain, `https://domain.com/teamurl/`.
+
+- It may contain only lowercase letters, numbers and dashes.
+- It must start with a letter and cannot end in a dash.
+- It must be 4 - 15 characters in length.
+
+If the system administrator has *Restrict Team Names* set to true, the team URL cannot start with the following restricted words: www, web, admin, support, notify, test, demo, mail, team, channel, internal, localhost, dockerhost, stag, post, cluster, api, oauth.
+
+## User Roles on Multiple Teams
+Each user is distinct and owned by a team. A team creator is automatically granted Team Administrator privileges for that team, even if they are a System Administrator on another team. A System Administrator with accounts on multiple teams must grant all their accounts *System Admin* privileges from the system console. To do this, go to the **Main Menu > System Console**, then click **Users** under the *Teams* heading for the team you want to manage.
diff --git a/doc/install/Configuration-Settings.md b/doc/install/Configuration-Settings.md
index 5f9b3b62d..c18012af8 100644
--- a/doc/install/Configuration-Settings.md
+++ b/doc/install/Configuration-Settings.md
@@ -289,6 +289,52 @@ Enter `https://<your-gitlab-url>/oauth/authorize` (example: `https://example.com
```"UserApiEndpoint": ""```
Enter `https://<your-gitlab-url>/oauth/authorize` (example: `https://example.com:3000/api/v3/user`). Use HTTP or HTTPS depending on how your server is configured.
+### LDAP Settings (Enterprise)
+
+Settings used to enable and configure LDAP authentication with Mattermost. Available in the Enterprise version of Mattermost.
+
+```"Enable Login With LDAP": "false"```
+When true, Mattermost allows login using LDAP.
+
+```“LDAP Serverâ€: “â€```
+The domain or IP address of the LDAP server.
+
+```“LDAP Portâ€: “389â€```
+The port Mattermost will use to connect to the LDAP server. Default is 389.
+
+```â€BaseDNâ€: â€â€```
+The Base DN is the Distinguished Name of the location where Mattermost should start its search for users in the LDAP tree.
+
+```â€Bind Usernameâ€: â€â€```
+The username used to perform the LDAP search. This should typically be an account created specifically for use with Mattermost. It should be a read only account with access limited to the portion of the LDAP tree specified in the BaseDN field.
+
+```â€Bind Passwordâ€: â€â€```
+Password of the user given in “Bind Usernameâ€.
+
+```â€First Name Attributeâ€: â€â€```
+The attribute in the LDAP server that will be used to populate the first name of users in Mattermost.
+
+```â€Last Name Attributeâ€: â€â€```
+The attribute in the LDAP server that will be used to populate the last name of users in Mattermost.
+
+```â€Email Attributeâ€: â€â€```
+The attribute in the LDAP server that will be used to populate the email addresses of users in Mattermost.
+
+```â€Username Attributeâ€: â€â€```
+The attribute in the LDAP server that will be used to populate the username field in Mattermost. This may be the same as the ID Attribute.
+
+```â€ID Attributeâ€: â€â€```
+
+The attribute in the LDAP server that will be used as a unique identifier in Mattermost.
+
+This is the attribute that will be used to create Mattermost accounts. It should be an LDAP attribute with a value that does not change, such as username or uid. If a user’s Id Attribute changes, it will create a new Mattermost account unassociated with their old one.
+
+This is also the value used to log in to Mattermost in the “LDAP Username†field on the sign in page. Normally this attribute is the same as the “Username Attribute†field above. If your team typically uses domain\username to sign in to other services with LDAP, you may choose to put domain\username in this field to maintain consistency between sites.
+
+```â€Query Timeout (seconds)â€: â€60â€```
+
+The timeout value for queries to the LDAP server. Increase this value if you are getting timeout errors caused by a slow LDAP server.
+
## Config.json Settings Not in System Console
System Console allows an IT Admin to update settings defined in `config.json`. However there are a number of settings in `config.json` unavailable in the System Console and require update from the file itself. We describe them here:
diff --git a/doc/install/LDAP-Setup.md b/doc/install/LDAP-Setup.md
new file mode 100644
index 000000000..a619e645e
--- /dev/null
+++ b/doc/install/LDAP-Setup.md
@@ -0,0 +1,34 @@
+## LDAP Setup
+
+LDAP authentication is available in the Enterprise version of Mattermost.
+### How to enable LDAP
+
+After installing Mattermost:
+
+1. Create a team using email authentication
+ - Note: The first account used to create a team will be the “System Administrator†account, used to configure settings for your Mattermost site
+ 3. Go to Main Menu (the three dots near your team name in the top left of your screen) > **System Console**
+ 4. Go to LDAP Settings
+ 5. Fill in the fields to set up Mattermost authentication with your LDAP server
+
+ After LDAP has been enabled, users should be able to go to your Mattermost site and sign in using their LDAP credentials. The “LDAP username†will be the attribute set in the “Id Attribute†field.
+
+ **Note: In the initial implementation of LDAP, if a user attribute changes on the LDAP server it will be updated the next time the user enters their credentials to log in to Mattermost. This includes if a user is made inactive or removed from an LDAP server. Synchronization with LDAP servers is planned in a future release.**
+
+### Switching System Administrator account to LDAP authentication
+
+If you would like to switch your System Administrator account to LDAP authentication, it is recommended you do the following:
+
+1. Create a new account using LDAP
+ - Note: If your LDAP credentials use the same email address as your System Administrator account, it is recommended you change the email on your System Administrator account by going to Main Menu -> Account Settings -> General -> Email. This will free up the email address so it can be used by the LDAP account.
+ 2. Sign in to your email based System Administrator account
+ 3. Navigate to the System Console
+ 4. Go to Teams -> Team Name -> Users, and find your new LDAP user account
+ 5. Promote your LDAP account to “System Administrator†using the dropdown menu beside the username
+ 6. Log in with your LDAP account
+ 7. Navigate to the System Console
+ 8. Go to Teams -> Team Name -> Users, and find your old email based System Administrator account
+ 9. Make the email account “Inactive†using the dropdown beside the username
+
+ **Note: If you make the email account inactive without promoting another account to System Administrator, you will lose your System Administrator privileges. This can be fixed by promoting another account to System Administrator using the command line.**
+
diff --git a/doc/install/Production-Debian.md b/doc/install/Production-Debian.md
index 13ff051a3..4b942a088 100644
--- a/doc/install/Production-Debian.md
+++ b/doc/install/Production-Debian.md
@@ -13,6 +13,7 @@ Note: This install guide has been generously contributed by the Mattermost commu
* ``` sudo apt-get update```
* ``` sudo apt-get upgrade```
+
## Set up Database Server
1. For the purposes of this guide we will assume this server has an IP address of 10.10.10.1
1. Install PostgreSQL 9.3+ (or MySQL 5.6+)
@@ -31,22 +32,36 @@ Note: This install guide has been generously contributed by the Mattermost commu
* ```postgre=# \q```
1. You can exit the postgres account by typing:
* ``` exit```
+1. Allow Postgres to listen on all assigned IP Addresses
+ * ```sudo vi /etc/postgresql/9.3/main/postgresql.conf```
+ * Uncomment 'listen_addresses' and change 'localhost' to '*'
+1. Alter pg_hba.conf to allow the mattermost server to talk to the postgres database
+ * ```sudo vi /etc/postgresql/9.3/main/pg_hba.conf```
+ * Add the following line to the 'IPv4 local connections'
+ * host all all 10.10.10.2/32 md5
+1. Reload Postgres database
+ * ```sudo /etc/init.d/postgresql reload```
+1. Attempt to connect with the new created user to verify everything looks good
+ * ```psql --host=10.10.10.1 --dbname=mattermost --username=mmuser --password```
+ * ```mattermost=> \q```
+
## Set up Mattermost Server
1. For the purposes of this guide we will assume this server has an IP address of 10.10.10.2
1. Download the latest Mattermost Server by typing:
- * ``` wget https://github.com/mattermost/platform/releases/download/v1.1.0/mattermost.tar.gz```
+ * ``` wget https://github.com/mattermost/platform/releases/download/v1.3.0/mattermost.tar.gz```
1. Install Mattermost under /opt
- * ``` cd /opt```
* Unzip the Mattermost Server by typing:
* ``` tar -xvzf mattermost.tar.gz```
-1. Create the storage directory for files. We assume you will have attached a large drive for storage of images and files. For this setup we will assume the directory is located at `/mattermost/data`.
+ * ``` sudo mv mattermost /opt```
+1. Create the storage directory for files. We assume you will have attached a large drive for storage of images and files. For this setup we will assume the directory is located at `/opt/mattermost/data`.
* Create the directory by typing:
* ``` sudo mkdir -p /opt/mattermost/data```
1. Create a system user and group called mattermost that will run this service
- * ``` useradd -r mattermost -U```
+ * ``` sudo useradd -r mattermost -U```
* Set the mattermost account as the directory owner by typing:
* ``` sudo chown -R mattermost:mattermost /opt/mattermost```
+ * ``` sudo chmod -R g+w /opt/mattermost```
* Add yourself to the mattermost group to ensure you can edit these files:
* ``` sudo usermod -aG mattermost USERNAME```
1. Configure Mattermost Server by editing the config.json file at /opt/mattermost/config
@@ -183,7 +198,7 @@ esac
exit 0
```
* Make sure that /etc/init.d/mattermost is executable
- * ``` chmod +x /etc/init.d/mattermost```
+ * ``` sudo chmod +x /etc/init.d/mattermost```
1. On reboot, systemd will generate a unit file from the headers in this init script and install it in `/run/systemd/generator.late/`
## Set up Nginx Server
@@ -207,7 +222,7 @@ exit 0
* Create a configuration for Mattermost
* ``` sudo touch /etc/nginx/sites-available/mattermost```
* Below is a sample configuration with the minimum settings required to configure Mattermost
- ```
+```
server {
server_name mattermost.example.com;
location / {
@@ -276,6 +291,8 @@ exit 0
gzip off;
proxy_set_header X-Forwarded-Ssl on;
```
+
+
## Finish Mattermost Server setup
1. Navigate to https://mattermost.example.com and create a team and user.
1. The first user in the system is automatically granted the `system_admin` role, which gives you access to the System Console.
diff --git a/doc/install/Production-RHEL6.md b/doc/install/Production-RHEL6.md
new file mode 100644
index 000000000..e3c6423c3
--- /dev/null
+++ b/doc/install/Production-RHEL6.md
@@ -0,0 +1,219 @@
+# Production Installation on Red Hat Enterprise Linux 6.6
+
+## Install Red Hat Enterprise Linux (x64) 6.6
+1. Set up 3 machines with RHEL with 2GB of RAM or more. The servers will be used for the Load Balancer, Mattermost (this must be x64 to use pre-built binaries), and Database.
+ - **Optional:** You can also use a single machine for all 3 components in this install guide, depending on the standards of your data center.
+2. Make sure the system is up to date with the most recent security patches.
+ * ``` sudo yum update```
+ * ``` sudo yum upgrade```
+
+## Set up Database Server
+1. For the purposes of this guide we will assume this server has an IP address of `10.10.10.1`
+ - **Optional:** if installing on the same machine substitute `10.10.10.1` with `127.0.0.1`
+1. Install PostgreSQL 9.4+ (or MySQL 5.6+)
+ * ``` sudo yum install http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-redhat94-9.4-1.noarch.rpm```
+ * ``` sudo yum install postgresql94-server postgresql94-contrib```
+ * ``` sudo service postgresql-9.4 initdb```
+ * ``` sudo chkconfig postgresql-9.4 on```
+ * ``` sudo service postgresql-9.4 start```
+1. PostgreSQL created a user account called `postgres`. You will need to log into that account with:
+ * ``` sudo -i -u postgres```
+1. You can get a PostgreSQL prompt by typing:
+ * ``` psql```
+1. Create the Mattermost database by typing:
+ * ```postgres=# CREATE DATABASE mattermost;```
+1. Create the Mattermost user by typing:
+ * ```postgres=# CREATE USER mmuser WITH PASSWORD 'mmuser_password';```
+1. Grant the user access to the Mattermost database by typing:
+ * ```postgres=# GRANT ALL PRIVILEGES ON DATABASE mattermost to mmuser;```
+1. You can exit out of PostgreSQL by typing:
+ * ```postgres=# \q```
+1. You can exit the Postgres account by typing:
+ * ``` exit```
+1. Allow Postgres to listen on all assigned IP Addresses:
+ * ```sudo vi /var/lib/pgsql/9.4/data/postgresql.conf```
+ * Uncomment 'listen_addresses' and change 'localhost' to '*'
+1. Alter `pg_hba.conf` to allow the Mattermost Server to talk to the Postgres database:
+ * ```sudo vi /var/lib/pgsql/9.4/data/pg_hba.conf```
+ * Add the following line to the 'IPv4 local connections':
+ * host all all 10.10.10.2/32 md5
+1. Reload Postgres database:
+ * ```sudo service postgresql-9.4 restart```
+1. Attempt to connect with the new created user to verify everything looks good:
+ * ```psql --host=10.10.10.1 --dbname=mattermost --username=mmuser --password```
+ * ```mattermost=> \q```
+
+
+## Set up Mattermost Server
+1. For the purposes of this guide we will assume this server has an IP address of `10.10.10.2`
+1. Download the latest Mattermost Server by typing:
+ * ``` wget https://github.com/mattermost/platform/releases/download/v1.3.0/mattermost.tar.gz```
+1. Install Mattermost under `/opt`
+ * Unzip the Mattermost Server by typing:
+ * ``` tar -xvzf mattermost.tar.gz```
+ * ``` sudo mv mattermost /opt```
+1. Create the storage directory for files. We assume you will have attached a large drive for storage of images and files. For this setup we will assume the directory is located at `/opt/mattermost/data`.
+ * Create the directory by typing:
+ * ``` sudo mkdir -p /opt/mattermost/data```
+1. Create a system user and group called mattermost that will run this service:
+ * ``` sudo useradd -r mattermost -U```
+ * Set the Mattermost account as the directory owner by typing:
+ * ``` sudo chown -R mattermost:mattermost /opt/mattermost```
+ * ``` sudo chmod -R g+w /opt/mattermost```
+ * Add yourself to the mattermost group to ensure you can edit these files:
+ * ``` sudo usermod -a -G mattermost USERNAME```
+1. Configure Mattermost Server by editing the `config.json` file at `/opt/mattermost/config`
+ * ``` cd /opt/mattermost/config```
+ * Edit the file by typing:
+ * ``` sudo vi config.json```
+ * replace `DriverName": "mysql"` with `DriverName": "postgres"`
+ * replace `"DataSource": "mmuser:mostest@tcp(dockerhost:3306)/mattermost_test?charset=utf8mb4,utf8"` with `"DataSource": "postgres://mmuser:mmuser_password@10.10.10.1:5432/mattermost?sslmode=disable&connect_timeout=10"`
+ * Optionally you may continue to edit configuration settings in `config.json` or use the System Console described in a later section to finish the configuration.
+1. Test the Mattermost Server
+ * ``` cd /opt/mattermost/bin```
+ * Run the Mattermost Server by typing:
+ * ``` sudo su mattermost```
+ * ``` ./platform```
+ * You should see a console log like `Server is listening on :8065` letting you know the service is running.
+ * Stop the server for now by typing `Ctrl-C`
+1. Setup Mattermost to use the Upstart daemon which handles supervision of the Mattermost process.
+ * ``` sudo touch /etc/init/mattermost.conf```
+ * ``` sudo vi /etc/init/mattermost.conf```
+ * Copy the following lines into `/etc/init/mattermost.conf`
+```
+start on runlevel [2345]
+stop on runlevel [016]
+respawn
+chdir /opt/mattermost
+exec bin/platform
+```
+ * You can manage the process by typing:
+ * ``` sudo start mattermost```
+ * Verify the service is running by typing:
+ * ``` curl http://10.10.10.2:8065```
+ * You should see a page titles *Mattermost - Signup*
+ * You can also stop the process by running the command ` sudo stop mattermost`, but we will skip this step for now.
+
+## Set up Nginx Server
+1. For the purposes of this guide we will assume this server has an IP address of `10.10.10.3`
+1. We use Nginx for proxying request to the Mattermost Server. The main benefits are:
+ * SSL termination
+ * HTTP to HTTPS redirect
+ * Port mapping :80 to :8065
+ * Standard request logs
+1. Install Nginx on RHEL with
+ * ``` sudo vi /etc/yum.repos.d/nginx.repo```
+ * Copy the below into the file
+```
+[nginx]
+name=nginx repo
+baseurl=http://nginx.org/packages/rhel/6/$basearch/
+gpgcheck=0
+enabled=1
+```
+ * ``` sudo yum install nginx.x86_64```
+ * ``` sudo service nginx start```
+ * ``` sudo chkconfig nginx on```
+1. Verify Nginx is running
+ * ``` curl http://10.10.10.3```
+ * You should see a *Welcome to nginx!* page
+1. Map a FQDN (fully qualified domain name) like **mattermost.example.com** to point to the Nginx server.
+1. Configure Nginx to proxy connections from the internet to the Mattermost Server
+ * Create a configuration for Mattermost
+ * ``` sudo touch /etc/nginx/conf.d/mattermost.conf```
+ * Below is a sample configuration with the minimum settings required to configure Mattermost
+```
+ server {
+ server_name mattermost.example.com;
+ location / {
+ client_max_body_size 50M;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Frame-Options SAMEORIGIN;
+ proxy_pass http://10.10.10.2:8065;
+ }
+ }
+```
+ * Remove the existing file with:
+ * ``` sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak```
+ * Restart Nginx by typing:
+ * ``` sudo service nginx restart```
+ * Verify you can see Mattermost thru the proxy by typing:
+ * ``` curl http://localhost```
+ * You should see a page titles *Mattermost - Signup*
+ * Not seeing the page? Look for errors with ``` sudo cat /var/log/audit/audit.log | grep nginx | grep denied```
+ * **Optional** if you're running on the same server as the Mattermost server and see 502 errors you may need to run `sudo setsebool -P httpd_can_network_connect true` because SELinux is preventing the connection
+
+## Set up Nginx with SSL (Recommended)
+1. You will need a SSL cert from a certificate authority.
+1. For simplicity we will generate a test certificate.
+ * ``` mkdir /top/mattermost/cert```
+ * ``` cd /top/mattermost/cert```
+ * ``` sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mattermost.key -out mattermost.crt```
+ * Input the following info
+```
+ Country Name (2 letter code) [AU]:US
+ State or Province Name (full name) [Some-State]:California
+ Locality Name (eg, city) []:Palo Alto
+ Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example LLC
+ Organizational Unit Name (eg, section) []:
+ Common Name (e.g. server FQDN or YOUR name) []:mattermost.example.com
+ Email Address []:admin@mattermost.example.com
+```
+1. Modify the file at `/etc/nginx/conf.d/mattermost.conf` and add the following lines
+ *
+```
+ server {
+ listen 80;
+ server_name mattermost.example.com;
+ return 301 https://$server_name$request_uri;
+ }
+
+ server {
+ listen 443 ssl;
+ server_name mattermost.example.com;
+
+ ssl on;
+ ssl_certificate /opt/mattermost/cert/mattermost.crt;
+ ssl_certificate_key /opt/mattermost/cert/mattermost.key;
+ ssl_session_timeout 5m;
+ ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
+ ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
+ ssl_prefer_server_ciphers on;
+ ssl_session_cache shared:SSL:10m;
+
+ # add to location / above
+ location / {
+ gzip off;
+ proxy_set_header X-Forwarded-Ssl on;
+```
+
+## Finish Mattermost Server setup
+1. Navigate to `https://mattermost.example.com` and create a team and user.
+1. The first user in the system is automatically granted the `system_admin` role, which gives you access to the System Console.
+1. From the `town-square` channel click the dropdown and choose the `System Console` option
+1. Update Email Settings. We recommend using an email sending service. The example below assumes AmazonSES.
+ * Set *Send Email Notifications* to true
+ * Set *Require Email Verification* to true
+ * Set *Feedback Name* to `No-Reply`
+ * Set *Feedback Email* to `mattermost@example.com`
+ * Set *SMTP Username* to `AFIADTOVDKDLGERR`
+ * Set *SMTP Password* to `DFKJoiweklsjdflkjOIGHLSDFJewiskdjf`
+ * Set *SMTP Server* to `email-smtp.us-east-1.amazonaws.com`
+ * Set *SMTP Port* to `465`
+ * Set *Connection Security* to `TLS`
+ * Save the Settings
+1. Update File Settings:
+ * Change *Local Directory Location* from `./data/` to `/opt/mattermost/data`
+1. Update Log Settings:
+ * Set *Log to The Console* to `false`
+1. Update Rate Limit Settings:
+ * Set *Vary By Remote Address* to false
+ * Set *Vary By HTTP Header* to X-Real-IP
+1. Feel free to modify other settings
+1. Restart the Mattermost Service by typing:
+ * ``` sudo restart mattermost```
diff --git a/doc/install/Production-RHEL7.md b/doc/install/Production-RHEL7.md
new file mode 100644
index 000000000..a479ec5ad
--- /dev/null
+++ b/doc/install/Production-RHEL7.md
@@ -0,0 +1,226 @@
+# Production Installation on Red Hat Enterprise Linux 7.1+
+
+## Install Red Hat Enterprise Linux (x64) 7.1+
+1. Set up 3 machines with RHEL with 2GB of RAM or more. The servers will be used for the Load Balancer, Mattermost (this must be x64 to use pre-built binaries), and Database.
+ - **Optional:** You can also use a single machine for all 3 components in this install guide, depending on the standards of your data center.
+2. Make sure the system is up to date with the most recent security patches.
+ * ``` sudo yum update```
+ * ``` sudo yum upgrade```
+
+## Set up Database Server
+1. For the purposes of this guide we will assume this server has an IP address of `10.10.10.1`
+ - **Optional:** if installing on the same machine substitute `10.10.10.1` with `127.0.0.1`
+1. Install PostgreSQL 9.4+ (or MySQL 5.6+)
+ * ``` sudo yum install http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-redhat94-9.4-1.noarch.rpm```
+ * ``` sudo yum install postgresql94-server postgresql94-contrib```
+ * ``` sudo /usr/pgsql-9.4/bin/postgresql94-setup initdb```
+ * ``` sudo systemctl enable postgresql-9.4.service```
+ * ``` sudo systemctl start postgresql-9.4.service```
+1. PostgreSQL created a user account called `postgres`. You will need to log into that account with:
+ * ``` sudo -i -u postgres```
+1. You can get a PostgreSQL prompt by typing:
+ * ``` psql```
+1. Create the Mattermost database by typing:
+ * ```postgres=# CREATE DATABASE mattermost;```
+1. Create the Mattermost user by typing:
+ * ```postgres=# CREATE USER mmuser WITH PASSWORD 'mmuser_password';```
+1. Grant the user access to the Mattermost database by typing:
+ * ```postgres=# GRANT ALL PRIVILEGES ON DATABASE mattermost to mmuser;```
+1. You can exit out of PostgreSQL by typing:
+ * ```postgres=# \q```
+1. You can exit the Postgres account by typing:
+ * ``` exit```
+1. Allow Postgres to listen on all assigned IP Addresses:
+ * ```sudo vi /var/lib/pgsql/9.4/data/postgresql.conf```
+ * Uncomment 'listen_addresses' and change 'localhost' to '*'
+1. Alter `pg_hba.conf` to allow the Mattermost Server to talk to the Postgres database:
+ * ```sudo vi /var/lib/pgsql/9.4/data/pg_hba.conf```
+ * Add the following line to the 'IPv4 local connections':
+ * host all all 10.10.10.2/32 md5
+1. Reload Postgres database:
+ * ```sudo systemctl reload postgresql-9.4.service```
+1. Attempt to connect with the new created user to verify everything looks good:
+ * ```psql --host=10.10.10.1 --dbname=mattermost --username=mmuser --password```
+ * ```mattermost=> \q```
+
+
+## Set up Mattermost Server
+1. For the purposes of this guide we will assume this server has an IP address of `10.10.10.2`
+1. Download the latest Mattermost Server by typing:
+ * ``` wget https://github.com/mattermost/platform/releases/download/v1.3.0/mattermost.tar.gz```
+1. Install Mattermost under `/opt`
+ * Unzip the Mattermost Server by typing:
+ * ``` tar -xvzf mattermost.tar.gz```
+ * ``` sudo mv mattermost /opt```
+1. Create the storage directory for files. We assume you will have attached a large drive for storage of images and files. For this setup we will assume the directory is located at `/opt/mattermost/data`.
+ * Create the directory by typing:
+ * ``` sudo mkdir -p /opt/mattermost/data```
+1. Create a system user and group called mattermost that will run this service:
+ * ``` sudo useradd -r mattermost -U```
+ * Set the Mattermost account as the directory owner by typing:
+ * ``` sudo chown -R mattermost:mattermost /opt/mattermost```
+ * ``` sudo chmod -R g+w /opt/mattermost```
+ * Add yourself to the mattermost group to ensure you can edit these files:
+ * ``` sudo usermod -aG mattermost USERNAME```
+1. Configure Mattermost Server by editing the `config.json` file at `/opt/mattermost/config`
+ * ``` cd /opt/mattermost/config```
+ * Edit the file by typing:
+ * ``` sudo vi config.json```
+ * replace `DriverName": "mysql"` with `DriverName": "postgres"`
+ * replace `"DataSource": "mmuser:mostest@tcp(dockerhost:3306)/mattermost_test?charset=utf8mb4,utf8"` with `"DataSource": "postgres://mmuser:mmuser_password@10.10.10.1:5432/mattermost?sslmode=disable&connect_timeout=10"`
+ * Optionally you may continue to edit configuration settings in `config.json` or use the System Console described in a later section to finish the configuration.
+1. Test the Mattermost Server
+ * ``` cd /opt/mattermost/bin```
+ * Run the Mattermost Server by typing:
+ * ``` ./platform```
+ * You should see a console log like `Server is listening on :8065` letting you know the service is running.
+ * Stop the server for now by typing `Ctrl-C`
+1. Set up Mattermost to use the systemd init daemon which handles supervision of the Mattermost process:
+ * ``` sudo touch /etc/systemd/system/mattermost.service```
+ * ``` sudo vi /etc/systemd/system/mattermost.service```
+ * Copy the following lines into `/etc/systemd/system/mattermost.service`
+```
+[Unit]
+Description=Mattermost
+After=syslog.target network.target
+
+[Service]
+Type=simple
+WorkingDirectory=/opt/mattermost/bin
+User=mattermost
+ExecStart=/opt/mattermost/bin/platform
+PIDFile=/var/spool/mattermost/pid/master.pid
+
+[Install]
+WantedBy=multi-user.target
+```
+ * Make sure the service is executable with ``` sudo chmod 664 /etc/systemd/system/mattermost.service```
+ * Reload the services with `sudo systemctl daemon-reload`
+ * Start Mattermost service with `sudo systemctl start mattermost.service`
+ * `sudo chkconfig mattermost on`
+ * Start server on reboot `sudo systemctl enable mattermost.service`
+
+
+## Set up Nginx Server
+1. For the purposes of this guide we will assume this server has an IP address of `10.10.10.3`
+1. We use Nginx for proxying request to the Mattermost Server. The main benefits are:
+ * SSL termination
+ * HTTP to HTTPS redirect
+ * Port mapping :80 to :8065
+ * Standard request logs
+1. Install Nginx on RHEL with
+ * ``` sudo vi /etc/yum.repos.d/nginx.repo```
+ * Copy the below into the file
+```
+[nginx]
+name=nginx repo
+baseurl=http://nginx.org/packages/rhel/7/$basearch/
+gpgcheck=0
+enabled=1
+```
+ * ``` sudo yum install nginx.x86_64```
+ * ``` sudo service nginx start```
+ * ``` sudo chkconfig nginx on```
+1. Verify Nginx is running
+ * ``` curl http://10.10.10.3```
+ * You should see a *Welcome to nginx!* page
+1. Map a FQDN (fully qualified domain name) like **mattermost.example.com** to point to the Nginx server.
+1. Configure Nginx to proxy connections from the internet to the Mattermost Server
+ * Create a configuration for Mattermost
+ * ``` sudo touch /etc/nginx/conf.d/mattermost.conf```
+ * Below is a sample configuration with the minimum settings required to configure Mattermost
+```
+ server {
+ server_name mattermost.example.com;
+ location / {
+ client_max_body_size 50M;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Frame-Options SAMEORIGIN;
+ proxy_pass http://10.10.10.2:8065;
+ }
+ }
+```
+ * Remove the existing file with:
+ * ``` sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak```
+ * Restart Nginx by typing:
+ * ``` sudo service nginx restart```
+ * Verify you can see Mattermost thru the proxy by typing:
+ * ``` curl http://localhost```
+ * You should see a page titles *Mattermost - Signup*
+ * Not seeing the page? Look for errors with ``` sudo cat /var/log/audit/audit.log | grep nginx | grep denied```
+ * **Optional** if you're running on the same server as the Mattermost server and see 502 errors you may need to run `sudo setsebool -P httpd_can_network_connect true` because SELinux is preventing the connection
+
+## Set up Nginx with SSL (Recommended)
+1. You will need a SSL cert from a certificate authority.
+1. For simplicity we will generate a test certificate.
+ * ``` mkdir /top/mattermost/cert```
+ * ``` cd /top/mattermost/cert```
+ * ``` sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mattermost.key -out mattermost.crt```
+ * Input the following info
+```
+ Country Name (2 letter code) [AU]:US
+ State or Province Name (full name) [Some-State]:California
+ Locality Name (eg, city) []:Palo Alto
+ Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example LLC
+ Organizational Unit Name (eg, section) []:
+ Common Name (e.g. server FQDN or YOUR name) []:mattermost.example.com
+ Email Address []:admin@mattermost.example.com
+```
+1. Modify the file at `/etc/nginx/conf.d/mattermost.conf` and add the following lines
+ *
+```
+ server {
+ listen 80;
+ server_name mattermost.example.com;
+ return 301 https://$server_name$request_uri;
+ }
+
+ server {
+ listen 443 ssl;
+ server_name mattermost.example.com;
+
+ ssl on;
+ ssl_certificate /opt/mattermost/cert/mattermost.crt;
+ ssl_certificate_key /opt/mattermost/cert/mattermost.key;
+ ssl_session_timeout 5m;
+ ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
+ ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
+ ssl_prefer_server_ciphers on;
+ ssl_session_cache shared:SSL:10m;
+
+ # add to location / above
+ location / {
+ gzip off;
+ proxy_set_header X-Forwarded-Ssl on;
+```
+
+## Finish Mattermost Server setup
+1. Navigate to `https://mattermost.example.com` and create a team and user.
+1. The first user in the system is automatically granted the `system_admin` role, which gives you access to the System Console.
+1. From the `town-square` channel click the dropdown and choose the `System Console` option
+1. Update Email Settings. We recommend using an email sending service. The example below assumes AmazonSES.
+ * Set *Send Email Notifications* to true
+ * Set *Require Email Verification* to true
+ * Set *Feedback Name* to `No-Reply`
+ * Set *Feedback Email* to `mattermost@example.com`
+ * Set *SMTP Username* to `AFIADTOVDKDLGERR`
+ * Set *SMTP Password* to `DFKJoiweklsjdflkjOIGHLSDFJewiskdjf`
+ * Set *SMTP Server* to `email-smtp.us-east-1.amazonaws.com`
+ * Set *SMTP Port* to `465`
+ * Set *Connection Security* to `TLS`
+ * Save the Settings
+1. Update File Settings:
+ * Change *Local Directory Location* from `./data/` to `/opt/mattermost/data`
+1. Update Log Settings:
+ * Set *Log to The Console* to `false`
+1. Update Rate Limit Settings:
+ * Set *Vary By Remote Address* to false
+ * Set *Vary By HTTP Header* to X-Real-IP
+1. Feel free to modify other settings
+1. Restart the Mattermost Service by typing:
+ * ``` sudo restart mattermost```
diff --git a/doc/install/Production-Ubuntu.md b/doc/install/Production-Ubuntu.md
index 1022f30cf..da3487f45 100644
--- a/doc/install/Production-Ubuntu.md
+++ b/doc/install/Production-Ubuntu.md
@@ -2,7 +2,8 @@
## Install Ubuntu Server (x64) 14.04 LTS
1. Set up 3 machines with Ubuntu 14.04 with 2GB of RAM or more. The servers will be used for the Load Balancer, Mattermost (this must be x64 to use pre-built binaries), and Database.
-1. Make sure the system is up to date with the most recent security patches.
+ - **Optional:** You can also use a single machine for all 3 components in this install guide, depending on the standards of your data center.
+2. Make sure the system is up to date with the most recent security patches.
* ``` sudo apt-get update```
* ``` sudo apt-get upgrade```
@@ -33,6 +34,9 @@
* host all all 10.10.10.2/32 md5
1. Reload Postgres database
* ```sudo /etc/init.d/postgresql reload```
+1. Attempt to connect with the new created user to verify everything looks good
+ * ```psql --host=10.10.10.1 --dbname=mattermost --username=mmuser --password```
+ * ```mattermost=> \q```
## Set up Mattermost Server
@@ -40,7 +44,7 @@
1. For the sake of making this guide simple we located the files at `/home/ubuntu/mattermost`. In the future we will give guidance for storing under `/opt`.
1. We have also elected to run the Mattermost Server as the `ubuntu` account for simplicity. We recommend setting up and running the service under a `mattermost` user account with limited permissions.
1. Download the latest Mattermost Server by typing:
- * ``` wget https://github.com/mattermost/platform/releases/download/v1.2.1/mattermost.tar.gz```
+ * ``` wget https://github.com/mattermost/platform/releases/download/v1.3.0/mattermost.tar.gz```
1. Unzip the Mattermost Server by typing:
* ``` tar -xvzf mattermost.tar.gz```
1. Create the storage directory for files. We assume you will have attached a large drive for storage of images and files. For this setup we will assume the directory is located at `/mattermost/data`.
@@ -61,7 +65,7 @@
* ``` ./platform```
* You should see a console log like `Server is listening on :8065` letting you know the service is running.
* Stop the server for now by typing `ctrl-c`
-1. Setup Mattermost to use the Ubuntu Upstart daemon which handles supervision of the Mattermost process.
+1. Setup Mattermost to use the Upstart daemon which handles supervision of the Mattermost process.
* ``` sudo touch /etc/init/mattermost.conf```
* ``` sudo vi /etc/init/mattermost.conf```
* Copy the following lines into `/etc/init/mattermost.conf`
@@ -72,7 +76,7 @@ respawn
chdir /home/ubuntu/mattermost
setuid ubuntu
exec bin/platform
-```
+```
* You can manage the process by typing:
* ``` sudo start mattermost```
* Verify the service is running by typing:
@@ -101,7 +105,7 @@ exec bin/platform
* Create a configuration for Mattermost
* ``` sudo touch /etc/nginx/sites-available/mattermost```
* Below is a sample configuration with the minimum settings required to configure Mattermost
- ```
+```
server {
server_name mattermost.example.com;
location / {
@@ -171,8 +175,9 @@ exec bin/platform
gzip off;
proxy_set_header X-Forwarded-Ssl on;
```
-## Finish Mattermost Server setup
+
+## Finish Mattermost Server setup
1. Navigate to https://mattermost.example.com and create a team and user.
1. The first user in the system is automatically granted the `system_admin` role, which gives you access to the System Console.
1. From the `town-square` channel click the dropdown and choose the `System Console` option
diff --git a/doc/process/release-process.md b/doc/process/release-process.md
index 294f5aa79..6e1cf6a77 100644
--- a/doc/process/release-process.md
+++ b/doc/process/release-process.md
@@ -9,114 +9,148 @@ Notes:
- T-minus counts are measured in "working days" (weekdays other than major holidays concurrent in US and Canada) prior to release day.
### (Code complete date of previous release) Beginning of release
-- Pre-work for the current release begins at the code complete date of the previous release. See "Code Complete" section below for details.
+
+Pre-work for the current release begins at the code complete date of the previous release. See "Code Complete" section below for details.
### (T-minus 10 working days) Cut-off for major features
-- No pull requests for major features should be submitted to the current release after this date (except if release manager decides to add "release-exception" label)
-- (Ops) Post this checklist in Release channel
-- (PM) Write compatibility updates for config.json and database changes [See example](https://github.com/mattermost/platform/blob/master/CHANGELOG.md#compatibility)
-- (PM) Confirm changes to config.json in compatibility section of Changelog are written back to [settings documentation](https://github.com/mattermost/platform/blob/master/doc/install/Configuration-Settings.md)
-- (Dev) Prioritize reviewing, updating, and merging of pull requests for current release until there are no more tickets in the [pull request queue](https://github.com/mattermost/platform/pulls) marked for the current release
-- (Leads) Meets to prioritize the final tickets of the release
- - Backlog is reviewed and major features that won’t make it are moved to next release
- - Triage tickets
- - Finalize roadmap for next release
- - Draft roadmap for release after next (used to prioritize design tasks)
-- (Marketing) Drafts marketing bullet points for next release based off of roadmap
-- (Marketing) Submits pull request for "Highlights" section of the Changelog
-- (Marketing) Notes date of announcements in release channel
-- (PM) Update [Upgrade Guide](https://github.com/mattermost/platform/blob/master/doc/install/Upgrade-Guide.md) for any steps needed to upgrade to new version
-- (PM) Prepare tickets for [cutting RC builds](https://mattermost.atlassian.net/browse/PLT-985), [creating the final release candidate](https://mattermost.atlassian.net/browse/PLT-986), [creating AMIs](https://mattermost.atlassian.net/browse/PLT-1213), and [testing GitLab RC with Mattermost](https://mattermost.atlassian.net/browse/PLT-1013)
-- (Stand-up) Each team member discusses worst bug (10-15s)
+No pull requests for major features should be submitted to the current release after this date (except if release manager decides to add "release-exception" label to Jira ticket).
+
+1. Logistics:
+ 1. Post this checklist in Release channel
+2. PM:
+ 1. Write compatibility updates for config.json and database changes [See example](https://github.com/mattermost/platform/blob/master/CHANGELOG.md#compatibility)
+  - Confirm changes to config.json in compatibility section of Changelog are written back to [settings documentation](https://github.com/mattermost/platform/blob/master/doc/install/Configuration-Settings.md)
+ - Update [Upgrade Guide](https://github.com/mattermost/platform/blob/master/doc/install/Upgrade-Guide.md) for any steps needed to upgrade to new version
+  - Prepare tickets for [cutting RC builds](https://mattermost.atlassian.net/browse/PLT-985), [creating the final release candidate](https://mattermost.atlassian.net/browse/PLT-986), [creating AMIs](https://mattermost.atlassian.net/browse/PLT-1213), and [testing GitLab RC with Mattermost](https://mattermost.atlassian.net/browse/PLT-1013)
+3. Dev:
+ 1. Prioritize reviewing, updating, and merging of pull requests for current release until there are no more tickets in the [pull request queue](https://github.com/mattermost/platform/pulls) marked for the current release
+4. Leads: Meet to prioritize the final tickets of the release
  
+ 1. Backlog is reviewed and major features that won’t make it are moved to next release
+  - Triage tickets
+  - Finalize roadmap for next release
+  - Draft roadmap for release after next (used to prioritize design tasks)
+5. Marketing:
+ 1. Drafts marketing bullet points for next release based off of roadmap
+ - Submits pull request for "Highlights" section of the Changelog
+ - Notes date of announcements in release channel
+6. Team:
+ 1. In Stand-up, each team member discusses worst bug (10-15s)
+
### (T-minus 8 working days) Feature Complete and Stabilization
-- No pull requests for features can be submitted to the current release after this date (except if release manager add "release-exception" label to Jira ticket)
-- (Ops) Post this checklist in Release channel
-- (Dev) Prioritize reviewing, updating, and merging of pull requests for current release until there are no more tickets in the [pull request queue](https://github.com/mattermost/platform/pulls) marked for the current release
-- **Stablization** period begins when all features for release have been committed.
- - During this period, only **bugs** can be committed to master. Non-bug pull requests are tagged for next version and wait until after a release candidate is cut to be committed to master
- - (RM) Exceptions can be made by release manager by setting priority to "Highest" and labelling "release-exception", which will add ticket to [Hotfix list for release candidate](https://mattermost.atlassian.net/issues/?filter=10204).
- - (PM) Review all [Severity 1 bugs (data loss or security)](https://mattermost.atlassian.net/secure/IssueNavigator.jspa?mode=hide&requestId=10600) to consider for adding to Hotfix list.
-- (PM) Complete documentation
- - (PM) Make Changelog PR with updates for latest feature additions and changes
- - (PM) Make Changelog PR with updates to contributors
- - (PM) Make NOTICE.txt PR for any new libraries added from dev, if not added already
- - (PM) Prioritize any developer documentation tickets
- - (PM) Draft [GitLab ticket](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/942) to take next Mattermost version in the Omnibus, but do not post until RC1 is cut
-- (PM) Check testing is complete
- - (PM) Works with Ops to check the [Quality Gate](https://github.com/mattermost/process/blob/master/release/quality-gates.md) for feature complete
- - (PM + Dev) Sign-off testing of their feature areas (i.e. PM/dev either signs-off that their area is well tested, or they flag that potential quality issues may exist)
-- **(Team) Feature Complete Meeting (10:15am PST)**
- - (PM) Leads review of Changelog
+
+**Stablization** period begins when all features for release have been committed. During this period, only **bugs** can be committed to master. Non-bug pull requests are tagged for next version, and are not committed to master until after a release candidate is cut.
+
+Exceptions can be made by the release manager setting priority to "Highest" and adding a "release-exception" label to the Jira ticket. This will add the ticket to the [hotfix list for release candidate](https://mattermost.atlassian.net/issues/?filter=10204).
+
+1. Logistics:
+ 1. Post this checklist in Release channel
+ - Update the channel header to reflect date
+ - Mail out mugs to any new contributors
+- Dev:
+ 1. Prioritize reviewing, updating, and merging of pull requests for current release until there are no more tickets in the [pull request queue](https://github.com/mattermost/platform/pulls) marked for the current release
+- PM:
+ 1. Review all [Severity 1 bugs (data loss or security)](https://mattermost.atlassian.net/secure/IssueNavigator.jspa?mode=hide&requestId=10600) to consider for adding to Hotfix list
+ - Update documentation:
+ 1. Make Changelog PR with updates for latest feature additions, known issues, and contributors
+ - Make NOTICE.txt PR for any new libraries added from dev, if not added already
+ - Prioritize any developer documentation tickets
+ - Draft [GitLab ticket](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/942) to take next Mattermost version in the Omnibus, but do not post until RC1 is cut
+ - Coordinate testing:
+ 1. Work with Ops to check the [Quality Gate](https://github.com/mattermost/process/blob/master/release/quality-gates.md) for feature complete
+ - Receive testing sign-off from feature area owners (i.e. PM/Dev either signs-off that their area is well tested, or flags potential quality issues that may exist)
+ - Check that Release Candidate Testing Spreadsheet is up to date
+- **(Team) Feature Complete Meeting (10:15am PST)**:
+ 1. (PM) Leads review of Changelog
- (Team) Each team member discusses worst bug (10-15s)
- (PM) Review feature list for next release
- - (Marketing) Share draft of marketing announce for next release
-- (Marketing) Communicates checklist of items needed by specific dates to write the blog post announce (e.g. screenshots, GIFs,
-- (Ops) Post Announce Date in Release channel + update the channel header to reflect date
-- (Ops) Mail out mugs to any new contributors
+ - (Marketing) Share draft of marketing bullet points for next release
+- Marketing:
+ 1. Communicate checklist of items needed by specific dates to write the blog post announce (e.g. screenshots, GIFs, documentation) and begins to write the blog post, tweet, and email for the release announcement
### (T-minus 5 working days) Code Complete and Release Candidate Cut
-- (Ops) Post this checklist in Release channel
-- (Ops) For the next release, create team meetings on Feature Complete and Code Complete dates
-- (PM) Remove "Under Development" notice for current release from Changelog on master
+
+1. Logistics:
+ 1. Post this checklist in Release channel
+ - For the next release, create team meetings on Feature Complete and Code Complete dates
+- PM:
+ 1. Remove "Under Development" notice for current release from Changelog on master
+ - Assign each area of the release testing spreadsheet to a team member
- **(Team) Code Complete Meeting (10:15am PST meeting)**
- - (Ops) Walks through each item of this checklist
- - (PM) Assigns each area of the release testing spreadsheet to a team member
+ 1. (Logistics) Walk through each item of this checklist
- (Dev) Last check of tickets that need to be merged before RC1
- (Team) Each team member discusses worst bug (10-15s)
- **Code Complete** is declared after meeting
- - (Dev) Prioritize reviewing, updating, and merging of pull requests for current release until there are no more tickets in the [pull request queue](https://github.com/mattermost/platform/pulls) marked for the current release
- - (Build) Master is tagged and branched and “Release Candidate 1″ is cut (e.g. 1.1.0-RC1) according to the [Release Candidate Checklist](https://github.com/mattermost/process/blob/master/release/create-release-candidate.md)
- - (PM) Create meta issue for regressions in GitHub (see [example](https://github.com/mattermost/platform/issues/574))
- - (PM) Include link to meta-issue in release notes of RC1
- - (PM) Tweet announcement that RC1 is ready (see [example](https://twitter.com/mattermosthq/status/664172166368264192))
- - (PM) Submit GitLab ticket to take next Mattermost version in the Omnibus
-
+- Dev:
+ 1. Prioritize reviewing, updating, and merging of pull requests for current release until there are no more tickets in the [pull request queue](https://github.com/mattermost/platform/pulls) marked for the current release
+- Build:
+ 1. Master is tagged and branched and “Release Candidate 1″ is cut (e.g. 1.1.0-RC1) according to the [Release Candidate Checklist](https://github.com/mattermost/process/blob/master/release/create-release-candidate.md)
+- PM:
+ 1.  Create meta issue for regressions in GitHub (see [example](https://github.com/mattermost/platform/issues/574))
+ - Include link to meta-issue in release notes of RC1
+ - Submit GitLab ticket to take next Mattermost version in the Omnibus
+- Marketing:
+ 1.  Tweet announcement that RC1 is ready (see [example](https://twitter.com/mattermosthq/status/664172166368264192))
+
### (T-minus 4 working days) Release Candidate Testing
-- (Team) Final testing is conducted by the team on the acceptance server and any issues found are filed
-- (Build) Tests upgrade from previous version to current version, following the [Upgrade Guide](https://github.com/mattermost/platform/blob/master/doc/install/Upgrade-Guide.md)
- - Database upgrade should be tested on both MySQL and Postgres
- - (Ops) Posts copy of the **Release Candidate Testing** checklist into Town Square in PRODUCTION
- - (Ops) Moves meeting, test and community channels over to the production version of RC, and posts in Town Square asking everyone to move communication over to the new team for testing purposes
- - (PM) Test feature areas and post bugs to Bugs/Issues in PRODUCTION
- - (Ops) Runs through general testing checklist on RC1 and post bugs to Bugs/Issues in PRODUCTION
- - (PM & DEV) Add **#p1** tag to any “Blocking†issue that looks like a hotfix to the RC is needed, and create a public ticket in Jira. Blocking issues are considered to be security issues, data loss issues, issues that break core functionality, or significantly impact aesthetics.
-- (PM) Updates the GitHub meta issue
- - (PM) Posts links to all issues found in RC as comments on the meta issue
- - (PM) Updates description to include approved fixes
- - (PM) Posts screenshot and link to final tickets for next RC to the Release room
- - (PM) Updates Release Notes with any new issues that will not be fixed for the current version
-- (PM & DEV leads) Triage hotfix candidates and decide on whether and when to cut next RC or final
-- (Dev) PRs for hotfixes made to release branch, and changes from release branch are merged into master
- - (Ops) Tests approved fixes on master
- - (Dev) Pushes next RC to acceptance after testing is complete and approved fixes merged
-- (Dev) pushes next RC to acceptance and announces in Town Square on PRODUCTION
- - (PM) closes the meta issue after the next RC is cut, and opens another ticket for new RC
-- (Ops) verifies each of the issues in meta ticket is fixed
- - (PM) If no blocking issues are found, PM, Dev and Ops signs off on the release
+1. Logistics:
+ 1. Post this checklist in Release channel
+ - Queue an agenda item for next team meeting for Release Process Kaizen/Q&A
+- Build:
+ 1. Test upgrade from previous version to current version, following the [Upgrade Guide](https://github.com/mattermost/platform/blob/master/doc/install/Upgrade-Guide.md)
+ - Database upgrade should be tested on both MySQL and Postgres
+- Team:
+ 1. Test assigned areas of the Release Candidate Testing Spreadsheet and file any bugs found in Jira
+ - Post a link to any "Blocking" issue that may need a hotfix to the RC in the Release room, with the **#p1** tag. If the issue is security related or contains confidential information, post the link in the Confidential Bugs private group. Blocking issues are considered to be security issues, data loss issues, issues that break core functionality, or significantly impact aesthetics.
+ - Triage hotfix candidates and decide on whether and when to cut next RC or final
+ - If no blocking issues are found, PM, Dev and Ops signs off on the release
+- PM:
+ 1. Post links to all issues found in RC as comments on the meta issue
+ - Update the meta issue description to include approved fixes
+ - Post screenshot and link to final tickets for next RC to the Release room
+ - Update Changelog “Known Issues†section with any significant issues that were found and not fixed for the final release
+- Dev:
+ 1. PRs for hotfixes made to release branch, and changes from release branch are merged into master
+- Logistics:
+ 1. For potentially destabilizing changes, test approved fixes on a spinmint private build
+- Build:
+ 1. Push next RC to acceptance after testing is complete and approved fixes merged, announces in Town Square on pre-release.mattermost.com/core
+- PM:
+ 1. Closes the meta issue after the next RC is cut, and opens another ticket for new RC
+- Ops:
+ 1. Verifies each of the issues in meta ticket is fixed
+
### (T-minus 2 working days) Release Build Cut
-- (Ops) Post this checklist in Release channel
-- (Build) Tags a new release (e.g. 1.1.0) and runs an official build which should be essentially identical to the last RC
- - (PM) Any significant issues that were found and not fixed for the final release are noted in the release notes
- - If an urgent and important issue needs to be addressed between major releases, a bug fix release (e.g. 1.1.1) may be created
-- (PM) Copy and paste the Release Notes from the Changelog to the Release Description
-- (PM) Update the mattermost.org/download page
-- (PM) Update the AMI links on mattermost.org/installation
-- (PM) Close final GitHub RC meta ticket
-- (Dev) Delete RCs after final version is shipped
-- (Marketing) Finalize marketing
- - (Marketing) Finalize mailchimp email blast
- - (Marketing) Finalize blog post and put on timer for release
- - (Marketing) Finalize tweet announcement
- - (Marketing) Finalize announcement on general mailing list
- - (Marketing) Finalize announcement for gitlab.mattermost.com
-
+
+The final release is cut. If an urgent and important issue needs to be addressed between major releases, a bug fix release (e.g. 1.1.1) may be created
+
+1. Logistics:
+ 1. Post this checklist in Release channel
+- Build:
+ 1. Tags a new release (e.g. 1.1.0) and runs an official build which should be essentially identical to the last RC
+ - Delete RCs after final version is shipped
+- PM:
+ 1. Copy and paste the Release Notes from the Changelog to the Release Description
+ - Update the mattermost.org/download page
+ - Update the AMI links on mattermost.org/download and mattermost.org/installation
+ - Close final GitHub RC meta ticket
+- Marketing:
+ 1. Finalize mailchimp email blast
+ - Finalize blog post and put on timer for release
+ - Finalize tweet announcement
+ - Finalize announcement on general mailing list
+ - Finalize announcement for gitlab.mattermost.com
+
### (T-minus 0 working days) Release Day
-- (Ops) Post this checklist in Release channel
-- (PM) Confirm marketing has been posted (animated GIFs, screenshots, mail announcement, Tweets, blog posts)
-- (PM) Close the release in Jira
-- (PM) Set header of next release as UNDER DEVELOPMENT in CHANGELOG on master
-- (Dev) Check if any libraries need to be updated for the next release, and if so bring up in weekly team meeting
-- (Ops) Post key dates for the next release in the header of the Release channel
-- (Ops) Queue an agenda item for next team meeting for Release Process Kaizen/Q&A
+
+1. Logistics:
+ 1. Post this checklist in Release channel
+ - Post key dates for the next release in the header of the Release channel
+- PM:
+ 1. Close the release in Jira
+ - Set header of next release as UNDER DEVELOPMENT in CHANGELOG on master
+- Dev:
+ 1. Check if any libraries need to be updated for the next release, and if so bring up in weekly team meeting
+- Marketing:
+ 1. Confirm marketing has been posted (animated GIFs, screenshots, mail announcement, tweets, blog posts)
diff --git a/einterfaces/ldap.go b/einterfaces/ldap.go
new file mode 100644
index 000000000..d4bfadc21
--- /dev/null
+++ b/einterfaces/ldap.go
@@ -0,0 +1,22 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package einterfaces
+
+import (
+ "github.com/mattermost/platform/model"
+)
+
+type LdapInterface interface {
+ DoLogin(team *model.Team, id string, password string) (*model.User, *model.AppError)
+}
+
+var theLdapInterface LdapInterface
+
+func RegisterLdapInterface(newInterface LdapInterface) {
+ theLdapInterface = newInterface
+}
+
+func GetLdapInterface() LdapInterface {
+ return theLdapInterface
+}
diff --git a/einterfaces/oauthproviders.go b/einterfaces/oauthproviders.go
new file mode 100644
index 000000000..c2ea8c72d
--- /dev/null
+++ b/einterfaces/oauthproviders.go
@@ -0,0 +1,29 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package einterfaces
+
+import (
+ "github.com/mattermost/platform/model"
+ "io"
+)
+
+type OauthProvider interface {
+ GetIdentifier() string
+ GetUserFromJson(data io.Reader) *model.User
+ GetAuthDataFromJson(data io.Reader) string
+}
+
+var oauthProviders = make(map[string]OauthProvider)
+
+func RegisterOauthProvider(name string, newProvider OauthProvider) {
+ oauthProviders[name] = newProvider
+}
+
+func GetOauthProvider(name string) OauthProvider {
+ provider, ok := oauthProviders[name]
+ if ok {
+ return provider
+ }
+ return nil
+}
diff --git a/mattermost.go b/mattermost.go
index da50a26c3..3d8ab736f 100644
--- a/mattermost.go
+++ b/mattermost.go
@@ -23,8 +23,16 @@ import (
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
"github.com/mattermost/platform/web"
+
+ // Plugins
+ _ "github.com/mattermost/platform/model/gitlab"
+
+ // Enterprise Deps
+ _ "github.com/go-ldap/ldap"
)
+//ENTERPRISE_IMPORTS
+
var flagCmdCreateTeam bool
var flagCmdCreateUser bool
var flagCmdAssignRole bool
@@ -51,6 +59,7 @@ func main() {
pwd, _ := os.Getwd()
l4g.Info("Current version is %v (%v/%v/%v)", model.CurrentVersion, model.BuildNumber, model.BuildDate, model.BuildHash)
+ l4g.Info("Enterprise Enabled: %t", model.BuildEnterpriseReady)
l4g.Info("Current working directory is %v", pwd)
l4g.Info("Loaded config file from %v", utils.FindConfigFile(flagConfigFile))
@@ -112,6 +121,7 @@ func runSecurityAndDiagnosticsJobAndForget() {
v.Set(utils.PROP_DIAGNOSTIC_ID, utils.CfgDiagnosticId)
v.Set(utils.PROP_DIAGNOSTIC_BUILD, model.CurrentVersion+"."+model.BuildNumber)
+ v.Set(utils.PROP_DIAGNOSTIC_ENTERPRISE_READY, model.BuildEnterpriseReady)
v.Set(utils.PROP_DIAGNOSTIC_DATABASE, utils.Cfg.SqlSettings.DriverName)
v.Set(utils.PROP_DIAGNOSTIC_OS, runtime.GOOS)
v.Set(utils.PROP_DIAGNOSTIC_CATEGORY, utils.VAL_DIAGNOSTIC_CATEGORY_DEFAULT)
@@ -283,10 +293,6 @@ func cmdCreateUser() {
os.Exit(1)
}
- c := &api.Context{}
- c.RequestId = model.NewId()
- c.IpAddress = "cmd_line"
-
var team *model.Team
user := &model.User{}
user.Email = flagEmail
@@ -302,10 +308,10 @@ func cmdCreateUser() {
user.TeamId = team.Id
}
- api.CreateUser(c, team, user)
- if c.Err != nil {
- if c.Err.Message != "An account with that email already exists." {
- l4g.Error("%v", c.Err)
+ _, err := api.CreateUser(team, user)
+ if err != nil {
+ if err.Message != "An account with that email already exists." {
+ l4g.Error("%v", err)
flushLogAndExit(1)
}
}
@@ -320,6 +326,7 @@ func cmdVersion() {
fmt.Fprintln(os.Stderr, "Build Number: "+model.BuildNumber)
fmt.Fprintln(os.Stderr, "Build Date: "+model.BuildDate)
fmt.Fprintln(os.Stderr, "Build Hash: "+model.BuildHash)
+ fmt.Fprintln(os.Stderr, "Build Enterprise Ready: "+model.BuildEnterpriseReady)
os.Exit(0)
}
diff --git a/model/client.go b/model/client.go
index d3f76817d..b9b97dedc 100644
--- a/model/client.go
+++ b/model/client.go
@@ -717,7 +717,7 @@ func (c *Client) GetFileInfo(url string) (*Result, *AppError) {
return nil, AppErrorFromJson(rp.Body)
} else {
return &Result{rp.Header.Get(HEADER_REQUEST_ID),
- rp.Header.Get(HEADER_ETAG_SERVER), MapFromJson(rp.Body)}, nil
+ rp.Header.Get(HEADER_ETAG_SERVER), FileInfoFromJson(rp.Body)}, nil
}
}
diff --git a/model/config.go b/model/config.go
index 06cb9829e..38ef81a85 100644
--- a/model/config.go
+++ b/model/config.go
@@ -20,6 +20,7 @@ const (
DATABASE_DRIVER_POSTGRES = "postgres"
SERVICE_GITLAB = "gitlab"
+ SERVICE_GOOGLE = "google"
)
type ServiceSettings struct {
@@ -133,6 +134,26 @@ type TeamSettings struct {
EnableTeamListing *bool
}
+type LdapSettings struct {
+ // Basic
+ Enable *bool
+ LdapServer *string
+ LdapPort *int
+ BaseDN *string
+ BindUsername *string
+ BindPassword *string
+
+ // User Mapping
+ FirstNameAttribute *string
+ LastNameAttribute *string
+ EmailAttribute *string
+ UsernameAttribute *string
+ IdAttribute *string
+
+ // Advansed
+ QueryTimeout *int
+}
+
type Config struct {
ServiceSettings ServiceSettings
TeamSettings TeamSettings
@@ -144,6 +165,8 @@ type Config struct {
PrivacySettings PrivacySettings
SupportSettings SupportSettings
GitLabSettings SSOSettings
+ GoogleSettings SSOSettings
+ LdapSettings LdapSettings
}
func (o *Config) ToJson() string {
@@ -156,8 +179,11 @@ func (o *Config) ToJson() string {
}
func (o *Config) GetSSOService(service string) *SSOSettings {
- if service == SERVICE_GITLAB {
+ switch service {
+ case SERVICE_GITLAB:
return &o.GitLabSettings
+ case SERVICE_GOOGLE:
+ return &o.GoogleSettings
}
return nil
@@ -251,6 +277,21 @@ func (o *Config) SetDefaults() {
o.SupportSettings.SupportEmail = new(string)
*o.SupportSettings.SupportEmail = "feedback@mattermost.com"
}
+
+ if o.LdapSettings.LdapPort == nil {
+ o.LdapSettings.LdapPort = new(int)
+ *o.LdapSettings.LdapPort = 389
+ }
+
+ if o.LdapSettings.QueryTimeout == nil {
+ o.LdapSettings.QueryTimeout = new(int)
+ *o.LdapSettings.QueryTimeout = 60
+ }
+
+ if o.LdapSettings.Enable == nil {
+ o.LdapSettings.Enable = new(bool)
+ *o.LdapSettings.Enable = false
+ }
}
func (o *Config) IsValid() *AppError {
diff --git a/model/file_info.go b/model/file_info.go
new file mode 100644
index 000000000..741b4e55d
--- /dev/null
+++ b/model/file_info.go
@@ -0,0 +1,72 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+import (
+ "bytes"
+ "encoding/json"
+ "image/gif"
+ "io"
+ "mime"
+ "path/filepath"
+)
+
+type FileInfo struct {
+ Filename string `json:"filename"`
+ Size int `json:"size"`
+ Extension string `json:"extension"`
+ MimeType string `json:"mime_type"`
+ HasPreviewImage bool `json:"has_preview_image"`
+}
+
+func GetInfoForBytes(filename string, data []byte) (*FileInfo, *AppError) {
+ size := len(data)
+
+ var mimeType string
+ extension := filepath.Ext(filename)
+ isImage := IsFileExtImage(extension)
+ if isImage {
+ mimeType = GetImageMimeType(extension)
+ } else {
+ mimeType = mime.TypeByExtension(extension)
+ }
+
+ hasPreviewImage := isImage
+ if mimeType == "image/gif" {
+ // just show the gif itself instead of a preview image for animated gifs
+ if gifImage, err := gif.DecodeAll(bytes.NewReader(data)); err != nil {
+ return nil, NewAppError("GetInfoForBytes", "Could not decode gif.", "filename="+filename)
+ } else {
+ hasPreviewImage = len(gifImage.Image) == 1
+ }
+ }
+
+ return &FileInfo{
+ Filename: filename,
+ Size: size,
+ Extension: extension[1:],
+ MimeType: mimeType,
+ HasPreviewImage: hasPreviewImage,
+ }, nil
+}
+
+func (info *FileInfo) ToJson() string {
+ b, err := json.Marshal(info)
+ if err != nil {
+ return ""
+ } else {
+ return string(b)
+ }
+}
+
+func FileInfoFromJson(data io.Reader) *FileInfo {
+ decoder := json.NewDecoder(data)
+
+ var info FileInfo
+ if err := decoder.Decode(&info); err != nil {
+ return nil
+ } else {
+ return &info
+ }
+}
diff --git a/model/file_info_test.go b/model/file_info_test.go
new file mode 100644
index 000000000..ecf0d509c
--- /dev/null
+++ b/model/file_info_test.go
@@ -0,0 +1,76 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+import (
+ "encoding/base64"
+ "io/ioutil"
+ "testing"
+)
+
+func TestGetInfoForBytes(t *testing.T) {
+ fakeFile := make([]byte, 1000)
+
+ if info, err := GetInfoForBytes("file.txt", fakeFile); err != nil {
+ t.Fatal(err)
+ } else if info.Filename != "file.txt" {
+ t.Fatalf("Got incorrect filename: %v", info.Filename)
+ } else if info.Size != 1000 {
+ t.Fatalf("Got incorrect size: %v", info.Size)
+ } else if info.Extension != "txt" {
+ t.Fatalf("Git incorrect file extension: %v", info.Extension)
+ } else if info.MimeType != "text/plain; charset=utf-8" {
+ t.Fatalf("Got incorrect mime type: %v", info.MimeType)
+ } else if info.HasPreviewImage {
+ t.Fatalf("Got HasPreviewImage = true for non-image file")
+ }
+
+ if info, err := GetInfoForBytes("file.png", fakeFile); err != nil {
+ t.Fatal(err)
+ } else if info.Filename != "file.png" {
+ t.Fatalf("Got incorrect filename: %v", info.Filename)
+ } else if info.Size != 1000 {
+ t.Fatalf("Got incorrect size: %v", info.Size)
+ } else if info.Extension != "png" {
+ t.Fatalf("Git incorrect file extension: %v", info.Extension)
+ } else if info.MimeType != "image/png" {
+ t.Fatalf("Got incorrect mime type: %v", info.MimeType)
+ } else if !info.HasPreviewImage {
+ t.Fatalf("Got HasPreviewImage = false for image")
+ }
+
+ // base 64 encoded version of handtinywhite.gif from http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever
+ gifFile, _ := base64.StdEncoding.DecodeString("R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=")
+ if info, err := GetInfoForBytes("handtinywhite.gif", gifFile); err != nil {
+ t.Fatal(err)
+ } else if info.Filename != "handtinywhite.gif" {
+ t.Fatalf("Got incorrect filename: %v", info.Filename)
+ } else if info.Size != 35 {
+ t.Fatalf("Got incorrect size: %v", info.Size)
+ } else if info.Extension != "gif" {
+ t.Fatalf("Git incorrect file extension: %v", info.Extension)
+ } else if info.MimeType != "image/gif" {
+ t.Fatalf("Got incorrect mime type: %v", info.MimeType)
+ } else if !info.HasPreviewImage {
+ t.Fatalf("Got HasPreviewImage = false for static gif")
+ }
+
+ animatedGifFile, err := ioutil.ReadFile("../web/static/images/testgif.gif")
+ if err != nil {
+ t.Fatalf("Failed to load testgif.gif: %v", err.Error())
+ }
+ if info, err := GetInfoForBytes("testgif.gif", animatedGifFile); err != nil {
+ t.Fatal(err)
+ } else if info.Filename != "testgif.gif" {
+ t.Fatalf("Got incorrect filename: %v", info.Filename)
+ } else if info.Size != 38689 {
+ t.Fatalf("Got incorrect size: %v", info.Size)
+ } else if info.Extension != "gif" {
+ t.Fatalf("Git incorrect file extension: %v", info.Extension)
+ } else if info.MimeType != "image/gif" {
+ t.Fatalf("Got incorrect mime type: %v", info.MimeType)
+ } else if info.HasPreviewImage {
+ t.Fatalf("Got HasPreviewImage = true for animated gif")
+ }
+}
diff --git a/model/gitlab.go b/model/gitlab/gitlab.go
index 2a8756807..8b96c64f6 100644
--- a/model/gitlab.go
+++ b/model/gitlab/gitlab.go
@@ -1,10 +1,12 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-package model
+package oauthgitlab
import (
"encoding/json"
+ "github.com/mattermost/platform/einterfaces"
+ "github.com/mattermost/platform/model"
"io"
"strconv"
"strings"
@@ -14,6 +16,9 @@ const (
USER_AUTH_SERVICE_GITLAB = "gitlab"
)
+type GitLabProvider struct {
+}
+
type GitLabUser struct {
Id int64 `json:"id"`
Username string `json:"username"`
@@ -22,13 +27,18 @@ type GitLabUser struct {
Name string `json:"name"`
}
-func UserFromGitLabUser(glu *GitLabUser) *User {
- user := &User{}
+func init() {
+ provider := &GitLabProvider{}
+ einterfaces.RegisterOauthProvider(USER_AUTH_SERVICE_GITLAB, provider)
+}
+
+func userFromGitLabUser(glu *GitLabUser) *model.User {
+ user := &model.User{}
username := glu.Username
if username == "" {
username = glu.Login
}
- user.Username = CleanUsername(username)
+ user.Username = model.CleanUsername(username)
splitName := strings.Split(glu.Name, " ")
if len(splitName) == 2 {
user.FirstName = splitName[0]
@@ -46,7 +56,7 @@ func UserFromGitLabUser(glu *GitLabUser) *User {
return user
}
-func GitLabUserFromJson(data io.Reader) *GitLabUser {
+func gitLabUserFromJson(data io.Reader) *GitLabUser {
decoder := json.NewDecoder(data)
var glu GitLabUser
err := decoder.Decode(&glu)
@@ -57,6 +67,18 @@ func GitLabUserFromJson(data io.Reader) *GitLabUser {
}
}
-func (glu *GitLabUser) GetAuthData() string {
+func (glu *GitLabUser) getAuthData() string {
return strconv.FormatInt(glu.Id, 10)
}
+
+func (m *GitLabProvider) GetIdentifier() string {
+ return USER_AUTH_SERVICE_GITLAB
+}
+
+func (m *GitLabProvider) GetUserFromJson(data io.Reader) *model.User {
+ return userFromGitLabUser(gitLabUserFromJson(data))
+}
+
+func (m *GitLabProvider) GetAuthDataFromJson(data io.Reader) string {
+ return gitLabUserFromJson(data).getAuthData()
+}
diff --git a/model/version.go b/model/version.go
index 5e41a28d1..142ddb371 100644
--- a/model/version.go
+++ b/model/version.go
@@ -27,6 +27,7 @@ var CurrentVersion string = versions[0]
var BuildNumber = "_BUILD_NUMBER_"
var BuildDate = "_BUILD_DATE_"
var BuildHash = "_BUILD_HASH_"
+var BuildEnterpriseReady = "_BUILD_ENTERPRISE_READY_"
func SplitVersion(version string) (int64, int64, int64) {
parts := strings.Split(version, ".")
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index d19135b64..82a2ccd05 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -540,7 +540,7 @@ func (us SqlUserStore) GetTotalActiveUsersCount() StoreChannel {
go func() {
result := StoreResult{}
- time := model.GetMillis() - (1000 * 60 * 60 * 12)
+ time := model.GetMillis() - (1000 * 60 * 60 * 24)
if count, err := us.GetReplica().SelectInt("SELECT COUNT(Id) FROM Users WHERE LastActivityAt > :Time", map[string]interface{}{"Time": time}); err != nil {
result.Err = model.NewAppError("SqlUserStore.GetTotalActiveUsersCount", "We could not count the users", err.Error())
diff --git a/utils/config.go b/utils/config.go
index 3f451b88a..18bd15241 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -180,6 +180,7 @@ func getClientConfig(c *model.Config) map[string]string {
props["BuildNumber"] = model.BuildNumber
props["BuildDate"] = model.BuildDate
props["BuildHash"] = model.BuildHash
+ props["BuildEnterpriseReady"] = model.BuildEnterpriseReady
props["SiteName"] = c.TeamSettings.SiteName
props["EnableTeamCreation"] = strconv.FormatBool(c.TeamSettings.EnableTeamCreation)
@@ -203,6 +204,7 @@ func getClientConfig(c *model.Config) map[string]string {
props["FeedbackEmail"] = c.EmailSettings.FeedbackEmail
props["EnableSignUpWithGitLab"] = strconv.FormatBool(c.GitLabSettings.Enable)
+ props["EnableSignUpWithGoogle"] = strconv.FormatBool(c.GoogleSettings.Enable)
props["ShowEmailAddress"] = strconv.FormatBool(c.PrivacySettings.ShowEmailAddress)
@@ -217,5 +219,7 @@ func getClientConfig(c *model.Config) map[string]string {
props["ProfileHeight"] = fmt.Sprintf("%v", c.FileSettings.ProfileHeight)
props["ProfileWidth"] = fmt.Sprintf("%v", c.FileSettings.ProfileWidth)
+ props["EnableLdap"] = strconv.FormatBool(*c.LdapSettings.Enable)
+
return props
}
diff --git a/utils/diagnostic.go b/utils/diagnostic.go
index fd24c2c25..ee199cb35 100644
--- a/utils/diagnostic.go
+++ b/utils/diagnostic.go
@@ -15,6 +15,7 @@ const (
PROP_DIAGNOSTIC_CATEGORY = "c"
VAL_DIAGNOSTIC_CATEGORY_DEFAULT = "d"
PROP_DIAGNOSTIC_BUILD = "b"
+ PROP_DIAGNOSTIC_ENTERPRISE_READY = "be"
PROP_DIAGNOSTIC_DATABASE = "db"
PROP_DIAGNOSTIC_OS = "os"
PROP_DIAGNOSTIC_USER_COUNT = "uc"
diff --git a/web/react/components/about_build_modal.jsx b/web/react/components/about_build_modal.jsx
index 6962876d4..f71e1c9ab 100644
--- a/web/react/components/about_build_modal.jsx
+++ b/web/react/components/about_build_modal.jsx
@@ -33,10 +33,14 @@ export default class AboutBuildModal extends React.Component {
<div className='col-sm-3 info__label'>{'Build Date:'}</div>
<div className='col-sm-9'>{config.BuildDate}</div>
</div>
- <div className='row'>
+ <div className='row form-group'>
<div className='col-sm-3 info__label'>{'Build Hash:'}</div>
<div className='col-sm-9'>{config.BuildHash}</div>
</div>
+ <div className='row'>
+ <div className='col-sm-3 info__label'>{'Enterprise Ready:'}</div>
+ <div className='col-sm-9'>{config.BuildEnterpriseReady}</div>
+ </div>
</Modal.Body>
<Modal.Footer>
<button
@@ -59,4 +63,4 @@ AboutBuildModal.defaultProps = {
AboutBuildModal.propTypes = {
show: React.PropTypes.bool.isRequired,
onModalDismissed: React.PropTypes.func.isRequired
-}; \ No newline at end of file
+};
diff --git a/web/react/components/admin_console/admin_controller.jsx b/web/react/components/admin_console/admin_controller.jsx
index e587c4f84..32b2e9bb7 100644
--- a/web/react/components/admin_console/admin_controller.jsx
+++ b/web/react/components/admin_console/admin_controller.jsx
@@ -21,6 +21,7 @@ import ServiceSettingsTab from './service_settings.jsx';
import LegalAndSupportSettingsTab from './legal_and_support_settings.jsx';
import TeamUsersTab from './team_users.jsx';
import TeamAnalyticsTab from './team_analytics.jsx';
+import LdapSettingsTab from './ldap_settings.jsx';
export default class AdminController extends React.Component {
constructor(props) {
@@ -151,6 +152,8 @@ export default class AdminController extends React.Component {
tab = <ServiceSettingsTab config={this.state.config} />;
} else if (this.state.selected === 'legal_and_support_settings') {
tab = <LegalAndSupportSettingsTab config={this.state.config} />;
+ } else if (this.state.selected === 'ldap_settings') {
+ tab = <LdapSettingsTab config={this.state.config} />;
} else if (this.state.selected === 'team_users') {
if (this.state.teams) {
tab = <TeamUsersTab team={this.state.teams[this.state.selectedTeam]} />;
diff --git a/web/react/components/admin_console/admin_sidebar.jsx b/web/react/components/admin_console/admin_sidebar.jsx
index da445da37..1279f4d22 100644
--- a/web/react/components/admin_console/admin_sidebar.jsx
+++ b/web/react/components/admin_console/admin_sidebar.jsx
@@ -334,4 +334,4 @@ AdminSidebar.propTypes = {
selected: React.PropTypes.string,
selectedTeam: React.PropTypes.string,
selectTab: React.PropTypes.func
-}; \ No newline at end of file
+};
diff --git a/web/react/components/admin_console/ldap_settings.jsx b/web/react/components/admin_console/ldap_settings.jsx
new file mode 100644
index 000000000..6e3da2f72
--- /dev/null
+++ b/web/react/components/admin_console/ldap_settings.jsx
@@ -0,0 +1,394 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import * as Client from '../../utils/client.jsx';
+import * as AsyncClient from '../../utils/async_client.jsx';
+
+const DEFAULT_LDAP_PORT = 389;
+const DEFAULT_QUERY_TIMEOUT = 60;
+
+export default class LdapSettings extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+ this.handleChange = this.handleChange.bind(this);
+ this.handleEnable = this.handleEnable.bind(this);
+ this.handleDisable = this.handleDisable.bind(this);
+
+ this.state = {
+ saveNeeded: false,
+ serverError: null,
+ enable: this.props.config.LdapSettings.Enable
+ };
+ }
+ handleChange() {
+ this.setState({saveNeeded: true});
+ }
+ handleEnable() {
+ this.setState({saveNeeded: true, enable: true});
+ }
+ handleDisable() {
+ this.setState({saveNeeded: true, enable: false});
+ }
+ handleSubmit(e) {
+ e.preventDefault();
+ $('#save-button').button('loading');
+
+ const config = this.props.config;
+ config.LdapSettings.Enable = this.refs.Enable.checked;
+ config.LdapSettings.LdapServer = this.refs.LdapServer.value.trim();
+
+ let LdapPort = DEFAULT_LDAP_PORT;
+ if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.LdapPort).value, 10))) {
+ LdapPort = parseInt(ReactDOM.findDOMNode(this.refs.LdapPort).value, 10);
+ }
+ config.LdapSettings.LdapPort = LdapPort;
+
+ config.LdapSettings.BaseDN = this.refs.BaseDN.value.trim();
+ config.LdapSettings.BindUsername = this.refs.BindUsername.value.trim();
+ config.LdapSettings.BindPassword = this.refs.BindPassword.value.trim();
+ config.LdapSettings.FirstNameAttribute = this.refs.FirstNameAttribute.value.trim();
+ config.LdapSettings.LastNameAttribute = this.refs.LastNameAttribute.value.trim();
+ config.LdapSettings.EmailAttribute = this.refs.EmailAttribute.value.trim();
+ config.LdapSettings.UsernameAttribute = this.refs.UsernameAttribute.value.trim();
+ config.LdapSettings.IdAttribute = this.refs.IdAttribute.value.trim();
+
+ let QueryTimeout = DEFAULT_QUERY_TIMEOUT;
+ if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.QueryTimeout).value, 10))) {
+ QueryTimeout = parseInt(ReactDOM.findDOMNode(this.refs.QueryTimeout).value, 10);
+ }
+ config.LdapSettings.QueryTimeout = QueryTimeout;
+
+ Client.saveConfig(
+ config,
+ () => {
+ AsyncClient.getConfig();
+ this.setState({
+ serverError: null,
+ saveNeeded: false
+ });
+ $('#save-button').button('reset');
+ },
+ (err) => {
+ this.setState({
+ serverError: err.message,
+ saveNeeded: true
+ });
+ $('#save-button').button('reset');
+ }
+ );
+ }
+ render() {
+ let serverError = '';
+ if (this.state.serverError) {
+ serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
+ }
+
+ let saveClass = 'btn';
+ if (this.state.saveNeeded) {
+ saveClass = 'btn btn-primary';
+ }
+
+ return (
+ <div className='wrapper--fixed'>
+ <div className='banner'>
+ <div className='banner__content'>
+ <h4 className='banner__heading'>{'Note:'}</h4>
+ <p>{'If a user attribute changes on the LDAP server it will be updated the next time the user enters their credentials to log in to Mattermost. This includes if a user is made inactive or removed from an LDAP server. Synchronization with LDAP servers is planned in a future release.'}</p>
+ </div>
+ </div>
+ <h3>{'LDAP Settings'}</h3>
+ <form
+ className='form-horizontal'
+ role='form'
+ >
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='Enable'
+ >
+ {'Enable Login With LDAP:'}
+ </label>
+ <div className='col-sm-8'>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='Enable'
+ value='true'
+ ref='Enable'
+ defaultChecked={this.props.config.LdapSettings.Enable}
+ onChange={this.handleEnable}
+ />
+ {'true'}
+ </label>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='Enable'
+ value='false'
+ defaultChecked={!this.props.config.LdapSettings.Enable}
+ onChange={this.handleDisable}
+ />
+ {'false'}
+ </label>
+ <p className='help-text'>{'When true, Mattermost allows login using LDAP'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='LdapServer'
+ >
+ {'LDAP Server:'}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='text'
+ className='form-control'
+ id='LdapServer'
+ ref='LdapServer'
+ placeholder='Ex "10.0.0.23"'
+ defaultValue={this.props.config.LdapSettings.LdapServer}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'The domain or IP address of LDAP server.'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='LdapPort'
+ >
+ {'LDAP Port:'}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='number'
+ className='form-control'
+ id='LdapPort'
+ ref='LdapPort'
+ placeholder='Ex "389"'
+ defaultValue={this.props.config.LdapSettings.LdapPort}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'The port Mattermost will use to connect to the LDAP server. Default is 389.'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='BaseDN'
+ >
+ {'BaseDN:'}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='text'
+ className='form-control'
+ id='BaseDN'
+ ref='BaseDN'
+ placeholder='Ex "dc=mydomain,dc=com"'
+ defaultValue={this.props.config.LdapSettings.BaseDN}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'The Base DN is the Distinguished Name of the location where Mattermost should start its search for users in the LDAP tree.'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='BindUsername'
+ >
+ {'Bind Username:'}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='text'
+ className='form-control'
+ id='BindUsername'
+ ref='BindUsername'
+ placeholder=''
+ defaultValue={this.props.config.LdapSettings.BindUsername}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'The username used to perform the LDAP search. This should typically be an account created specifically for use with Mattermost. It should have access limited to read the portion of the LDAP tree specified in the BaseDN field.'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='BindPassword'
+ >
+ {'Bind Password:'}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='password'
+ className='form-control'
+ id='BindPassword'
+ ref='BindPassword'
+ placeholder=''
+ defaultValue={this.props.config.LdapSettings.BindPassword}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'Password of the user given in "Bind Username".'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='FirstNameAttribute'
+ >
+ {'First Name Attrubute'}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='text'
+ className='form-control'
+ id='FirstNameAttribute'
+ ref='FirstNameAttribute'
+ placeholder='Ex "givenName"'
+ defaultValue={this.props.config.LdapSettings.FirstNameAttribute}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'The attribute in the LDAP server that will be used to populate the first name of users in Mattermost.'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='LastNameAttribute'
+ >
+ {'Last Name Attribute:'}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='text'
+ className='form-control'
+ id='LastNameAttribute'
+ ref='LastNameAttribute'
+ placeholder='Ex "sn"'
+ defaultValue={this.props.config.LdapSettings.LastNameAttribute}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'The attribute in the LDAP server that will be used to populate the last name of users in Mattermost.'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='EmailAttribute'
+ >
+ {'Email Attribute:'}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='text'
+ className='form-control'
+ id='EmailAttribute'
+ ref='EmailAttribute'
+ placeholder='Ex "mail"'
+ defaultValue={this.props.config.LdapSettings.EmailAttribute}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'The attribute in the LDAP server that will be used to populate the email addresses of users in Mattermost.'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='UsernameAttribute'
+ >
+ {'Username Attribute:'}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='text'
+ className='form-control'
+ id='UsernameAttribute'
+ ref='UsernameAttribute'
+ placeholder='Ex "sAMAccountName"'
+ defaultValue={this.props.config.LdapSettings.UsernameAttribute}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'The attribute in the LDAP server that will be used to populate the username field in Mattermost. This may be the same as the ID Attribute.'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='IdAttribute'
+ >
+ {'Id Attribute: '}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='text'
+ className='form-control'
+ id='IdAttribute'
+ ref='IdAttribute'
+ placeholder='Ex "sAMAccountName"'
+ defaultValue={this.props.config.LdapSettings.IdAttribute}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'The attribute in the LDAP server that will be used as a unique identifier in Mattermost. It should be an LDAP attribute with a value that does not change, such as username or uid. If a user’s Id Attribute changes, it will create a new Mattermost account unassociated with their old one. This is the value used to log in to Mattermost in the "LDAP Username" field on the sign in page. Normally this attribute is the same as the “Username Attribute†field above. If your team typically uses domain\\username to sign in to other services with LDAP, you may choose to put domain\\username in this field to maintain consistency between sites.'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='QueryTimeout'
+ >
+ {'Query Timeout (seconds):'}
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='number'
+ className='form-control'
+ id='QueryTimeout'
+ ref='QueryTimeout'
+ placeholder='Ex "60"'
+ defaultValue={this.props.config.LdapSettings.QueryTimeout}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <p className='help-text'>{'The timeout value for queries to the LDAP server. Increase if you are getting timeout errors caused by a slow LDAP server.'}</p>
+ </div>
+ </div>
+ <div className='form-group'>
+ <div className='col-sm-12'>
+ {serverError}
+ <button
+ disabled={!this.state.saveNeeded}
+ type='submit'
+ className={saveClass}
+ onClick={this.handleSubmit}
+ id='save-button'
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ >
+ {'Save'}
+ </button>
+ </div>
+ </div>
+ </form>
+ </div>
+ );
+ }
+}
+LdapSettings.defaultProps = {
+};
+
+LdapSettings.propTypes = {
+ config: React.PropTypes.object
+};
diff --git a/web/react/components/admin_console/rate_settings.jsx b/web/react/components/admin_console/rate_settings.jsx
index ca9fcb074..aabb24326 100644
--- a/web/react/components/admin_console/rate_settings.jsx
+++ b/web/react/components/admin_console/rate_settings.jsx
@@ -241,7 +241,7 @@ export default class RateSettings extends React.Component {
onChange={this.handleChange}
disabled={!this.state.EnableRateLimiter || this.state.VaryByRemoteAddr}
/>
- <p className='help-text'>{'When filled in, vary rate limiting by HTTP header field specified (e.g. when configuring Ngnix set to "X-Real-IP", when configuring AmazonELB set to "X-Forwarded-For").'}</p>
+ <p className='help-text'>{'When filled in, vary rate limiting by HTTP header field specified (e.g. when configuring NGINX set to "X-Real-IP", when configuring AmazonELB set to "X-Forwarded-For").'}</p>
</div>
</div>
diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx
index d87bd20ad..9afaa8b0d 100644
--- a/web/react/components/login.jsx
+++ b/web/react/components/login.jsx
@@ -2,97 +2,19 @@
// See License.txt for license information.
import * as Utils from '../utils/utils.jsx';
-import * as Client from '../utils/client.jsx';
-import UserStore from '../stores/user_store.jsx';
-import BrowserStore from '../stores/browser_store.jsx';
+import LoginEmail from './login_email.jsx';
+import LoginLdap from './login_ldap.jsx';
export default class Login extends React.Component {
constructor(props) {
super(props);
- this.handleSubmit = this.handleSubmit.bind(this);
-
this.state = {};
}
- handleSubmit(e) {
- e.preventDefault();
- var state = {};
-
- const name = this.props.teamName;
- if (!name) {
- state.serverError = 'Bad team name';
- this.setState(state);
- return;
- }
-
- const email = ReactDOM.findDOMNode(this.refs.email).value.trim();
- if (!email) {
- state.serverError = 'An email is required';
- this.setState(state);
- return;
- }
-
- const password = ReactDOM.findDOMNode(this.refs.password).value.trim();
- if (!password) {
- state.serverError = 'A password is required';
- this.setState(state);
- return;
- }
-
- if (!BrowserStore.isLocalStorageSupported()) {
- state.serverError = 'This service requires local storage to be enabled. Please enable it or exit private browsing.';
- this.setState(state);
- return;
- }
-
- state.serverError = '';
- this.setState(state);
-
- Client.loginByEmail(name, email, password,
- () => {
- UserStore.setLastEmail(email);
-
- const redirect = Utils.getUrlParameter('redirect');
- if (redirect) {
- window.location.href = decodeURIComponent(redirect);
- } else {
- window.location.href = '/' + name + '/channels/town-square';
- }
- },
- (err) => {
- if (err.message === 'Login failed because email address has not been verified') {
- window.location.href = '/verify_email?teamname=' + encodeURIComponent(name) + '&email=' + encodeURIComponent(email);
- return;
- }
- state.serverError = err.message;
- this.valid = false;
- this.setState(state);
- }
- );
- }
render() {
- let serverError;
- if (this.state.serverError) {
- serverError = <label className='control-label'>{this.state.serverError}</label>;
- }
- let priorEmail = UserStore.getLastEmail();
-
- const emailParam = Utils.getUrlParameter('email');
- if (emailParam) {
- priorEmail = decodeURIComponent(emailParam);
- }
-
const teamDisplayName = this.props.teamDisplayName;
const teamName = this.props.teamName;
- let focusEmail = false;
- let focusPassword = false;
- if (priorEmail === '') {
- focusEmail = true;
- } else {
- focusPassword = true;
- }
-
let loginMessage = [];
if (global.window.mm_config.EnableSignUpWithGitLab === 'true') {
loginMessage.push(
@@ -106,9 +28,16 @@ export default class Login extends React.Component {
);
}
- let errorClass = '';
- if (serverError) {
- errorClass = ' has-error';
+ if (global.window.mm_config.EnableSignUpWithGoogle === 'true') {
+ loginMessage.push(
+ <a
+ className='btn btn-custom-login google'
+ href={'/' + teamName + '/login/google'}
+ >
+ <span className='icon' />
+ <span>{'with Google Apps'}</span>
+ </a>
+ );
}
const verifiedParam = Utils.getUrlParameter('verified');
@@ -125,39 +54,9 @@ export default class Login extends React.Component {
let emailSignup;
if (global.window.mm_config.EnableSignUpWithEmail === 'true') {
emailSignup = (
- <div className='signup__email-container'>
- <div className={'form-group' + errorClass}>
- <input
- autoFocus={focusEmail}
- type='email'
- className='form-control'
- name='email'
- defaultValue={priorEmail}
- ref='email'
- placeholder='Email'
- spellCheck='false'
- />
- </div>
- <div className={'form-group' + errorClass}>
- <input
- autoFocus={focusPassword}
- type='password'
- className='form-control'
- name='password'
- ref='password'
- placeholder='Password'
- spellCheck='false'
- />
- </div>
- <div className='form-group'>
- <button
- type='submit'
- className='btn btn-primary'
- >
- {'Sign in'}
- </button>
- </div>
- </div>
+ <LoginEmail
+ teamName={this.props.teamName}
+ />
);
}
@@ -211,25 +110,30 @@ export default class Login extends React.Component {
);
}
+ let ldapLogin = null;
+ if (global.window.mm_config.EnableLdap === 'true') {
+ ldapLogin = (
+ <LoginLdap
+ teamName={this.props.teamName}
+ />
+ );
+ }
+
return (
<div className='signup-team__container'>
<h5 className='margin--less'>{'Sign in to:'}</h5>
<h2 className='signup-team__name'>{teamDisplayName}</h2>
<h2 className='signup-team__subdomain'>{'on '}{global.window.mm_config.SiteName}</h2>
- <form onSubmit={this.handleSubmit}>
{verifiedBox}
- <div className={'form-group' + errorClass}>
- {serverError}
- </div>
{loginMessage}
{emailSignup}
+ {ldapLogin}
{userSignUp}
<div className='form-group margin--extra form-group--small'>
<span><a href='/find_team'>{'Find your other teams'}</a></span>
</div>
{forgotPassword}
{teamSignUp}
- </form>
</div>
);
}
diff --git a/web/react/components/login_email.jsx b/web/react/components/login_email.jsx
new file mode 100644
index 000000000..cfe34d1c7
--- /dev/null
+++ b/web/react/components/login_email.jsx
@@ -0,0 +1,137 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import * as Utils from '../utils/utils.jsx';
+import * as Client from '../utils/client.jsx';
+import UserStore from '../stores/user_store.jsx';
+
+export default class LoginEmail extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+
+ this.state = {
+ serverError: ''
+ };
+ }
+ handleSubmit(e) {
+ e.preventDefault();
+ var state = {};
+
+ const name = this.props.teamName;
+ if (!name) {
+ state.serverError = 'Bad team name';
+ this.setState(state);
+ return;
+ }
+
+ const email = this.refs.email.value.trim();
+ if (!email) {
+ state.serverError = 'An email is required';
+ this.setState(state);
+ return;
+ }
+
+ const password = this.refs.password.value.trim();
+ if (!password) {
+ state.serverError = 'A password is required';
+ this.setState(state);
+ return;
+ }
+
+ state.serverError = '';
+ this.setState(state);
+
+ Client.loginByEmail(name, email, password,
+ () => {
+ UserStore.setLastEmail(email);
+
+ const redirect = Utils.getUrlParameter('redirect');
+ if (redirect) {
+ window.location.href = decodeURIComponent(redirect);
+ } else {
+ window.location.href = '/' + name + '/channels/town-square';
+ }
+ },
+ (err) => {
+ if (err.message === 'Login failed because email address has not been verified') {
+ window.location.href = '/verify_email?teamname=' + encodeURIComponent(name) + '&email=' + encodeURIComponent(email);
+ return;
+ }
+ state.serverError = err.message;
+ this.valid = false;
+ this.setState(state);
+ }
+ );
+ }
+ render() {
+ let serverError;
+ let errorClass = '';
+ if (this.state.serverError) {
+ serverError = <label className='control-label'>{this.state.serverError}</label>;
+ errorClass = ' has-error';
+ }
+
+ let priorEmail = UserStore.getLastEmail();
+ let focusEmail = false;
+ let focusPassword = false;
+ if (priorEmail === '') {
+ focusEmail = true;
+ } else {
+ focusPassword = true;
+ }
+
+ const emailParam = Utils.getUrlParameter('email');
+ if (emailParam) {
+ priorEmail = decodeURIComponent(emailParam);
+ }
+
+ return (
+ <form onSubmit={this.handleSubmit}>
+ <div className='signup__email-container'>
+ <div className={'form-group' + errorClass}>
+ {serverError}
+ </div>
+ <div className={'form-group' + errorClass}>
+ <input
+ autoFocus={focusEmail}
+ type='email'
+ className='form-control'
+ name='email'
+ defaultValue={priorEmail}
+ ref='email'
+ placeholder='Email'
+ spellCheck='false'
+ />
+ </div>
+ <div className={'form-group' + errorClass}>
+ <input
+ autoFocus={focusPassword}
+ type='password'
+ className='form-control'
+ name='password'
+ ref='password'
+ placeholder='Password'
+ spellCheck='false'
+ />
+ </div>
+ <div className='form-group'>
+ <button
+ type='submit'
+ className='btn btn-primary'
+ >
+ {'Sign in'}
+ </button>
+ </div>
+ </div>
+ </form>
+ );
+ }
+}
+LoginEmail.defaultProps = {
+};
+
+LoginEmail.propTypes = {
+ teamName: React.PropTypes.string.isRequired
+};
diff --git a/web/react/components/login_ldap.jsx b/web/react/components/login_ldap.jsx
new file mode 100644
index 000000000..1e0e32f4f
--- /dev/null
+++ b/web/react/components/login_ldap.jsx
@@ -0,0 +1,110 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import * as Utils from '../utils/utils.jsx';
+import * as Client from '../utils/client.jsx';
+
+export default class LoginLdap extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+
+ this.state = {
+ serverError: ''
+ };
+ }
+ handleSubmit(e) {
+ e.preventDefault();
+ var state = {};
+
+ const teamName = this.props.teamName;
+ if (!teamName) {
+ state.serverError = 'Bad team name';
+ this.setState(state);
+ return;
+ }
+
+ const id = this.refs.id.value.trim();
+ if (!id) {
+ state.serverError = 'An LDAP ID is required';
+ this.setState(state);
+ return;
+ }
+
+ const password = this.refs.password.value.trim();
+ if (!password) {
+ state.serverError = 'An LDAP password is required';
+ this.setState(state);
+ return;
+ }
+
+ state.serverError = '';
+ this.setState(state);
+
+ Client.loginByLdap(teamName, id, password,
+ () => {
+ const redirect = Utils.getUrlParameter('redirect');
+ if (redirect) {
+ window.location.href = decodeURIComponent(redirect);
+ } else {
+ window.location.href = '/' + teamName + '/channels/town-square';
+ }
+ },
+ (err) => {
+ state.serverError = err.message;
+ this.setState(state);
+ }
+ );
+ }
+ render() {
+ let serverError;
+ let errorClass = '';
+ if (this.state.serverError) {
+ serverError = <label className='control-label'>{this.state.serverError}</label>;
+ errorClass = ' has-error';
+ }
+
+ return (
+ <form onSubmit={this.handleSubmit}>
+ <div className='signup__email-container'>
+ <div className={'form-group' + errorClass}>
+ {serverError}
+ </div>
+ <div className={'form-group' + errorClass}>
+ <input
+ autoFocus={true}
+ className='form-control'
+ ref='id'
+ placeholder='LDAP Username'
+ spellCheck='false'
+ />
+ </div>
+ <div className={'form-group' + errorClass}>
+ <input
+ type='password'
+ className='form-control'
+ ref='password'
+ placeholder='LDAP Password'
+ spellCheck='false'
+ />
+ </div>
+ <div className='form-group'>
+ <button
+ type='submit'
+ className='btn btn-primary'
+ >
+ {'Sign in'}
+ </button>
+ </div>
+ </div>
+ </form>
+ );
+ }
+}
+LoginLdap.defaultProps = {
+};
+
+LoginLdap.propTypes = {
+ teamName: React.PropTypes.string.isRequired
+};
diff --git a/web/react/components/rhs_root_post.jsx b/web/react/components/rhs_root_post.jsx
index dd9a793be..cd7f6766c 100644
--- a/web/react/components/rhs_root_post.jsx
+++ b/web/react/components/rhs_root_post.jsx
@@ -227,7 +227,6 @@ export default class RhsRootPost extends React.Component {
</div>
</div>
</div>
- <hr />
</div>
);
}
diff --git a/web/react/components/settings_sidebar.jsx b/web/react/components/settings_sidebar.jsx
index 4af46c35a..271ea9a41 100644
--- a/web/react/components/settings_sidebar.jsx
+++ b/web/react/components/settings_sidebar.jsx
@@ -1,6 +1,8 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import * as Utils from '../utils/utils.jsx';
+
export default class SettingsSidebar extends React.Component {
componentDidUpdate() {
$('.settings-modal').find('.modal-body').scrollTop(0);
@@ -16,6 +18,11 @@ export default class SettingsSidebar extends React.Component {
this.props.updateTab(tab.name);
$(e.target).closest('.settings-modal').addClass('display--content');
}
+ componentDidMount() {
+ if (Utils.isBrowserFirefox()) {
+ $('.settings-modal .settings-table .nav').addClass('position--top');
+ }
+ }
render() {
let tabList = this.props.tabs.map(function makeTab(tab) {
let key = `${tab.name}_li`;
diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx
index cc2279b57..18c360cb8 100644
--- a/web/react/components/sidebar.jsx
+++ b/web/react/components/sidebar.jsx
@@ -39,6 +39,7 @@ export default class Sidebar extends React.Component {
this.handleLeaveDirectChannel = this.handleLeaveDirectChannel.bind(this);
this.handleResize = this.handleResize.bind(this);
+ this.showMoreChannelsModal = this.showMoreChannelsModal.bind(this);
this.showNewChannelModal = this.showNewChannelModal.bind(this);
this.hideNewChannelModal = this.hideNewChannelModal.bind(this);
this.showMoreDirectChannelsModal = this.showMoreDirectChannelsModal.bind(this);
@@ -250,6 +251,11 @@ export default class Sidebar extends React.Component {
return a.display_name.localeCompare(b.display_name);
}
+ showMoreChannelsModal() {
+ // manually show the modal because using data-toggle messes with keyboard focus when the modal is dismissed
+ $('#more_channels').modal({'data-channeltype': 'O'}).modal('show');
+ }
+
showNewChannelModal(type) {
this.setState({newChannelModalType: type});
}
@@ -594,10 +600,8 @@ export default class Sidebar extends React.Component {
<li>
<a
href='#'
- data-toggle='modal'
className='nav-more'
- data-target='#more_channels'
- data-channeltype='O'
+ onClick={this.showMoreChannelsModal}
>
{'More...'}
</a>
diff --git a/web/react/components/sidebar_right.jsx b/web/react/components/sidebar_right.jsx
index ac1049da0..ee247265d 100644
--- a/web/react/components/sidebar_right.jsx
+++ b/web/react/components/sidebar_right.jsx
@@ -52,14 +52,29 @@ export default class SidebarRight extends React.Component {
doStrangeThings() {
// We should have a better way to do this stuff
// Hence the function name.
+ var windowWidth = $(window).outerWidth();
+ var sidebarRightWidth = $('.sidebar--right').outerWidth();
+
$('.inner__wrap').removeClass('.move--right');
$('.inner__wrap').addClass('move--left');
$('.sidebar--left').removeClass('move--right');
$('.sidebar--right').addClass('move--left');
//$('.sidebar--right').prepend('<div class="sidebar__overlay"></div>');
-
- if (!(this.state.search_visible || this.state.post_right_visible)) {
+ if (this.state.search_visible || this.state.post_right_visible) {
+ if (windowWidth > 960) {
+ $('.inner__wrap').velocity({marginRight: sidebarRightWidth}, {duration: 500, easing: 'easeOutSine'});
+ $('.sidebar--right').velocity({translateX: 0}, {duration: 500, easing: 'easeOutSine'});
+ } else {
+ $('.inner__wrap, .sidebar--right').attr('style', '');
+ }
+ } else {
+ if (windowWidth > 960) {
+ $('.inner__wrap').velocity({marginRight: 0}, {duration: 500, easing: 'easeOutSine'});
+ $('.sidebar--right').velocity({translateX: sidebarRightWidth}, {duration: 500, easing: 'easeOutSine'});
+ } else {
+ $('.inner__wrap, .sidebar--right').attr('style', '');
+ }
$('.inner__wrap').removeClass('move--left').removeClass('move--right');
$('.sidebar--right').removeClass('move--left');
return (
diff --git a/web/react/components/signup_team.jsx b/web/react/components/signup_team.jsx
index 0ac837326..a554427d5 100644
--- a/web/react/components/signup_team.jsx
+++ b/web/react/components/signup_team.jsx
@@ -28,6 +28,8 @@ export default class TeamSignUp extends React.Component {
this.state = {page: 'email'};
} else if (global.window.mm_config.EnableSignUpWithGitLab === 'true') {
this.state = {page: 'gitlab'};
+ } else {
+ this.state = {page: 'none'};
}
}
@@ -112,6 +114,15 @@ export default class TeamSignUp extends React.Component {
<SSOSignupPage service={Constants.GITLAB_SERVICE} />
</div>
);
+ } else if (this.state.page === 'google') {
+ return (
+ <div>
+ {teamListing}
+ <SSOSignupPage service={Constants.GOOGLE_SERVICE} />
+ </div>
+ );
+ } else if (this.state.page === 'none') {
+ return (<div>{'No team creation method has been enabled. Please contact an administrator for access.'}</div>);
}
}
}
diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx
index 2bde78726..df11fe045 100644
--- a/web/react/components/signup_user_complete.jsx
+++ b/web/react/components/signup_user_complete.jsx
@@ -183,11 +183,23 @@ export default class SignupUserComplete extends React.Component {
href={'/' + this.props.teamName + '/signup/gitlab' + window.location.search}
>
<span className='icon' />
- <span>with GitLab</span>
+ <span>{'with GitLab'}</span>
</a>
);
}
+ if (global.window.mm_config.EnableSignUpWithGoogle === 'true') {
+ signupMessage.push(
+ <a
+ className='btn btn-custom-login google'
+ href={'/' + this.props.teamName + '/signup/google' + window.location.search}
+ >
+ <span className='icon' />
+ <span>{'with Google'}</span>
+ </a>
+ );
+ }
+
var emailSignup;
if (global.window.mm_config.EnableSignUpWithEmail === 'true') {
emailSignup = (
diff --git a/web/react/components/suggestion/search_channel_provider.jsx b/web/react/components/suggestion/search_channel_provider.jsx
index 7547a9341..66a534907 100644
--- a/web/react/components/suggestion/search_channel_provider.jsx
+++ b/web/react/components/suggestion/search_channel_provider.jsx
@@ -19,7 +19,7 @@ class SearchChannelSuggestion extends React.Component {
onClick={onClick}
className={className}
>
- {item.name}
+ <i className='fa fa fa-plus-square'></i>{item.name}
</div>
);
}
diff --git a/web/react/components/suggestion/search_user_provider.jsx b/web/react/components/suggestion/search_user_provider.jsx
index cf2953937..0d553bfc4 100644
--- a/web/react/components/suggestion/search_user_provider.jsx
+++ b/web/react/components/suggestion/search_user_provider.jsx
@@ -22,7 +22,7 @@ class SearchUserSuggestion extends React.Component {
className='profile-img rounded'
src={'/api/v1/users/' + item.id + '/image?time=' + item.update_at}
/>
- {item.username}
+ <i className='fa fa fa-plus-square'></i>{item.username}
</div>
);
}
diff --git a/web/react/components/team_signup_choose_auth.jsx b/web/react/components/team_signup_choose_auth.jsx
index 0254c8b4e..19b9750b3 100644
--- a/web/react/components/team_signup_choose_auth.jsx
+++ b/web/react/components/team_signup_choose_auth.jsx
@@ -26,6 +26,24 @@ export default class ChooseAuthPage extends React.Component {
);
}
+ if (global.window.mm_config.EnableSignUpWithGoogle === 'true') {
+ buttons.push(
+ <a
+ className='btn btn-custom-login google btn-full'
+ href='#'
+ onClick={
+ (e) => {
+ e.preventDefault();
+ this.props.updatePage('google');
+ }
+ }
+ >
+ <span className='icon' />
+ <span>{'Create new team with Google Apps Account'}</span>
+ </a>
+ );
+ }
+
if (global.window.mm_config.EnableSignUpWithEmail === 'true') {
buttons.push(
<a
diff --git a/web/react/components/team_signup_with_sso.jsx b/web/react/components/team_signup_with_sso.jsx
index e3f16efb0..f4b323956 100644
--- a/web/react/components/team_signup_with_sso.jsx
+++ b/web/react/components/team_signup_with_sso.jsx
@@ -88,6 +88,18 @@ export default class SSOSignUpPage extends React.Component {
<span>{'Create team with GitLab Account'}</span>
</a>
);
+ } else if (this.props.service === Constants.GOOGLE_SERVICE) {
+ button = (
+ <a
+ className='btn btn-custom-login google btn-full'
+ href='#'
+ onClick={this.handleSubmit}
+ disabled={disabled}
+ >
+ <span className='icon'/>
+ <span>{'Create team with Google Apps Account'}</span>
+ </a>
+ );
}
return (
diff --git a/web/react/components/user_settings/custom_theme_chooser.jsx b/web/react/components/user_settings/custom_theme_chooser.jsx
index b7d90922a..8ec3863f3 100644
--- a/web/react/components/user_settings/custom_theme_chooser.jsx
+++ b/web/react/components/user_settings/custom_theme_chooser.jsx
@@ -104,7 +104,7 @@ export default class CustomThemeChooser extends React.Component {
>
<label className='custom-label'>{element.uiName}</label>
<div
- className='input-group theme-group dropdown'
+ className='input-group theme-group group--code dropdown'
id={element.id}
>
<select
diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx
index 820f8fd8e..7edf6283b 100644
--- a/web/react/components/view_image.jsx
+++ b/web/react/components/view_image.jsx
@@ -1,9 +1,11 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import * as AsyncClient from '../utils/async_client.jsx';
import * as Client from '../utils/client.jsx';
import * as Utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx';
+import FileStore from '../stores/file_store.jsx';
import ViewImagePopoverBar from './view_image_popover_bar.jsx';
const Modal = ReactBootstrap.Modal;
const KeyCodes = Constants.KeyCodes;
@@ -12,80 +14,90 @@ export default class ViewImageModal extends React.Component {
constructor(props) {
super(props);
- this.canSetState = false;
-
+ this.showImage = this.showImage.bind(this);
this.loadImage = this.loadImage.bind(this);
+
this.handleNext = this.handleNext.bind(this);
this.handlePrev = this.handlePrev.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
- this.getPublicLink = this.getPublicLink.bind(this);
- this.getPreviewImagePath = this.getPreviewImagePath.bind(this);
+
this.onModalShown = this.onModalShown.bind(this);
this.onModalHidden = this.onModalHidden.bind(this);
+
+ this.onFileStoreChange = this.onFileStoreChange.bind(this);
+
+ this.getPublicLink = this.getPublicLink.bind(this);
+ this.getPreviewImagePath = this.getPreviewImagePath.bind(this);
this.onMouseEnterImage = this.onMouseEnterImage.bind(this);
this.onMouseLeaveImage = this.onMouseLeaveImage.bind(this);
- var loaded = [];
- var progress = [];
+ const loaded = [];
+ const progress = [];
for (var i = 0; i < this.props.filenames.length; i++) {
loaded.push(false);
progress.push(0);
}
+
this.state = {
imgId: this.props.startId,
+ fileInfo: new Map(),
imgHeight: '100%',
- loaded: loaded,
- progress: progress,
- images: {},
- fileSizes: {},
- fileMimes: {},
- showFooter: false,
- isPlaying: {},
- isLoading: {}
+ loaded,
+ progress,
+ showFooter: false
};
}
+
handleNext(e) {
if (e) {
e.stopPropagation();
}
- var id = this.state.imgId + 1;
+ let id = this.state.imgId + 1;
if (id > this.props.filenames.length - 1) {
id = 0;
}
- this.setState({imgId: id});
- this.loadImage(id);
+ this.showImage(id);
}
+
handlePrev(e) {
if (e) {
e.stopPropagation();
}
- var id = this.state.imgId - 1;
+ let id = this.state.imgId - 1;
if (id < 0) {
id = this.props.filenames.length - 1;
}
- this.setState({imgId: id});
- this.loadImage(id);
+ this.showImage(id);
}
+
handleKeyPress(e) {
- if (!e || !this.props.show) {
- return;
- } else if (e.keyCode === KeyCodes.RIGHT) {
+ if (e.keyCode === KeyCodes.RIGHT) {
this.handleNext();
} else if (e.keyCode === KeyCodes.LEFT) {
this.handlePrev();
}
}
+
onModalShown(nextProps) {
- this.setState({imgId: nextProps.startId});
- this.loadImage(nextProps.startId);
+ $(window).on('keyup', this.handleKeyPress);
+
+ this.showImage(nextProps.startId);
+
+ FileStore.addChangeListener(this.onFileStoreChange);
}
+
onModalHidden() {
+ $(window).off('keyup', this.handleKeyPress);
+
if (this.refs.video) {
var video = ReactDOM.findDOMNode(this.refs.video);
video.pause();
video.currentTime = 0;
}
+
+ FileStore.removeChangeListener(this.onFileStoreChange);
}
+
componentWillReceiveProps(nextProps) {
if (nextProps.show === true && this.props.show === false) {
this.onModalShown(nextProps);
@@ -93,31 +105,65 @@ export default class ViewImageModal extends React.Component {
this.onModalHidden();
}
}
- loadImage(id) {
- var imgHeight = $(window).height() - 100;
+
+ onFileStoreChange(filename) {
+ const id = this.props.filenames.indexOf(filename);
+
+ if (id !== -1 && !this.state.loaded[id]) {
+ const fileInfo = this.state.fileInfo;
+ fileInfo.set(filename, FileStore.getInfo(filename));
+ this.setState({fileInfo});
+
+ this.loadImage(id, filename);
+ }
+ }
+
+ showImage(id) {
+ this.setState({imgId: id});
+
+ const imgHeight = $(window).height() - 100;
this.setState({imgHeight});
- var filename = this.props.filenames[id];
+ const filename = this.props.filenames[id];
- var fileInfo = Utils.splitFileLocation(filename);
- var fileType = Utils.getFileType(fileInfo.ext);
+ if (!FileStore.hasInfo(filename)) {
+ // the image will actually be loaded once we know what we need to load
+ AsyncClient.getFileInfo(filename);
+ return;
+ }
+
+ if (!this.state.loaded[id]) {
+ this.loadImage(id, filename);
+ }
+ }
+
+ loadImage(id, filename) {
+ const fileInfo = FileStore.getInfo(filename);
+ const fileType = Utils.getFileType(fileInfo.extension);
if (fileType === 'image') {
- var img = new Image();
- img.load(this.getPreviewImagePath(filename),
- () => {
- const progress = this.state.progress;
- progress[id] = img.completedPercentage;
- this.setState({progress});
- });
+ let previewUrl;
+ if (fileInfo.has_image_preview) {
+ previewUrl = fileInfo.getPreviewImagePath(filename);
+ } else {
+ // some images (eg animated gifs) just show the file itself and not a preview
+ previewUrl = Utils.getFileUrl(filename);
+ }
+
+ const img = new Image();
+ img.load(
+ previewUrl,
+ () => {
+ const progress = this.state.progress;
+ progress[id] = img.completedPercentage;
+ this.setState({progress});
+ }
+ );
img.onload = () => {
const loaded = this.state.loaded;
loaded[id] = true;
this.setState({loaded});
};
- var images = this.state.images;
- images[id] = img;
- this.setState({images});
} else {
// there's nothing to load for non-image files
var loaded = this.state.loaded;
@@ -125,169 +171,82 @@ export default class ViewImageModal extends React.Component {
this.setState({loaded});
}
}
- playGif(e, filename, fileUrl) {
- var isLoading = this.state.isLoading;
- var isPlaying = this.state.isPlaying;
-
- isLoading[filename] = fileUrl;
- this.setState({isLoading});
-
- var img = new Image();
- img.load(fileUrl);
- img.onload = () => {
- delete isLoading[filename];
- isPlaying[filename] = fileUrl;
- this.setState({isPlaying, isLoading});
- };
- img.onError = () => {
- delete isLoading[filename];
- this.setState({isLoading});
- };
-
- e.stopPropagation();
- e.preventDefault();
- }
- stopGif(e, filename) {
- var isPlaying = this.state.isPlaying;
- delete isPlaying[filename];
- this.setState({isPlaying});
-
- e.stopPropagation();
- e.preventDefault();
- }
- componentDidMount() {
- $(window).on('keyup', this.handleKeyPress);
- // keep track of whether or not this component is mounted so we can safely set the state asynchronously
- this.canSetState = true;
- }
- componentWillUnmount() {
- this.canSetState = false;
- $(window).off('keyup', this.handleKeyPress);
- }
getPublicLink() {
var data = {};
data.channel_id = this.props.channelId;
data.user_id = this.props.userId;
data.filename = this.props.filenames[this.state.imgId];
- Client.getPublicLink(data,
- function sucess(serverData) {
+ Client.getPublicLink(
+ data,
+ (serverData) => {
if (Utils.isMobile()) {
window.location.href = serverData.public_link;
} else {
window.open(serverData.public_link);
}
},
- function error() {}
+ () => {}
);
}
+
getPreviewImagePath(filename) {
// Returns the path to a preview image that can be used to represent a file.
var fileInfo = Utils.splitFileLocation(filename);
var fileType = Utils.getFileType(fileInfo.ext);
if (fileType === 'image') {
- if (filename in this.state.isPlaying) {
- return this.state.isPlaying[filename];
- }
-
// This is a temporary patch to fix issue with old files using absolute paths
if (fileInfo.path.indexOf('/api/v1/files/get') !== -1) {
fileInfo.path = fileInfo.path.split('/api/v1/files/get')[1];
}
fileInfo.path = Utils.getWindowLocationOrigin() + '/api/v1/files/get' + fileInfo.path;
- return fileInfo.path + '_preview.jpg' + '?' + Utils.getSessionIndex();
+ return fileInfo.path + '_preview.jpg?' + Utils.getSessionIndex();
}
// only images have proper previews, so just use a placeholder icon for non-images
return Utils.getPreviewImagePathForFileType(fileType);
}
+
onMouseEnterImage() {
this.setState({showFooter: true});
}
+
onMouseLeaveImage() {
this.setState({showFooter: false});
}
+
render() {
if (this.props.filenames.length < 1 || this.props.filenames.length - 1 < this.state.imgId) {
return <div/>;
}
- var filename = this.props.filenames[this.state.imgId];
- var fileUrl = Utils.getFileUrl(filename);
-
- var name = decodeURIComponent(Utils.getFileName(filename));
+ const filename = this.props.filenames[this.state.imgId];
+ const fileUrl = Utils.getFileUrl(filename);
var content;
- var bgClass = '';
if (this.state.loaded[this.state.imgId]) {
- var fileInfo = Utils.splitFileLocation(filename);
- var fileType = Utils.getFileType(fileInfo.ext);
+ // if a file has been loaded, we also have its info
+ const fileInfo = this.state.fileInfo.get(filename);
- if (fileType === 'image') {
- if (!(filename in this.state.fileMimes)) {
- Client.getFileInfo(
- filename,
- (data) => {
- if (this.canSetState) {
- var fileMimes = this.state.fileMimes;
- fileMimes[filename] = data.mime;
- this.setState(fileMimes);
- }
- },
- () => {}
- );
- }
+ const extension = Utils.splitFileLocation(filename).ext;
+ const fileType = Utils.getFileType(extension);
- var playbackControls = '';
- if (this.state.fileMimes[filename] === 'image/gif' && !(filename in this.state.isLoading)) {
- if (filename in this.state.isPlaying) {
- playbackControls = (
- <div
- className='file-playback-controls stop'
- onClick={(e) => this.stopGif(e, filename)}
- >
- {"â– "}
- </div>
- );
- } else {
- playbackControls = (
- <div
- className='file-playback-controls play'
- onClick={(e) => this.playGif(e, filename, fileUrl)}
- >
- {"â–º"}
- </div>
- );
- }
- }
-
- var loadingIndicator = '';
- if (this.state.isLoading[filename] === fileUrl) {
- loadingIndicator = (
- <img
- className='spinner file__loading'
- src='/static/images/load.gif'
- />
- );
- playbackControls = '';
+ if (fileType === 'image') {
+ let previewUrl;
+ if (fileInfo.has_preview_image) {
+ previewUrl = this.getPreviewImagePath(filename);
+ } else {
+ previewUrl = fileUrl;
}
- // image files just show a preview of the file
content = (
- <a
- href={fileUrl}
- target='_blank'
- >
- {loadingIndicator}
- {playbackControls}
- <img
- style={{maxHeight: this.state.imgHeight}}
- ref='image'
- src={this.getPreviewImagePath(filename)}
- />
- </a>
+ <ImagePreview
+ fileUrl={fileUrl}
+ previewUrl={previewUrl}
+ maxHeight={this.state.imgHeight}
+ />
);
} else if (fileType === 'video' || fileType === 'audio') {
let width = Constants.WEB_VIDEO_WIDTH;
@@ -311,11 +270,13 @@ export default class ViewImageModal extends React.Component {
);
} else {
// non-image files include a section providing details about the file
- var infoString = 'File type ' + fileInfo.ext.toUpperCase();
- if (this.state.fileSizes[filename] && this.state.fileSizes[filename] >= 0) {
- infoString += ', Size ' + Utils.fileSizeToString(this.state.fileSizes[filename]);
+ let infoString = 'File type ' + fileInfo.extension.toUpperCase();
+ if (fileInfo.size > 0) {
+ infoString += ', Size ' + Utils.fileSizeToString(fileInfo.size);
}
+ const name = decodeURIComponent(Utils.getFileName(filename));
+
content = (
<div className='file-details__container'>
<a
@@ -335,53 +296,16 @@ export default class ViewImageModal extends React.Component {
</div>
</div>
);
- bgClass = 'white-bg';
-
- // asynchronously request the actual size of this file
- if (!(filename in this.state.fileSizes)) {
- Client.getFileInfo(
- filename,
- function success(data) {
- if (this.canSetState) {
- var fileSizes = this.state.fileSizes;
- fileSizes[filename] = parseInt(data.size, 10);
- this.setState(fileSizes);
- }
- }.bind(this),
- function fail() {}
- );
- }
}
} else {
// display a progress indicator when the preview for an image is still loading
- var percentage = Math.floor(this.state.progress[this.state.imgId]);
- if (percentage) {
- content = (
- <div>
- <img
- className='loader-image'
- src='/static/images/load.gif'
- />
- <span className='loader-percent'>
- {'Previewing ' + percentage + '%'}
- </span>
- </div>
- );
- } else {
- content = (
- <div>
- <img
- className='loader-image'
- src='/static/images/load.gif'
- />
- </div>
- );
- }
- bgClass = 'black-bg';
+ const progress = Math.floor(this.state.progress[this.state.imgId]);
+
+ content = <LoadingImagePreview progress={progress} />;
}
- var leftArrow = '';
- var rightArrow = '';
+ let leftArrow = null;
+ let rightArrow = null;
if (this.props.filenames.length > 1) {
leftArrow = (
<a
@@ -427,7 +351,6 @@ export default class ViewImageModal extends React.Component {
onClick={this.props.onModalDismissed}
>
<div
- className={bgClass}
onMouseEnter={this.onMouseEnterImage}
onMouseLeave={this.onMouseLeaveImage}
onClick={(e) => e.stopPropagation()}
@@ -471,3 +394,38 @@ ViewImageModal.propTypes = {
userId: React.PropTypes.string,
startId: React.PropTypes.number
};
+
+function LoadingImagePreview({progress}) {
+ let progressView = null;
+ if (progress) {
+ progressView = (
+ <span className='loader-percent'>
+ {'Loading ' + progress + '%'}
+ </span>
+ );
+ }
+
+ return (
+ <div className='view-image__loading'>
+ <img
+ className='loader-image'
+ src='/static/images/load.gif'
+ />
+ {progressView}
+ </div>
+ );
+}
+
+function ImagePreview({maxHeight, fileUrl, previewUrl}) {
+ return (
+ <a
+ href={fileUrl}
+ target='_blank'
+ >
+ <img
+ style={{maxHeight}}
+ src={previewUrl}
+ />
+ </a>
+ );
+}
diff --git a/web/react/stores/file_store.jsx b/web/react/stores/file_store.jsx
new file mode 100644
index 000000000..ca8c6a96b
--- /dev/null
+++ b/web/react/stores/file_store.jsx
@@ -0,0 +1,60 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
+import Constants from '../utils/constants.jsx';
+import EventEmitter from 'events';
+
+const ActionTypes = Constants.ActionTypes;
+
+const CHANGE_EVENT = 'changed';
+
+class FileStore extends EventEmitter {
+ constructor() {
+ super();
+
+ this.addChangeListener = this.addChangeListener.bind(this);
+ this.removeChangeListener = this.removeChangeListener.bind(this);
+ this.emitChange = this.emitChange.bind(this);
+
+ this.handleEventPayload = this.handleEventPayload.bind(this);
+ this.dispatchToken = AppDispatcher.register(this.handleEventPayload);
+
+ this.fileInfo = new Map();
+ }
+
+ addChangeListener(callback) {
+ this.on(CHANGE_EVENT, callback);
+ }
+ removeChangeListener(callback) {
+ this.removeListener(CHANGE_EVENT, callback);
+ }
+ emitChange(filename) {
+ this.emit(CHANGE_EVENT, filename);
+ }
+
+ hasInfo(filename) {
+ return this.fileInfo.has(filename);
+ }
+
+ getInfo(filename) {
+ return this.fileInfo.get(filename);
+ }
+
+ setInfo(filename, info) {
+ this.fileInfo.set(filename, info);
+ }
+
+ handleEventPayload(payload) {
+ const action = payload.action;
+
+ switch (action.type) {
+ case ActionTypes.RECIEVED_FILE_INFO:
+ this.setInfo(action.filename, action.info);
+ this.emitChange(action.filename);
+ break;
+ }
+ }
+}
+
+export default new FileStore();
diff --git a/web/react/utils/async_client.jsx b/web/react/utils/async_client.jsx
index 88b5aa739..f218270da 100644
--- a/web/react/utils/async_client.jsx
+++ b/web/react/utils/async_client.jsx
@@ -769,3 +769,31 @@ export function getSuggestedCommands(command, suggestionId, component) {
}
);
}
+
+export function getFileInfo(filename) {
+ const callName = 'getFileInfo' + filename;
+
+ if (isCallInProgress(callName)) {
+ return;
+ }
+
+ callTracker[callName] = utils.getTimestamp();
+
+ client.getFileInfo(
+ filename,
+ (data) => {
+ callTracker[callName] = 0;
+
+ AppDispatcher.handleServerAction({
+ type: ActionTypes.RECIEVED_FILE_INFO,
+ filename,
+ info: data
+ });
+ },
+ (err) => {
+ callTracker[callName] = 0;
+
+ dispatchError(err, 'getFileInfo');
+ }
+ );
+}
diff --git a/web/react/utils/client.jsx b/web/react/utils/client.jsx
index beabf5227..1c417153b 100644
--- a/web/react/utils/client.jsx
+++ b/web/react/utils/client.jsx
@@ -243,7 +243,7 @@ export function loginByEmail(name, email, password, success, error) {
dataType: 'json',
contentType: 'application/json',
type: 'POST',
- data: JSON.stringify({name: name, email: email, password: password}),
+ data: JSON.stringify({name, email, password}),
success: function onSuccess(data, textStatus, xhr) {
track('api', 'api_users_login_success', data.team_id, 'email', data.email);
BrowserStore.signalLogin();
@@ -258,6 +258,26 @@ export function loginByEmail(name, email, password, success, error) {
});
}
+export function loginByLdap(teamName, id, password, success, error) {
+ $.ajax({
+ url: '/api/v1/users/login_ldap',
+ dataType: 'json',
+ contentType: 'application/json',
+ type: 'POST',
+ data: JSON.stringify({teamName, id, password}),
+ success: function onSuccess(data, textStatus, xhr) {
+ track('api', 'api_users_loginLdap_success', data.team_id, 'id', id);
+ success(data, textStatus, xhr);
+ },
+ error: function onError(xhr, status, err) {
+ track('api', 'api_users_loginLdap_fail', teamName, 'id', id);
+
+ var e = handleError('loginByLdap', xhr, status, err);
+ error(e);
+ }
+ });
+}
+
export function revokeSession(altId, success, error) {
$.ajax({
url: '/api/v1/users/revoke_session',
@@ -1056,7 +1076,9 @@ export function getFileInfo(filename, success, error) {
dataType: 'json',
contentType: 'application/json',
type: 'GET',
- success,
+ success: (data) => {
+ success(data);
+ },
error: function onError(xhr, status, err) {
var e = handleError('getFileInfo', xhr, status, err);
error(e);
diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx
index 5f027a409..ea4921417 100644
--- a/web/react/utils/constants.jsx
+++ b/web/react/utils/constants.jsx
@@ -37,6 +37,7 @@ export default {
RECIEVED_STATUSES: null,
RECIEVED_PREFERENCE: null,
RECIEVED_PREFERENCES: null,
+ RECIEVED_FILE_INFO: null,
RECIEVED_MSG: null,
@@ -114,6 +115,7 @@ export default {
DEFAULT_CHANNEL: 'town-square',
OFFTOPIC_CHANNEL: 'off-topic',
GITLAB_SERVICE: 'gitlab',
+ GOOGLE_SERVICE: 'google',
EMAIL_SERVICE: 'email',
POST_CHUNK_SIZE: 60,
MAX_POST_CHUNKS: 3,
diff --git a/web/react/utils/emoticons.jsx b/web/react/utils/emoticons.jsx
index fa5177232..23a847969 100644
--- a/web/react/utils/emoticons.jsx
+++ b/web/react/utils/emoticons.jsx
@@ -2,21 +2,21 @@
// See License.txt for license information.
const emoticonPatterns = {
- smile: /(^|\s)(:-?\))(?=$|\s)/g, // :)
+ slightly_smiling_face: /(^|\s)(:-?\))(?=$|\s)/g, // :)
wink: /(^|\s)(;-?\))(?=$|\s)/g, // ;)
open_mouth: /(^|\s)(:o)(?=$|\s)/gi, // :o
scream: /(^|\s)(:-o)(?=$|\s)/gi, // :-o
smirk: /(^|\s)(:-?])(?=$|\s)/g, // :]
- grinning: /(^|\s)(:-?d)(?=$|\s)/gi, // :D
+ smile: /(^|\s)(:-?d)(?=$|\s)/gi, // :D
stuck_out_tongue_closed_eyes: /(^|\s)(x-d)(?=$|\s)/gi, // x-d
stuck_out_tongue: /(^|\s)(:-?p)(?=$|\s)/gi, // :p
rage: /(^|\s)(:-?[\[@])(?=$|\s)/g, // :@
- frowning: /(^|\s)(:-?\()(?=$|\s)/g, // :(
- sob: /(^|\s)(:['’]-?\(|:&#x27;\(|:&#39;\()(?=$|\s)/g, // :`(
- pensive: /(^|\s)(:-?\/)(?=$|\s)/g, // :/
+ slightly_frowning_face: /(^|\s)(:-?\()(?=$|\s)/g, // :(
+ cry: /(^|\s)(:['’]-?\(|:&#x27;\(|:&#39;\()(?=$|\s)/g, // :`(
+ confused: /(^|\s)(:-?\/)(?=$|\s)/g, // :/
confounded: /(^|\s)(:-?s)(?=$|\s)/gi, // :s
- flushed: /(^|\s)(:-?\|)(?=$|\s)/g, // :|
- relaxed: /(^|\s)(:-?\$)(?=$|\s)/g, // :$
+ neutral_face: /(^|\s)(:-?\|)(?=$|\s)/g, // :|
+ flushed: /(^|\s)(:-?\$)(?=$|\s)/g, // :$
mask: /(^|\s)(:-x)(?=$|\s)/gi, // :-x
heart: /(^|\s)(<3|&lt;3)(?=$|\s)/g, // <3
broken_heart: /(^|\s)(<\/3|&lt;&#x2F;3)(?=$|\s)/g, // </3
@@ -34,10 +34,10 @@ function initializeEmoticonMap() {
'baby_bottle,baby_chick,baby_symbol,back,baggage_claim,balloon,ballot_box_with_check,bamboo,banana,bangbang,' +
'bank,bar_chart,barber,baseball,basketball,bath,bathtub,battery,bear,bee,beer,beers,beetle,beginner,bell,bento,' +
'bicyclist,bike,bikini,bird,birthday,black_circle,black_joker,black_medium_small_square,black_medium_square,' +
- 'black_nib,black_small_square,black_square,black_square_button,blossom,blowfish,blue_book,blue_car,blue_heart,' +
- 'blush,boar,boat,bomb,book,bookmark,bookmark_tabs,books,boom,boot,bouquet,bow,bowling,bowtie,boy,bread,' +
- 'bride_with_veil,bridge_at_night,briefcase,broken_heart,bug,bulb,bullettrain_front,bullettrain_side,bus,busstop,' +
- 'bust_in_silhouette,busts_in_silhouette,cactus,cake,calendar,calling,camel,camera,cancer,candy,capital_abcd,' +
+ 'black_large_square,black_nib,black_small_square,black_square,black_square_button,blossom,blowfish,blue_book,' +
+ 'blue_car,blue_heart,blush,boar,boat,bomb,book,bookmark,bookmark_tabs,books,boom,boot,bouquet,bow,bowling,bowtie,' +
+ 'boy,bread,bride_with_veil,bridge_at_night,briefcase,broken_heart,bug,bulb,bullettrain_front,bullettrain_side,bus,' +
+ 'busstop,bust_in_silhouette,busts_in_silhouette,cactus,cake,calendar,calling,camel,camera,cancer,candy,capital_abcd,' +
'capricorn,car,card_index,carousel_horse,cat,cat2,cd,chart,chart_with_downwards_trend,chart_with_upwards_trend,' +
'checkered_flag,cherries,cherry_blossom,chestnut,chicken,children_crossing,chocolate_bar,christmas_tree,church,' +
'cinema,circus_tent,city_sunrise,city_sunset,cl,clap,clapper,clipboard,clock1,clock10,clock1030,clock11,' +
@@ -92,16 +92,16 @@ function initializeEmoticonMap() {
'rugby_football,runner,running,running_shirt_with_sash,sa,sagittarius,sailboat,sake,sandal,santa,satellite,' +
'satisfied,saxophone,school,school_satchel,scissors,scorpius,scream,scream_cat,scroll,seat,secret,see_no_evil,' +
'seedling,seven,shaved_ice,sheep,shell,ship,shipit,shirt,shit,shoe,shower,signal_strength,six,six_pointed_star,' +
- 'ski,skull,sleeping,sleepy,slot_machine,small_blue_diamond,small_orange_diamond,small_red_triangle,' +
- 'small_red_triangle_down,smile,smile_cat,smiley,smiley_cat,smiling_imp,smirk,smirk_cat,smoking,snail,snake,' +
- 'snowboarder,snowflake,snowman,sob,soccer,soon,sos,sound,space_invader,spades,spaghetti,sparkle,sparkler,' +
- 'sparkles,sparkling_heart,speak_no_evil,speaker,speech_balloon,speedboat,squirrel,star,star2,stars,station,' +
- 'statue_of_liberty,steam_locomotive,stew,straight_ruler,strawberry,stuck_out_tongue,stuck_out_tongue_closed_eyes,' +
- 'stuck_out_tongue_winking_eye,sun_with_face,sunflower,sunglasses,sunny,sunrise,sunrise_over_mountains,surfer,' +
- 'sushi,suspect,suspension_railway,sweat,sweat_drops,sweat_smile,sweet_potato,swimmer,symbols,syringe,tada,' +
- 'tanabata_tree,tangerine,taurus,taxi,tea,telephone,telephone_receiver,telescope,tennis,tent,thought_balloon,' +
- 'three,thumbsdown,thumbsup,ticket,tiger,tiger2,tired_face,tm,toilet,tokyo_tower,tomato,tongue,top,tophat,' +
- 'tractor,traffic_light,train,train2,tram,triangular_flag_on_post,triangular_ruler,trident,triumph,trolleybus,' +
+ 'ski,skull,sleeping,sleepy,slightly_smiling_face,slightly_frowning_face,slot_machine,small_blue_diamond,' +
+ 'small_orange_diamond,small_red_triangle,small_red_triangle_down,smile,smile_cat,smiley,smiley_cat,smiling_imp,' +
+ 'smirk,smirk_cat,smoking,snail,snake,snowboarder,snowflake,snowman,sob,soccer,soon,sos,sound,space_invader,spades,' +
+ 'spaghetti,sparkle,sparkler,sparkles,sparkling_heart,speak_no_evil,speaker,speech_balloon,speedboat,squirrel,star,' +
+ 'star2,stars,station,statue_of_liberty,steam_locomotive,stew,straight_ruler,strawberry,stuck_out_tongue,' +
+ 'stuck_out_tongue_closed_eyes,stuck_out_tongue_winking_eye,sun_with_face,sunflower,sunglasses,sunny,sunrise,' +
+ 'sunrise_over_mountains,surfer,sushi,suspect,suspension_railway,sweat,sweat_drops,sweat_smile,sweet_potato,swimmer,' +
+ 'symbols,syringe,tada,tanabata_tree,tangerine,taurus,taxi,tea,telephone,telephone_receiver,telescope,tennis,tent,' +
+ 'thought_balloon,three,thumbsdown,thumbsup,ticket,tiger,tiger2,tired_face,tm,toilet,tokyo_tower,tomato,tongue,top,' +
+ 'tophat,tractor,traffic_light,train,train2,tram,triangular_flag_on_post,triangular_ruler,trident,triumph,trolleybus,' +
'trollface,trophy,tropical_drink,tropical_fish,truck,trumpet,tshirt,tulip,turtle,tv,twisted_rightwards_arrows,' +
'two,two_hearts,two_men_holding_hands,two_women_holding_hands,u5272,u5408,u55b6,u6307,u6708,u6709,u6e80,u7121,' +
'u7533,u7981,u7a7a,uk,umbrella,unamused,underage,unlock,up,us,v,vertical_traffic_light,vhs,vibration_mode,' +
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index e408febd9..24d27b10a 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -617,6 +617,7 @@ export function applyTheme(theme) {
if (theme.centerChannelColor) {
changeCss('.sidebar--left, .sidebar--right .sidebar--right__header', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1);
changeCss('.app__content, .post-create__container .post-create-body .btn-file, .post-create__container .post-create-footer .msg-typing, .command-name, .modal .modal-content, .dropdown-menu, .popover, .mentions-name, .tip-overlay', 'color:' + theme.centerChannelColor, 1);
+ changeCss('#archive-link-home', 'background:' + changeOpacity(theme.centerChannelColor, 0.15), 1);
changeCss('#post-create', 'color:' + theme.centerChannelColor, 2);
changeCss('.mentions--top, .suggestion-list', 'box-shadow:' + changeOpacity(theme.centerChannelColor, 0.2) + ' 1px -3px 12px', 3);
changeCss('.mentions--top, .suggestion-list', '-webkit-box-shadow:' + changeOpacity(theme.centerChannelColor, 0.2) + ' 1px -3px 12px', 2);
@@ -647,10 +648,11 @@ export function applyTheme(theme) {
changeCss('.attachment .attachment__content', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.3), 1);
changeCss('.channel-intro .channel-intro__content, .webhooks__container', 'background:' + changeOpacity(theme.centerChannelColor, 0.05), 1);
changeCss('.date-separator .separator__text', 'color:' + theme.centerChannelColor, 2);
- changeCss('.date-separator .separator__hr, .modal-footer, .modal .custom-textarea, .post-right__container .post.post--root hr, .search-item-container', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1);
+ changeCss('.date-separator .separator__hr, .modal-footer, .modal .custom-textarea', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1);
+ changeCss('.search-item-container, .post-right__container .post.post--root', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.1), 1);
changeCss('.modal .custom-textarea:focus', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.3), 1);
changeCss('.channel-intro, .settings-modal .settings-table .settings-content .divider-dark, hr, .settings-modal .settings-table .settings-links', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1);
- changeCss('.post.current--user .post__body, .post.post--comment.other--root.current--user .post-comment, pre', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1);
+ changeCss('.post.current--user .post__body, .post.post--comment.other--root.current--user .post-comment, pre, .post-right__container .post.post--root', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1);
changeCss('.post.current--user .post__body, .post.post--comment.other--root.current--user .post-comment, .post.same--root.post--comment .post__body, .modal .more-table tbody>tr td, .member-div:first-child, .member-div, .access-history__table .access__report, .activity-log__table', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.1), 2);
changeCss('@media(max-width: 1800px){.inner__wrap.move--left .post.post--comment.same--root', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.07), 2);
changeCss('.post:hover, .modal .more-table tbody>tr:hover td, .settings-modal .settings-table .settings-content .section-min:hover', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1);
@@ -684,11 +686,11 @@ export function applyTheme(theme) {
}
if (theme.mentionHighlightBg) {
- changeCss('.mention-highlight, .search-highlight, #archive-link-home', 'background:' + theme.mentionHighlightBg, 1);
+ changeCss('.mention-highlight, .search-highlight', 'background:' + theme.mentionHighlightBg, 1);
}
if (theme.mentionHighlightBg) {
- changeCss('.post.post--highlight, #archive-link-home', 'background:' + changeOpacity(theme.mentionHighlightBg, 0.5), 1);
+ changeCss('.post.post--highlight', 'background:' + changeOpacity(theme.mentionHighlightBg, 0.5), 1);
}
if (theme.mentionHighlightLink) {
diff --git a/web/sass-files/sass/partials/_base.scss b/web/sass-files/sass/partials/_base.scss
index 4f9e1d5c7..04ba9c51e 100644
--- a/web/sass-files/sass/partials/_base.scss
+++ b/web/sass-files/sass/partials/_base.scss
@@ -125,10 +125,6 @@ a:focus, a:hover {
}
}
-select {
- -moz-appearance:none;
-}
-
.form-control {
@include border-radius(2px);
&:focus {
diff --git a/web/sass-files/sass/partials/_content.scss b/web/sass-files/sass/partials/_content.scss
index da75bc61b..b54c97b41 100644
--- a/web/sass-files/sass/partials/_content.scss
+++ b/web/sass-files/sass/partials/_content.scss
@@ -1,9 +1,7 @@
@charset "UTF-8";
.inner__wrap {
- @include single-transition(all, 0.5s, ease);
&.move--left {
- margin-right: 400px;
.search-bar__container {
display: none;
}
diff --git a/web/sass-files/sass/partials/_files.scss b/web/sass-files/sass/partials/_files.scss
index 2c341f61e..62e067437 100644
--- a/web/sass-files/sass/partials/_files.scss
+++ b/web/sass-files/sass/partials/_files.scss
@@ -257,3 +257,8 @@
@include opacity(0);
}
}
+
+.view-image__loading {
+ background: black;
+ min-height: 100px;
+}
diff --git a/web/sass-files/sass/partials/_popover.scss b/web/sass-files/sass/partials/_popover.scss
index 1ae07fe5b..8a61758f1 100644
--- a/web/sass-files/sass/partials/_popover.scss
+++ b/web/sass-files/sass/partials/_popover.scss
@@ -85,6 +85,11 @@
background: rgba(black, 0.2);
}
+ .fa {
+ margin-right: 5px;
+ @include opacity(0.5);
+ }
+
.profile-img {
margin-top: -1px;
height: 16px;
diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss
index 2f6540a4e..c2df7b769 100644
--- a/web/sass-files/sass/partials/_post.scss
+++ b/web/sass-files/sass/partials/_post.scss
@@ -232,12 +232,12 @@ body.ios {
}
.more-messages-text {
- margin-top: 2px;
- margin-bottom: 5px;
+ margin: 5px 0 10px;
display: block;
text-align: center;
outline: none;
border: none;
+ font-size: 13px;
}
.beginning-messages-text {
margin-top: 2px;
@@ -546,6 +546,15 @@ body.ios {
&.post--comment {
+ .popover {
+
+ margin-top: 84px;
+
+ > .arrow {
+ top: 21px !important;
+ }
+ }
+
.post__header {
.col__reply {
@@ -719,7 +728,7 @@ body.ios {
}
.post__time {
- font-size: 13px;
+ font-size: 0.9em;
}
.post__time, &.post--system .post__body {
diff --git a/web/sass-files/sass/partials/_post_right.scss b/web/sass-files/sass/partials/_post_right.scss
index fa52e2972..d820447f5 100644
--- a/web/sass-files/sass/partials/_post_right.scss
+++ b/web/sass-files/sass/partials/_post_right.scss
@@ -17,7 +17,8 @@
.post {
&.post--root {
- padding-bottom: 0;
+ padding-bottom: 1.2em;
+ border-bottom: 1px solid #ddd;
}
.post__header {
@@ -36,6 +37,7 @@
hr {
margin-bottom: 0;
+ border: none;
}
.post-create__container {
diff --git a/web/sass-files/sass/partials/_responsive.scss b/web/sass-files/sass/partials/_responsive.scss
index c493c6aeb..635b46077 100644
--- a/web/sass-files/sass/partials/_responsive.scss
+++ b/web/sass-files/sass/partials/_responsive.scss
@@ -56,6 +56,7 @@
.sidebar--right {
z-index: 5;
@include translateX(100%);
+ @include single-transition(all, 0.5s, ease);
&.move--left {
@include translateX(0);
@@ -339,7 +340,10 @@
}
}
.settings-table {
- .nav, .nav.absolute {
+ .nav {
+ &.position--top {
+ top: auto;
+ }
position: relative;
top: auto;
width: 100%;
@@ -628,6 +632,7 @@
height: calc(100% - 44px);
}
.inner__wrap {
+ @include single-transition(all, 0.5s, ease);
&.move--right {
@include translate3d(290px, 0, 0);
&:before {
diff --git a/web/sass-files/sass/partials/_search.scss b/web/sass-files/sass/partials/_search.scss
index 0d9d7b50d..cb125bff0 100644
--- a/web/sass-files/sass/partials/_search.scss
+++ b/web/sass-files/sass/partials/_search.scss
@@ -18,6 +18,12 @@
z-index: 5;
cursor: pointer;
}
+
+.search-item-snippet {
+ @include clearfix;
+ text-overflow: ellipsis;
+}
+
.sidebar__collapse {
cursor: pointer;
z-index: 5;
@@ -134,7 +140,8 @@
}
.search-item-time {
- color: #a8adb7;
+ @include opacity(0.7);
+ font-size: 0.9em;
}
.search-results-none {
diff --git a/web/sass-files/sass/partials/_settings.scss b/web/sass-files/sass/partials/_settings.scss
index 473ffb28d..bd47ca960 100644
--- a/web/sass-files/sass/partials/_settings.scss
+++ b/web/sass-files/sass/partials/_settings.scss
@@ -82,9 +82,8 @@
.nav {
position: fixed;
width: 179px;
- &.absolute {
- position: absolute;
- top: 0;
+ &.position--top {
+ top: 57px;
}
}
.security-links {
@@ -141,144 +140,167 @@
width: 29px;
}
}
- .premade-themes {
- margin-bottom: 10px;
- .theme-label {
- font-weight: 400;
- margin-top: 5px;
- }
- img {
- border: 3px solid transparent;
+ .group--code {
+ select {
+ padding-right: 25px;
}
- .active {
- img {
- border-color: $primary-color;
- }
+ &:before {
+ position: absolute;
+ top: 11px;
+ right: 50px;
+ z-index: 5;
+ content: "\f0d7";
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
}
+ select {
+ -moz-appearance:none;
+ -webkit-appearance:none;
+ appearance:none;
+ }
+ }
+ .premade-themes {
+ margin-bottom: 10px;
+ .theme-label {
+ font-weight: 400;
+ margin-top: 5px;
}
- .custom-label {
- font-weight: normal;
- font-size: 13px;
- width: 100%;
- overflow: hidden;
- text-overflow: ellipsis;
- margin-bottom: 0;
- }
- .input-group-addon {
- background: transparent;
+ img {
+ border: 3px solid transparent;
}
- .radio {
- label {
- font-weight: 600;
+ .active {
+ img {
+ border-color: $primary-color;
}
}
}
-
- .section-title {
- margin-bottom: 5px;
- font-weight: 600;
+ .custom-label {
+ font-weight: normal;
+ font-size: 13px;
+ width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-bottom: 0;
}
-
- .section-edit {
- text-align: right;
- margin-bottom: 5px;
- .fa {
- margin-right: 5px;
- font-size: 12px;
- @include opacity(0.5);
- display: none;
+ .input-group-addon {
+ background: transparent;
+ }
+ .radio {
+ label {
+ font-weight: 600;
}
}
+ }
- .section-describe {
- @include opacity(0.7);
- white-space:pre;
- }
+ .section-title {
+ margin-bottom: 5px;
+ font-weight: 600;
+ }
- .divider-dark {
- border-bottom:1px solid #aaaaaa;
+ .section-edit {
+ text-align: right;
+ margin-bottom: 5px;
+ .fa {
+ margin-right: 5px;
+ font-size: 12px;
+ @include opacity(0.5);
+ display: none;
}
+ }
- .divider-light {
- border-bottom:1px solid lightgrey;
- }
+ .section-describe {
+ @include opacity(0.7);
+ white-space:pre;
+ }
- .setting-list {
- padding: 0;
- list-style-type:none;
- }
+ .divider-dark {
+ border-bottom:1px solid #aaaaaa;
+ }
- .setting-list__hint {
- margin-top: 20px;
- }
+ .divider-light {
+ border-bottom:1px solid lightgrey;
+ }
- .mentions-input {
- margin-top: 10px;
- }
+ .setting-list {
+ padding: 0;
+ list-style-type:none;
+ }
- .setting-list-item {
- margin-top:7px;
- }
- .has-error {
- color: #a94442;
- }
+ .setting-list__hint {
+ margin-top: 20px;
+ }
- .file-status {
- font-size: 13px;
- margin-top: 8px;
- color: #555;
- }
+ .mentions-input {
+ margin-top: 10px;
+ }
- .confirm-import {
- padding: 4px 10px;
- margin: 10px 0;
- }
+ .setting-list-item {
+ margin-top:7px;
+ }
+ .has-error {
+ color: #a94442;
+ }
+ .file-status {
+ font-size: 13px;
+ margin-top: 8px;
+ color: #555;
}
+
+ .confirm-import {
+ padding: 4px 10px;
+ margin: 10px 0;
+ }
+
}
- .nav-pills {
- > li {
- margin: 0;
+}
+.nav-pills {
+ > li {
+ margin: 0;
+ a {
+ border-radius: 0;
+ color: #777;
+ }
+ .glyphicon {
+ width: 25px;
+ top: 2px;
+ }
+ &:hover {
a {
- border-radius: 0;
- color: #777;
+ background: #E6F2FA;
}
- .glyphicon {
- width: 25px;
- top: 2px;
- }
- &:hover {
- a {
- background: #E6F2FA;
+ }
+ &.active {
+ a {
+ color: #111;
+ background-color: #E1E1E1;
+ &:before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 5px;
+ height: 100%;
+ background: #000;
}
}
- &.active {
- a {
- color: #111;
- background-color: #E1E1E1;
- &:before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- width: 5px;
- height: 100%;
- background: #000;
- }
- }
- a, a:hover, a:focus {
- padding-right: 10px;
- background-color: rgba(black, 0.1);
- border-radius: 0;
- font-weight: 400;
- position: relative;
- }
+ a, a:hover, a:focus {
+ padding-right: 10px;
+ background-color: rgba(black, 0.1);
+ border-radius: 0;
+ font-weight: 400;
+ position: relative;
}
}
}
- h3 {
- font-size: em(20px);
- }
+}
+h3 {
+ font-size: em(20px);
+}
}
.channel-settings {
diff --git a/web/sass-files/sass/partials/_sidebar--left.scss b/web/sass-files/sass/partials/_sidebar--left.scss
index b16ac31f7..e99e21257 100644
--- a/web/sass-files/sass/partials/_sidebar--left.scss
+++ b/web/sass-files/sass/partials/_sidebar--left.scss
@@ -44,6 +44,9 @@
display: inline-block;
i, path {
@include opacity(0.5);
+ &.online--icon {
+ @include opacity(1);
+ }
}
.fa-lock {
margin-left: 1px;
@@ -52,9 +55,6 @@
top: -1px;
position: relative;
}
- .online--icon {
- fill: #7DBE00;
- }
}
.nav-pills__container {
height: 100%;
diff --git a/web/sass-files/sass/partials/_sidebar--right.scss b/web/sass-files/sass/partials/_sidebar--right.scss
index e39f7730b..f40a50b03 100644
--- a/web/sass-files/sass/partials/_sidebar--right.scss
+++ b/web/sass-files/sass/partials/_sidebar--right.scss
@@ -7,13 +7,7 @@
right: 0px;
padding: 0;
background: #fff;
- @include single-transition(transform, 0.5s, ease);
@include translateX(400px);
-
- &.move--left {
- @include translateX(0);
- }
-
.post-body {
img {
diff --git a/web/static/js/velocity.min.js b/web/static/js/velocity.min.js
new file mode 100644
index 000000000..100360353
--- /dev/null
+++ b/web/static/js/velocity.min.js
@@ -0,0 +1,4 @@
+/*! VelocityJS.org (1.2.3). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */
+/*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */
+!function(a){function b(a){var b=a.length,d=c.type(a);return"function"===d||c.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===d||0===b||"number"==typeof b&&b>0&&b-1 in a}if(!a.jQuery){var c=function(a,b){return new c.fn.init(a,b)};c.isWindow=function(a){return null!=a&&a==a.window},c.type=function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?e[g.call(a)]||"object":typeof a},c.isArray=Array.isArray||function(a){return"array"===c.type(a)},c.isPlainObject=function(a){var b;if(!a||"object"!==c.type(a)||a.nodeType||c.isWindow(a))return!1;try{if(a.constructor&&!f.call(a,"constructor")&&!f.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(d){return!1}for(b in a);return void 0===b||f.call(a,b)},c.each=function(a,c,d){var e,f=0,g=a.length,h=b(a);if(d){if(h)for(;g>f&&(e=c.apply(a[f],d),e!==!1);f++);else for(f in a)if(e=c.apply(a[f],d),e===!1)break}else if(h)for(;g>f&&(e=c.call(a[f],f,a[f]),e!==!1);f++);else for(f in a)if(e=c.call(a[f],f,a[f]),e===!1)break;return a},c.data=function(a,b,e){if(void 0===e){var f=a[c.expando],g=f&&d[f];if(void 0===b)return g;if(g&&b in g)return g[b]}else if(void 0!==b){var f=a[c.expando]||(a[c.expando]=++c.uuid);return d[f]=d[f]||{},d[f][b]=e,e}},c.removeData=function(a,b){var e=a[c.expando],f=e&&d[e];f&&c.each(b,function(a,b){delete f[b]})},c.extend=function(){var a,b,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;for("boolean"==typeof h&&(k=h,h=arguments[i]||{},i++),"object"!=typeof h&&"function"!==c.type(h)&&(h={}),i===j&&(h=this,i--);j>i;i++)if(null!=(f=arguments[i]))for(e in f)a=h[e],d=f[e],h!==d&&(k&&d&&(c.isPlainObject(d)||(b=c.isArray(d)))?(b?(b=!1,g=a&&c.isArray(a)?a:[]):g=a&&c.isPlainObject(a)?a:{},h[e]=c.extend(k,g,d)):void 0!==d&&(h[e]=d));return h},c.queue=function(a,d,e){function f(a,c){var d=c||[];return null!=a&&(b(Object(a))?!function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;)a[e++]=b[d++];if(c!==c)for(;void 0!==b[d];)a[e++]=b[d++];return a.length=e,a}(d,"string"==typeof a?[a]:a):[].push.call(d,a)),d}if(a){d=(d||"fx")+"queue";var g=c.data(a,d);return e?(!g||c.isArray(e)?g=c.data(a,d,f(e)):g.push(e),g):g||[]}},c.dequeue=function(a,b){c.each(a.nodeType?[a]:a,function(a,d){b=b||"fx";var e=c.queue(d,b),f=e.shift();"inprogress"===f&&(f=e.shift()),f&&("fx"===b&&e.unshift("inprogress"),f.call(d,function(){c.dequeue(d,b)}))})},c.fn=c.prototype={init:function(a){if(a.nodeType)return this[0]=a,this;throw new Error("Not a DOM node.")},offset:function(){var b=this[0].getBoundingClientRect?this[0].getBoundingClientRect():{top:0,left:0};return{top:b.top+(a.pageYOffset||document.scrollTop||0)-(document.clientTop||0),left:b.left+(a.pageXOffset||document.scrollLeft||0)-(document.clientLeft||0)}},position:function(){function a(){for(var a=this.offsetParent||document;a&&"html"===!a.nodeType.toLowerCase&&"static"===a.style.position;)a=a.offsetParent;return a||document}var b=this[0],a=a.apply(b),d=this.offset(),e=/^(?:body|html)$/i.test(a.nodeName)?{top:0,left:0}:c(a).offset();return d.top-=parseFloat(b.style.marginTop)||0,d.left-=parseFloat(b.style.marginLeft)||0,a.style&&(e.top+=parseFloat(a.style.borderTopWidth)||0,e.left+=parseFloat(a.style.borderLeftWidth)||0),{top:d.top-e.top,left:d.left-e.left}}};var d={};c.expando="velocity"+(new Date).getTime(),c.uuid=0;for(var e={},f=e.hasOwnProperty,g=e.toString,h="Boolean Number String Function Array Date RegExp Object Error".split(" "),i=0;i<h.length;i++)e["[object "+h[i]+"]"]=h[i].toLowerCase();c.fn.init.prototype=c.fn,a.Velocity={Utilities:c}}}(window),function(a){"object"==typeof module&&"object"==typeof module.exports?module.exports=a():"function"==typeof define&&define.amd?define(a):a()}(function(){return function(a,b,c,d){function e(a){for(var b=-1,c=a?a.length:0,d=[];++b<c;){var e=a[b];e&&d.push(e)}return d}function f(a){return p.isWrapped(a)?a=[].slice.call(a):p.isNode(a)&&(a=[a]),a}function g(a){var b=m.data(a,"velocity");return null===b?d:b}function h(a){return function(b){return Math.round(b*a)*(1/a)}}function i(a,c,d,e){function f(a,b){return 1-3*b+3*a}function g(a,b){return 3*b-6*a}function h(a){return 3*a}function i(a,b,c){return((f(b,c)*a+g(b,c))*a+h(b))*a}function j(a,b,c){return 3*f(b,c)*a*a+2*g(b,c)*a+h(b)}function k(b,c){for(var e=0;p>e;++e){var f=j(c,a,d);if(0===f)return c;var g=i(c,a,d)-b;c-=g/f}return c}function l(){for(var b=0;t>b;++b)x[b]=i(b*u,a,d)}function m(b,c,e){var f,g,h=0;do g=c+(e-c)/2,f=i(g,a,d)-b,f>0?e=g:c=g;while(Math.abs(f)>r&&++h<s);return g}function n(b){for(var c=0,e=1,f=t-1;e!=f&&x[e]<=b;++e)c+=u;--e;var g=(b-x[e])/(x[e+1]-x[e]),h=c+g*u,i=j(h,a,d);return i>=q?k(b,h):0==i?h:m(b,c,c+u)}function o(){y=!0,(a!=c||d!=e)&&l()}var p=4,q=.001,r=1e-7,s=10,t=11,u=1/(t-1),v="Float32Array"in b;if(4!==arguments.length)return!1;for(var w=0;4>w;++w)if("number"!=typeof arguments[w]||isNaN(arguments[w])||!isFinite(arguments[w]))return!1;a=Math.min(a,1),d=Math.min(d,1),a=Math.max(a,0),d=Math.max(d,0);var x=v?new Float32Array(t):new Array(t),y=!1,z=function(b){return y||o(),a===c&&d===e?b:0===b?0:1===b?1:i(n(b),c,e)};z.getControlPoints=function(){return[{x:a,y:c},{x:d,y:e}]};var A="generateBezier("+[a,c,d,e]+")";return z.toString=function(){return A},z}function j(a,b){var c=a;return p.isString(a)?t.Easings[a]||(c=!1):c=p.isArray(a)&&1===a.length?h.apply(null,a):p.isArray(a)&&2===a.length?u.apply(null,a.concat([b])):p.isArray(a)&&4===a.length?i.apply(null,a):!1,c===!1&&(c=t.Easings[t.defaults.easing]?t.defaults.easing:s),c}function k(a){if(a){var b=(new Date).getTime(),c=t.State.calls.length;c>1e4&&(t.State.calls=e(t.State.calls));for(var f=0;c>f;f++)if(t.State.calls[f]){var h=t.State.calls[f],i=h[0],j=h[2],n=h[3],o=!!n,q=null;n||(n=t.State.calls[f][3]=b-16);for(var r=Math.min((b-n)/j.duration,1),s=0,u=i.length;u>s;s++){var w=i[s],y=w.element;if(g(y)){var z=!1;if(j.display!==d&&null!==j.display&&"none"!==j.display){if("flex"===j.display){var A=["-webkit-box","-moz-box","-ms-flexbox","-webkit-flex"];m.each(A,function(a,b){v.setPropertyValue(y,"display",b)})}v.setPropertyValue(y,"display",j.display)}j.visibility!==d&&"hidden"!==j.visibility&&v.setPropertyValue(y,"visibility",j.visibility);for(var B in w)if("element"!==B){var C,D=w[B],E=p.isString(D.easing)?t.Easings[D.easing]:D.easing;if(1===r)C=D.endValue;else{var F=D.endValue-D.startValue;if(C=D.startValue+F*E(r,j,F),!o&&C===D.currentValue)continue}if(D.currentValue=C,"tween"===B)q=C;else{if(v.Hooks.registered[B]){var G=v.Hooks.getRoot(B),H=g(y).rootPropertyValueCache[G];H&&(D.rootPropertyValue=H)}var I=v.setPropertyValue(y,B,D.currentValue+(0===parseFloat(C)?"":D.unitType),D.rootPropertyValue,D.scrollData);v.Hooks.registered[B]&&(g(y).rootPropertyValueCache[G]=v.Normalizations.registered[G]?v.Normalizations.registered[G]("extract",null,I[1]):I[1]),"transform"===I[0]&&(z=!0)}}j.mobileHA&&g(y).transformCache.translate3d===d&&(g(y).transformCache.translate3d="(0px, 0px, 0px)",z=!0),z&&v.flushTransformCache(y)}}j.display!==d&&"none"!==j.display&&(t.State.calls[f][2].display=!1),j.visibility!==d&&"hidden"!==j.visibility&&(t.State.calls[f][2].visibility=!1),j.progress&&j.progress.call(h[1],h[1],r,Math.max(0,n+j.duration-b),n,q),1===r&&l(f)}}t.State.isTicking&&x(k)}function l(a,b){if(!t.State.calls[a])return!1;for(var c=t.State.calls[a][0],e=t.State.calls[a][1],f=t.State.calls[a][2],h=t.State.calls[a][4],i=!1,j=0,k=c.length;k>j;j++){var l=c[j].element;if(b||f.loop||("none"===f.display&&v.setPropertyValue(l,"display",f.display),"hidden"===f.visibility&&v.setPropertyValue(l,"visibility",f.visibility)),f.loop!==!0&&(m.queue(l)[1]===d||!/\.velocityQueueEntryFlag/i.test(m.queue(l)[1]))&&g(l)){g(l).isAnimating=!1,g(l).rootPropertyValueCache={};var n=!1;m.each(v.Lists.transforms3D,function(a,b){var c=/^scale/.test(b)?1:0,e=g(l).transformCache[b];g(l).transformCache[b]!==d&&new RegExp("^\\("+c+"[^.]").test(e)&&(n=!0,delete g(l).transformCache[b])}),f.mobileHA&&(n=!0,delete g(l).transformCache.translate3d),n&&v.flushTransformCache(l),v.Values.removeClass(l,"velocity-animating")}if(!b&&f.complete&&!f.loop&&j===k-1)try{f.complete.call(e,e)}catch(o){setTimeout(function(){throw o},1)}h&&f.loop!==!0&&h(e),g(l)&&f.loop===!0&&!b&&(m.each(g(l).tweensContainer,function(a,b){/^rotate/.test(a)&&360===parseFloat(b.endValue)&&(b.endValue=0,b.startValue=360),/^backgroundPosition/.test(a)&&100===parseFloat(b.endValue)&&"%"===b.unitType&&(b.endValue=0,b.startValue=100)}),t(l,"reverse",{loop:!0,delay:f.delay})),f.queue!==!1&&m.dequeue(l,f.queue)}t.State.calls[a]=!1;for(var p=0,q=t.State.calls.length;q>p;p++)if(t.State.calls[p]!==!1){i=!0;break}i===!1&&(t.State.isTicking=!1,delete t.State.calls,t.State.calls=[])}var m,n=function(){if(c.documentMode)return c.documentMode;for(var a=7;a>4;a--){var b=c.createElement("div");if(b.innerHTML="<!--[if IE "+a+"]><span></span><![endif]-->",b.getElementsByTagName("span").length)return b=null,a}return d}(),o=function(){var a=0;return b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame||function(b){var c,d=(new Date).getTime();return c=Math.max(0,16-(d-a)),a=d+c,setTimeout(function(){b(d+c)},c)}}(),p={isString:function(a){return"string"==typeof a},isArray:Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)},isFunction:function(a){return"[object Function]"===Object.prototype.toString.call(a)},isNode:function(a){return a&&a.nodeType},isNodeList:function(a){return"object"==typeof a&&/^\[object (HTMLCollection|NodeList|Object)\]$/.test(Object.prototype.toString.call(a))&&a.length!==d&&(0===a.length||"object"==typeof a[0]&&a[0].nodeType>0)},isWrapped:function(a){return a&&(a.jquery||b.Zepto&&b.Zepto.zepto.isZ(a))},isSVG:function(a){return b.SVGElement&&a instanceof b.SVGElement},isEmptyObject:function(a){for(var b in a)return!1;return!0}},q=!1;if(a.fn&&a.fn.jquery?(m=a,q=!0):m=b.Velocity.Utilities,8>=n&&!q)throw new Error("Velocity: IE8 and below require jQuery to be loaded before Velocity.");if(7>=n)return void(jQuery.fn.velocity=jQuery.fn.animate);var r=400,s="swing",t={State:{isMobile:/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),isAndroid:/Android/i.test(navigator.userAgent),isGingerbread:/Android 2\.3\.[3-7]/i.test(navigator.userAgent),isChrome:b.chrome,isFirefox:/Firefox/i.test(navigator.userAgent),prefixElement:c.createElement("div"),prefixMatches:{},scrollAnchor:null,scrollPropertyLeft:null,scrollPropertyTop:null,isTicking:!1,calls:[]},CSS:{},Utilities:m,Redirects:{},Easings:{},Promise:b.Promise,defaults:{queue:"",duration:r,easing:s,begin:d,complete:d,progress:d,display:d,visibility:d,loop:!1,delay:!1,mobileHA:!0,_cacheValues:!0},init:function(a){m.data(a,"velocity",{isSVG:p.isSVG(a),isAnimating:!1,computedStyle:null,tweensContainer:null,rootPropertyValueCache:{},transformCache:{}})},hook:null,mock:!1,version:{major:1,minor:2,patch:2},debug:!1};b.pageYOffset!==d?(t.State.scrollAnchor=b,t.State.scrollPropertyLeft="pageXOffset",t.State.scrollPropertyTop="pageYOffset"):(t.State.scrollAnchor=c.documentElement||c.body.parentNode||c.body,t.State.scrollPropertyLeft="scrollLeft",t.State.scrollPropertyTop="scrollTop");var u=function(){function a(a){return-a.tension*a.x-a.friction*a.v}function b(b,c,d){var e={x:b.x+d.dx*c,v:b.v+d.dv*c,tension:b.tension,friction:b.friction};return{dx:e.v,dv:a(e)}}function c(c,d){var e={dx:c.v,dv:a(c)},f=b(c,.5*d,e),g=b(c,.5*d,f),h=b(c,d,g),i=1/6*(e.dx+2*(f.dx+g.dx)+h.dx),j=1/6*(e.dv+2*(f.dv+g.dv)+h.dv);return c.x=c.x+i*d,c.v=c.v+j*d,c}return function d(a,b,e){var f,g,h,i={x:-1,v:0,tension:null,friction:null},j=[0],k=0,l=1e-4,m=.016;for(a=parseFloat(a)||500,b=parseFloat(b)||20,e=e||null,i.tension=a,i.friction=b,f=null!==e,f?(k=d(a,b),g=k/e*m):g=m;;)if(h=c(h||i,g),j.push(1+h.x),k+=16,!(Math.abs(h.x)>l&&Math.abs(h.v)>l))break;return f?function(a){return j[a*(j.length-1)|0]}:k}}();t.Easings={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},spring:function(a){return 1-Math.cos(4.5*a*Math.PI)*Math.exp(6*-a)}},m.each([["ease",[.25,.1,.25,1]],["ease-in",[.42,0,1,1]],["ease-out",[0,0,.58,1]],["ease-in-out",[.42,0,.58,1]],["easeInSine",[.47,0,.745,.715]],["easeOutSine",[.39,.575,.565,1]],["easeInOutSine",[.445,.05,.55,.95]],["easeInQuad",[.55,.085,.68,.53]],["easeOutQuad",[.25,.46,.45,.94]],["easeInOutQuad",[.455,.03,.515,.955]],["easeInCubic",[.55,.055,.675,.19]],["easeOutCubic",[.215,.61,.355,1]],["easeInOutCubic",[.645,.045,.355,1]],["easeInQuart",[.895,.03,.685,.22]],["easeOutQuart",[.165,.84,.44,1]],["easeInOutQuart",[.77,0,.175,1]],["easeInQuint",[.755,.05,.855,.06]],["easeOutQuint",[.23,1,.32,1]],["easeInOutQuint",[.86,0,.07,1]],["easeInExpo",[.95,.05,.795,.035]],["easeOutExpo",[.19,1,.22,1]],["easeInOutExpo",[1,0,0,1]],["easeInCirc",[.6,.04,.98,.335]],["easeOutCirc",[.075,.82,.165,1]],["easeInOutCirc",[.785,.135,.15,.86]]],function(a,b){t.Easings[b[0]]=i.apply(null,b[1])});var v=t.CSS={RegEx:{isHex:/^#([A-f\d]{3}){1,2}$/i,valueUnwrap:/^[A-z]+\((.*)\)$/i,wrappedValueAlreadyExtracted:/[0-9.]+ [0-9.]+ [0-9.]+( [0-9.]+)?/,valueSplit:/([A-z]+\(.+\))|(([A-z0-9#-.]+?)(?=\s|$))/gi},Lists:{colors:["fill","stroke","stopColor","color","backgroundColor","borderColor","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor","outlineColor"],transformsBase:["translateX","translateY","scale","scaleX","scaleY","skewX","skewY","rotateZ"],transforms3D:["transformPerspective","translateZ","scaleZ","rotateX","rotateY"]},Hooks:{templates:{textShadow:["Color X Y Blur","black 0px 0px 0px"],boxShadow:["Color X Y Blur Spread","black 0px 0px 0px 0px"],clip:["Top Right Bottom Left","0px 0px 0px 0px"],backgroundPosition:["X Y","0% 0%"],transformOrigin:["X Y Z","50% 50% 0px"],perspectiveOrigin:["X Y","50% 50%"]},registered:{},register:function(){for(var a=0;a<v.Lists.colors.length;a++){var b="color"===v.Lists.colors[a]?"0 0 0 1":"255 255 255 1";v.Hooks.templates[v.Lists.colors[a]]=["Red Green Blue Alpha",b]}var c,d,e;if(n)for(c in v.Hooks.templates){d=v.Hooks.templates[c],e=d[0].split(" ");var f=d[1].match(v.RegEx.valueSplit);"Color"===e[0]&&(e.push(e.shift()),f.push(f.shift()),v.Hooks.templates[c]=[e.join(" "),f.join(" ")])}for(c in v.Hooks.templates){d=v.Hooks.templates[c],e=d[0].split(" ");for(var a in e){var g=c+e[a],h=a;v.Hooks.registered[g]=[c,h]}}},getRoot:function(a){var b=v.Hooks.registered[a];return b?b[0]:a},cleanRootPropertyValue:function(a,b){return v.RegEx.valueUnwrap.test(b)&&(b=b.match(v.RegEx.valueUnwrap)[1]),v.Values.isCSSNullValue(b)&&(b=v.Hooks.templates[a][1]),b},extractValue:function(a,b){var c=v.Hooks.registered[a];if(c){var d=c[0],e=c[1];return b=v.Hooks.cleanRootPropertyValue(d,b),b.toString().match(v.RegEx.valueSplit)[e]}return b},injectValue:function(a,b,c){var d=v.Hooks.registered[a];if(d){var e,f,g=d[0],h=d[1];return c=v.Hooks.cleanRootPropertyValue(g,c),e=c.toString().match(v.RegEx.valueSplit),e[h]=b,f=e.join(" ")}return c}},Normalizations:{registered:{clip:function(a,b,c){switch(a){case"name":return"clip";case"extract":var d;return v.RegEx.wrappedValueAlreadyExtracted.test(c)?d=c:(d=c.toString().match(v.RegEx.valueUnwrap),d=d?d[1].replace(/,(\s+)?/g," "):c),d;case"inject":return"rect("+c+")"}},blur:function(a,b,c){switch(a){case"name":return t.State.isFirefox?"filter":"-webkit-filter";case"extract":var d=parseFloat(c);if(!d&&0!==d){var e=c.toString().match(/blur\(([0-9]+[A-z]+)\)/i);d=e?e[1]:0}return d;case"inject":return parseFloat(c)?"blur("+c+")":"none"}},opacity:function(a,b,c){if(8>=n)switch(a){case"name":return"filter";case"extract":var d=c.toString().match(/alpha\(opacity=(.*)\)/i);return c=d?d[1]/100:1;case"inject":return b.style.zoom=1,parseFloat(c)>=1?"":"alpha(opacity="+parseInt(100*parseFloat(c),10)+")"}else switch(a){case"name":return"opacity";case"extract":return c;case"inject":return c}}},register:function(){9>=n||t.State.isGingerbread||(v.Lists.transformsBase=v.Lists.transformsBase.concat(v.Lists.transforms3D));for(var a=0;a<v.Lists.transformsBase.length;a++)!function(){var b=v.Lists.transformsBase[a];v.Normalizations.registered[b]=function(a,c,e){switch(a){case"name":return"transform";case"extract":return g(c)===d||g(c).transformCache[b]===d?/^scale/i.test(b)?1:0:g(c).transformCache[b].replace(/[()]/g,"");case"inject":var f=!1;switch(b.substr(0,b.length-1)){case"translate":f=!/(%|px|em|rem|vw|vh|\d)$/i.test(e);break;case"scal":case"scale":t.State.isAndroid&&g(c).transformCache[b]===d&&1>e&&(e=1),f=!/(\d)$/i.test(e);break;case"skew":f=!/(deg|\d)$/i.test(e);break;case"rotate":f=!/(deg|\d)$/i.test(e)}return f||(g(c).transformCache[b]="("+e+")"),g(c).transformCache[b]}}}();for(var a=0;a<v.Lists.colors.length;a++)!function(){var b=v.Lists.colors[a];v.Normalizations.registered[b]=function(a,c,e){switch(a){case"name":return b;case"extract":var f;if(v.RegEx.wrappedValueAlreadyExtracted.test(e))f=e;else{var g,h={black:"rgb(0, 0, 0)",blue:"rgb(0, 0, 255)",gray:"rgb(128, 128, 128)",green:"rgb(0, 128, 0)",red:"rgb(255, 0, 0)",white:"rgb(255, 255, 255)"};/^[A-z]+$/i.test(e)?g=h[e]!==d?h[e]:h.black:v.RegEx.isHex.test(e)?g="rgb("+v.Values.hexToRgb(e).join(" ")+")":/^rgba?\(/i.test(e)||(g=h.black),f=(g||e).toString().match(v.RegEx.valueUnwrap)[1].replace(/,(\s+)?/g," ")}return 8>=n||3!==f.split(" ").length||(f+=" 1"),f;case"inject":return 8>=n?4===e.split(" ").length&&(e=e.split(/\s+/).slice(0,3).join(" ")):3===e.split(" ").length&&(e+=" 1"),(8>=n?"rgb":"rgba")+"("+e.replace(/\s+/g,",").replace(/\.(\d)+(?=,)/g,"")+")"}}}()}},Names:{camelCase:function(a){return a.replace(/-(\w)/g,function(a,b){return b.toUpperCase()})},SVGAttribute:function(a){var b="width|height|x|y|cx|cy|r|rx|ry|x1|x2|y1|y2";return(n||t.State.isAndroid&&!t.State.isChrome)&&(b+="|transform"),new RegExp("^("+b+")$","i").test(a)},prefixCheck:function(a){if(t.State.prefixMatches[a])return[t.State.prefixMatches[a],!0];for(var b=["","Webkit","Moz","ms","O"],c=0,d=b.length;d>c;c++){var e;if(e=0===c?a:b[c]+a.replace(/^\w/,function(a){return a.toUpperCase()}),p.isString(t.State.prefixElement.style[e]))return t.State.prefixMatches[a]=e,[e,!0]}return[a,!1]}},Values:{hexToRgb:function(a){var b,c=/^#?([a-f\d])([a-f\d])([a-f\d])$/i,d=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;return a=a.replace(c,function(a,b,c,d){return b+b+c+c+d+d}),b=d.exec(a),b?[parseInt(b[1],16),parseInt(b[2],16),parseInt(b[3],16)]:[0,0,0]},isCSSNullValue:function(a){return 0==a||/^(none|auto|transparent|(rgba\(0, ?0, ?0, ?0\)))$/i.test(a)},getUnitType:function(a){return/^(rotate|skew)/i.test(a)?"deg":/(^(scale|scaleX|scaleY|scaleZ|alpha|flexGrow|flexHeight|zIndex|fontWeight)$)|((opacity|red|green|blue|alpha)$)/i.test(a)?"":"px"},getDisplayType:function(a){var b=a&&a.tagName.toString().toLowerCase();return/^(b|big|i|small|tt|abbr|acronym|cite|code|dfn|em|kbd|strong|samp|var|a|bdo|br|img|map|object|q|script|span|sub|sup|button|input|label|select|textarea)$/i.test(b)?"inline":/^(li)$/i.test(b)?"list-item":/^(tr)$/i.test(b)?"table-row":/^(table)$/i.test(b)?"table":/^(tbody)$/i.test(b)?"table-row-group":"block"},addClass:function(a,b){a.classList?a.classList.add(b):a.className+=(a.className.length?" ":"")+b},removeClass:function(a,b){a.classList?a.classList.remove(b):a.className=a.className.toString().replace(new RegExp("(^|\\s)"+b.split(" ").join("|")+"(\\s|$)","gi")," ")}},getPropertyValue:function(a,c,e,f){function h(a,c){function e(){j&&v.setPropertyValue(a,"display","none")}var i=0;if(8>=n)i=m.css(a,c);else{var j=!1;if(/^(width|height)$/.test(c)&&0===v.getPropertyValue(a,"display")&&(j=!0,v.setPropertyValue(a,"display",v.Values.getDisplayType(a))),!f){if("height"===c&&"border-box"!==v.getPropertyValue(a,"boxSizing").toString().toLowerCase()){var k=a.offsetHeight-(parseFloat(v.getPropertyValue(a,"borderTopWidth"))||0)-(parseFloat(v.getPropertyValue(a,"borderBottomWidth"))||0)-(parseFloat(v.getPropertyValue(a,"paddingTop"))||0)-(parseFloat(v.getPropertyValue(a,"paddingBottom"))||0);return e(),k}if("width"===c&&"border-box"!==v.getPropertyValue(a,"boxSizing").toString().toLowerCase()){var l=a.offsetWidth-(parseFloat(v.getPropertyValue(a,"borderLeftWidth"))||0)-(parseFloat(v.getPropertyValue(a,"borderRightWidth"))||0)-(parseFloat(v.getPropertyValue(a,"paddingLeft"))||0)-(parseFloat(v.getPropertyValue(a,"paddingRight"))||0);return e(),l}}var o;o=g(a)===d?b.getComputedStyle(a,null):g(a).computedStyle?g(a).computedStyle:g(a).computedStyle=b.getComputedStyle(a,null),"borderColor"===c&&(c="borderTopColor"),i=9===n&&"filter"===c?o.getPropertyValue(c):o[c],(""===i||null===i)&&(i=a.style[c]),e()}if("auto"===i&&/^(top|right|bottom|left)$/i.test(c)){var p=h(a,"position");("fixed"===p||"absolute"===p&&/top|left/i.test(c))&&(i=m(a).position()[c]+"px")}return i}var i;if(v.Hooks.registered[c]){var j=c,k=v.Hooks.getRoot(j);e===d&&(e=v.getPropertyValue(a,v.Names.prefixCheck(k)[0])),v.Normalizations.registered[k]&&(e=v.Normalizations.registered[k]("extract",a,e)),i=v.Hooks.extractValue(j,e)}else if(v.Normalizations.registered[c]){var l,o;l=v.Normalizations.registered[c]("name",a),"transform"!==l&&(o=h(a,v.Names.prefixCheck(l)[0]),v.Values.isCSSNullValue(o)&&v.Hooks.templates[c]&&(o=v.Hooks.templates[c][1])),i=v.Normalizations.registered[c]("extract",a,o)}if(!/^[\d-]/.test(i))if(g(a)&&g(a).isSVG&&v.Names.SVGAttribute(c))if(/^(height|width)$/i.test(c))try{i=a.getBBox()[c]}catch(p){i=0}else i=a.getAttribute(c);else i=h(a,v.Names.prefixCheck(c)[0]);return v.Values.isCSSNullValue(i)&&(i=0),t.debug>=2&&console.log("Get "+c+": "+i),i},setPropertyValue:function(a,c,d,e,f){var h=c;if("scroll"===c)f.container?f.container["scroll"+f.direction]=d:"Left"===f.direction?b.scrollTo(d,f.alternateValue):b.scrollTo(f.alternateValue,d);else if(v.Normalizations.registered[c]&&"transform"===v.Normalizations.registered[c]("name",a))v.Normalizations.registered[c]("inject",a,d),h="transform",d=g(a).transformCache[c];else{if(v.Hooks.registered[c]){var i=c,j=v.Hooks.getRoot(c);e=e||v.getPropertyValue(a,j),d=v.Hooks.injectValue(i,d,e),c=j}if(v.Normalizations.registered[c]&&(d=v.Normalizations.registered[c]("inject",a,d),c=v.Normalizations.registered[c]("name",a)),h=v.Names.prefixCheck(c)[0],8>=n)try{a.style[h]=d}catch(k){t.debug&&console.log("Browser does not support ["+d+"] for ["+h+"]")}else g(a)&&g(a).isSVG&&v.Names.SVGAttribute(c)?a.setAttribute(c,d):a.style[h]=d;t.debug>=2&&console.log("Set "+c+" ("+h+"): "+d)}return[h,d]},flushTransformCache:function(a){function b(b){return parseFloat(v.getPropertyValue(a,b))}var c="";if((n||t.State.isAndroid&&!t.State.isChrome)&&g(a).isSVG){var d={translate:[b("translateX"),b("translateY")],skewX:[b("skewX")],skewY:[b("skewY")],scale:1!==b("scale")?[b("scale"),b("scale")]:[b("scaleX"),b("scaleY")],rotate:[b("rotateZ"),0,0]};m.each(g(a).transformCache,function(a){/^translate/i.test(a)?a="translate":/^scale/i.test(a)?a="scale":/^rotate/i.test(a)&&(a="rotate"),d[a]&&(c+=a+"("+d[a].join(" ")+") ",delete d[a])})}else{var e,f;m.each(g(a).transformCache,function(b){return e=g(a).transformCache[b],"transformPerspective"===b?(f=e,!0):(9===n&&"rotateZ"===b&&(b="rotate"),void(c+=b+e+" "))}),f&&(c="perspective"+f+" "+c)}v.setPropertyValue(a,"transform",c)}};v.Hooks.register(),v.Normalizations.register(),t.hook=function(a,b,c){var e=d;return a=f(a),m.each(a,function(a,f){if(g(f)===d&&t.init(f),c===d)e===d&&(e=t.CSS.getPropertyValue(f,b));else{var h=t.CSS.setPropertyValue(f,b,c);"transform"===h[0]&&t.CSS.flushTransformCache(f),e=h}}),e};var w=function(){function a(){return h?B.promise||null:i}function e(){function a(){function a(a,b){var c=d,e=d,g=d;return p.isArray(a)?(c=a[0],!p.isArray(a[1])&&/^[\d-]/.test(a[1])||p.isFunction(a[1])||v.RegEx.isHex.test(a[1])?g=a[1]:(p.isString(a[1])&&!v.RegEx.isHex.test(a[1])||p.isArray(a[1]))&&(e=b?a[1]:j(a[1],h.duration),a[2]!==d&&(g=a[2]))):c=a,b||(e=e||h.easing),p.isFunction(c)&&(c=c.call(f,y,x)),p.isFunction(g)&&(g=g.call(f,y,x)),[c||0,e,g]}function l(a,b){var c,d;return d=(b||"0").toString().toLowerCase().replace(/[%A-z]+$/,function(a){return c=a,""}),c||(c=v.Values.getUnitType(a)),[d,c]}function n(){var a={myParent:f.parentNode||c.body,position:v.getPropertyValue(f,"position"),fontSize:v.getPropertyValue(f,"fontSize")},d=a.position===I.lastPosition&&a.myParent===I.lastParent,e=a.fontSize===I.lastFontSize;I.lastParent=a.myParent,I.lastPosition=a.position,I.lastFontSize=a.fontSize;var h=100,i={};if(e&&d)i.emToPx=I.lastEmToPx,i.percentToPxWidth=I.lastPercentToPxWidth,i.percentToPxHeight=I.lastPercentToPxHeight;else{var j=g(f).isSVG?c.createElementNS("http://www.w3.org/2000/svg","rect"):c.createElement("div");t.init(j),a.myParent.appendChild(j),m.each(["overflow","overflowX","overflowY"],function(a,b){t.CSS.setPropertyValue(j,b,"hidden")}),t.CSS.setPropertyValue(j,"position",a.position),t.CSS.setPropertyValue(j,"fontSize",a.fontSize),t.CSS.setPropertyValue(j,"boxSizing","content-box"),m.each(["minWidth","maxWidth","width","minHeight","maxHeight","height"],function(a,b){t.CSS.setPropertyValue(j,b,h+"%")}),t.CSS.setPropertyValue(j,"paddingLeft",h+"em"),i.percentToPxWidth=I.lastPercentToPxWidth=(parseFloat(v.getPropertyValue(j,"width",null,!0))||1)/h,i.percentToPxHeight=I.lastPercentToPxHeight=(parseFloat(v.getPropertyValue(j,"height",null,!0))||1)/h,i.emToPx=I.lastEmToPx=(parseFloat(v.getPropertyValue(j,"paddingLeft"))||1)/h,a.myParent.removeChild(j)}return null===I.remToPx&&(I.remToPx=parseFloat(v.getPropertyValue(c.body,"fontSize"))||16),null===I.vwToPx&&(I.vwToPx=parseFloat(b.innerWidth)/100,I.vhToPx=parseFloat(b.innerHeight)/100),i.remToPx=I.remToPx,i.vwToPx=I.vwToPx,i.vhToPx=I.vhToPx,t.debug>=1&&console.log("Unit ratios: "+JSON.stringify(i),f),i}if(h.begin&&0===y)try{h.begin.call(o,o)}catch(r){setTimeout(function(){throw r},1)}if("scroll"===C){var u,w,z,A=/^x$/i.test(h.axis)?"Left":"Top",D=parseFloat(h.offset)||0;h.container?p.isWrapped(h.container)||p.isNode(h.container)?(h.container=h.container[0]||h.container,u=h.container["scroll"+A],z=u+m(f).position()[A.toLowerCase()]+D):h.container=null:(u=t.State.scrollAnchor[t.State["scrollProperty"+A]],w=t.State.scrollAnchor[t.State["scrollProperty"+("Left"===A?"Top":"Left")]],z=m(f).offset()[A.toLowerCase()]+D),i={scroll:{rootPropertyValue:!1,startValue:u,currentValue:u,endValue:z,unitType:"",easing:h.easing,scrollData:{container:h.container,direction:A,alternateValue:w}},element:f},t.debug&&console.log("tweensContainer (scroll): ",i.scroll,f)}else if("reverse"===C){if(!g(f).tweensContainer)return void m.dequeue(f,h.queue);"none"===g(f).opts.display&&(g(f).opts.display="auto"),"hidden"===g(f).opts.visibility&&(g(f).opts.visibility="visible"),g(f).opts.loop=!1,g(f).opts.begin=null,g(f).opts.complete=null,s.easing||delete h.easing,s.duration||delete h.duration,h=m.extend({},g(f).opts,h);var E=m.extend(!0,{},g(f).tweensContainer);for(var F in E)if("element"!==F){var G=E[F].startValue;E[F].startValue=E[F].currentValue=E[F].endValue,E[F].endValue=G,p.isEmptyObject(s)||(E[F].easing=h.easing),t.debug&&console.log("reverse tweensContainer ("+F+"): "+JSON.stringify(E[F]),f)}i=E}else if("start"===C){var E;g(f).tweensContainer&&g(f).isAnimating===!0&&(E=g(f).tweensContainer),m.each(q,function(b,c){if(RegExp("^"+v.Lists.colors.join("$|^")+"$").test(b)){var e=a(c,!0),f=e[0],g=e[1],h=e[2];if(v.RegEx.isHex.test(f)){for(var i=["Red","Green","Blue"],j=v.Values.hexToRgb(f),k=h?v.Values.hexToRgb(h):d,l=0;l<i.length;l++){var m=[j[l]];g&&m.push(g),k!==d&&m.push(k[l]),q[b+i[l]]=m}delete q[b]}}});for(var H in q){var K=a(q[H]),L=K[0],M=K[1],N=K[2];H=v.Names.camelCase(H);var O=v.Hooks.getRoot(H),P=!1;if(g(f).isSVG||"tween"===O||v.Names.prefixCheck(O)[1]!==!1||v.Normalizations.registered[O]!==d){(h.display!==d&&null!==h.display&&"none"!==h.display||h.visibility!==d&&"hidden"!==h.visibility)&&/opacity|filter/.test(H)&&!N&&0!==L&&(N=0),h._cacheValues&&E&&E[H]?(N===d&&(N=E[H].endValue+E[H].unitType),P=g(f).rootPropertyValueCache[O]):v.Hooks.registered[H]?N===d?(P=v.getPropertyValue(f,O),N=v.getPropertyValue(f,H,P)):P=v.Hooks.templates[O][1]:N===d&&(N=v.getPropertyValue(f,H));var Q,R,S,T=!1;if(Q=l(H,N),N=Q[0],S=Q[1],Q=l(H,L),L=Q[0].replace(/^([+-\/*])=/,function(a,b){return T=b,""}),R=Q[1],N=parseFloat(N)||0,L=parseFloat(L)||0,"%"===R&&(/^(fontSize|lineHeight)$/.test(H)?(L/=100,R="em"):/^scale/.test(H)?(L/=100,R=""):/(Red|Green|Blue)$/i.test(H)&&(L=L/100*255,R="")),/[\/*]/.test(T))R=S;else if(S!==R&&0!==N)if(0===L)R=S;else{e=e||n();var U=/margin|padding|left|right|width|text|word|letter/i.test(H)||/X$/.test(H)||"x"===H?"x":"y";switch(S){case"%":N*="x"===U?e.percentToPxWidth:e.percentToPxHeight;break;case"px":break;default:N*=e[S+"ToPx"]}switch(R){case"%":N*=1/("x"===U?e.percentToPxWidth:e.percentToPxHeight);break;case"px":break;default:N*=1/e[R+"ToPx"]}}switch(T){case"+":L=N+L;break;case"-":L=N-L;break;case"*":L=N*L;break;case"/":L=N/L}i[H]={rootPropertyValue:P,startValue:N,currentValue:N,endValue:L,unitType:R,easing:M},t.debug&&console.log("tweensContainer ("+H+"): "+JSON.stringify(i[H]),f)}else t.debug&&console.log("Skipping ["+O+"] due to a lack of browser support.")}i.element=f}i.element&&(v.Values.addClass(f,"velocity-animating"),J.push(i),""===h.queue&&(g(f).tweensContainer=i,g(f).opts=h),g(f).isAnimating=!0,y===x-1?(t.State.calls.push([J,o,h,null,B.resolver]),t.State.isTicking===!1&&(t.State.isTicking=!0,k())):y++)}var e,f=this,h=m.extend({},t.defaults,s),i={};switch(g(f)===d&&t.init(f),parseFloat(h.delay)&&h.queue!==!1&&m.queue(f,h.queue,function(a){t.velocityQueueEntryFlag=!0,g(f).delayTimer={setTimeout:setTimeout(a,parseFloat(h.delay)),next:a}}),h.duration.toString().toLowerCase()){case"fast":h.duration=200;break;case"normal":h.duration=r;break;case"slow":h.duration=600;break;default:h.duration=parseFloat(h.duration)||1}t.mock!==!1&&(t.mock===!0?h.duration=h.delay=1:(h.duration*=parseFloat(t.mock)||1,h.delay*=parseFloat(t.mock)||1)),h.easing=j(h.easing,h.duration),h.begin&&!p.isFunction(h.begin)&&(h.begin=null),h.progress&&!p.isFunction(h.progress)&&(h.progress=null),h.complete&&!p.isFunction(h.complete)&&(h.complete=null),h.display!==d&&null!==h.display&&(h.display=h.display.toString().toLowerCase(),"auto"===h.display&&(h.display=t.CSS.Values.getDisplayType(f))),h.visibility!==d&&null!==h.visibility&&(h.visibility=h.visibility.toString().toLowerCase()),h.mobileHA=h.mobileHA&&t.State.isMobile&&!t.State.isGingerbread,h.queue===!1?h.delay?setTimeout(a,h.delay):a():m.queue(f,h.queue,function(b,c){return c===!0?(B.promise&&B.resolver(o),!0):(t.velocityQueueEntryFlag=!0,void a(b))}),""!==h.queue&&"fx"!==h.queue||"inprogress"===m.queue(f)[0]||m.dequeue(f)}var h,i,n,o,q,s,u=arguments[0]&&(arguments[0].p||m.isPlainObject(arguments[0].properties)&&!arguments[0].properties.names||p.isString(arguments[0].properties));if(p.isWrapped(this)?(h=!1,n=0,o=this,i=this):(h=!0,n=1,o=u?arguments[0].elements||arguments[0].e:arguments[0]),o=f(o)){u?(q=arguments[0].properties||arguments[0].p,s=arguments[0].options||arguments[0].o):(q=arguments[n],s=arguments[n+1]);var x=o.length,y=0;if(!/^(stop|finish|finishAll)$/i.test(q)&&!m.isPlainObject(s)){var z=n+1;s={};for(var A=z;A<arguments.length;A++)p.isArray(arguments[A])||!/^(fast|normal|slow)$/i.test(arguments[A])&&!/^\d/.test(arguments[A])?p.isString(arguments[A])||p.isArray(arguments[A])?s.easing=arguments[A]:p.isFunction(arguments[A])&&(s.complete=arguments[A]):s.duration=arguments[A]}var B={promise:null,resolver:null,rejecter:null};h&&t.Promise&&(B.promise=new t.Promise(function(a,b){B.resolver=a,B.rejecter=b}));var C;switch(q){case"scroll":C="scroll";break;case"reverse":C="reverse";break;case"finish":case"finishAll":case"stop":m.each(o,function(a,b){g(b)&&g(b).delayTimer&&(clearTimeout(g(b).delayTimer.setTimeout),g(b).delayTimer.next&&g(b).delayTimer.next(),delete g(b).delayTimer),"finishAll"!==q||s!==!0&&!p.isString(s)||(m.each(m.queue(b,p.isString(s)?s:""),function(a,b){p.isFunction(b)&&b()}),m.queue(b,p.isString(s)?s:"",[]))});var D=[];return m.each(t.State.calls,function(a,b){b&&m.each(b[1],function(c,e){var f=s===d?"":s;return f===!0||b[2].queue===f||s===d&&b[2].queue===!1?void m.each(o,function(c,d){d===e&&((s===!0||p.isString(s))&&(m.each(m.queue(d,p.isString(s)?s:""),function(a,b){p.isFunction(b)&&b(null,!0)
+}),m.queue(d,p.isString(s)?s:"",[])),"stop"===q?(g(d)&&g(d).tweensContainer&&f!==!1&&m.each(g(d).tweensContainer,function(a,b){b.endValue=b.currentValue}),D.push(a)):("finish"===q||"finishAll"===q)&&(b[2].duration=1))}):!0})}),"stop"===q&&(m.each(D,function(a,b){l(b,!0)}),B.promise&&B.resolver(o)),a();default:if(!m.isPlainObject(q)||p.isEmptyObject(q)){if(p.isString(q)&&t.Redirects[q]){var E=m.extend({},s),F=E.duration,G=E.delay||0;return E.backwards===!0&&(o=m.extend(!0,[],o).reverse()),m.each(o,function(a,b){parseFloat(E.stagger)?E.delay=G+parseFloat(E.stagger)*a:p.isFunction(E.stagger)&&(E.delay=G+E.stagger.call(b,a,x)),E.drag&&(E.duration=parseFloat(F)||(/^(callout|transition)/.test(q)?1e3:r),E.duration=Math.max(E.duration*(E.backwards?1-a/x:(a+1)/x),.75*E.duration,200)),t.Redirects[q].call(b,b,E||{},a,x,o,B.promise?B:d)}),a()}var H="Velocity: First argument ("+q+") was not a property map, a known action, or a registered redirect. Aborting.";return B.promise?B.rejecter(new Error(H)):console.log(H),a()}C="start"}var I={lastParent:null,lastPosition:null,lastFontSize:null,lastPercentToPxWidth:null,lastPercentToPxHeight:null,lastEmToPx:null,remToPx:null,vwToPx:null,vhToPx:null},J=[];m.each(o,function(a,b){p.isNode(b)&&e.call(b)});var K,E=m.extend({},t.defaults,s);if(E.loop=parseInt(E.loop),K=2*E.loop-1,E.loop)for(var L=0;K>L;L++){var M={delay:E.delay,progress:E.progress};L===K-1&&(M.display=E.display,M.visibility=E.visibility,M.complete=E.complete),w(o,"reverse",M)}return a()}};t=m.extend(w,t),t.animate=w;var x=b.requestAnimationFrame||o;return t.State.isMobile||c.hidden===d||c.addEventListener("visibilitychange",function(){c.hidden?(x=function(a){return setTimeout(function(){a(!0)},16)},k()):x=b.requestAnimationFrame||o}),a.Velocity=t,a!==b&&(a.fn.velocity=w,a.fn.velocity.defaults=t.defaults),m.each(["Down","Up"],function(a,b){t.Redirects["slide"+b]=function(a,c,e,f,g,h){var i=m.extend({},c),j=i.begin,k=i.complete,l={height:"",marginTop:"",marginBottom:"",paddingTop:"",paddingBottom:""},n={};i.display===d&&(i.display="Down"===b?"inline"===t.CSS.Values.getDisplayType(a)?"inline-block":"block":"none"),i.begin=function(){j&&j.call(g,g);for(var c in l){n[c]=a.style[c];var d=t.CSS.getPropertyValue(a,c);l[c]="Down"===b?[d,0]:[0,d]}n.overflow=a.style.overflow,a.style.overflow="hidden"},i.complete=function(){for(var b in n)a.style[b]=n[b];k&&k.call(g,g),h&&h.resolver(g)},t(a,l,i)}}),m.each(["In","Out"],function(a,b){t.Redirects["fade"+b]=function(a,c,e,f,g,h){var i=m.extend({},c),j={opacity:"In"===b?1:0},k=i.complete;i.complete=e!==f-1?i.begin=null:function(){k&&k.call(g,g),h&&h.resolver(g)},i.display===d&&(i.display="In"===b?"auto":"none"),t(this,j,i)}}),t}(window.jQuery||window.Zepto||window,window,document)});
diff --git a/web/templates/head.html b/web/templates/head.html
index e80f0a24c..c2c40098c 100644
--- a/web/templates/head.html
+++ b/web/templates/head.html
@@ -36,6 +36,7 @@
<script src="/static/js/bootstrap-3.3.5.js"></script>
<script src="/static/js/bootstrap-colorpicker.min.js"></script>
<script src="/static/js/react-bootstrap-0.28.1.js"></script>
+ <script src="/static/js/velocity.min.js"></script>
<script src="/static/js/perfect-scrollbar-0.6.7.jquery.min.js"></script>
<script src="/static/js/jquery-dragster/jquery.dragster.js"></script>
<script src="/static/js/babel-polyfill-6.1.18.min.js"></script>
diff --git a/web/web.go b/web/web.go
index 63544229b..f1e8471b8 100644
--- a/web/web.go
+++ b/web/web.go
@@ -8,6 +8,7 @@ import (
"fmt"
"github.com/gorilla/mux"
"github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -643,6 +644,12 @@ func signupWithOAuth(c *api.Context, w http.ResponseWriter, r *http.Request) {
service := params["service"]
teamName := params["team"]
+ if !utils.Cfg.TeamSettings.EnableUserCreation {
+ c.Err = model.NewAppError("signupTeam", "User sign-up is disabled.", "")
+ c.Err.StatusCode = http.StatusNotImplemented
+ return
+ }
+
if len(teamName) == 0 {
c.Err = model.NewAppError("signupWithOAuth", "Invalid team name", "team_name="+teamName)
c.Err.StatusCode = http.StatusBadRequest
@@ -699,9 +706,12 @@ func signupCompleteOAuth(c *api.Context, w http.ResponseWriter, r *http.Request)
return
} else {
var user *model.User
- if service == model.USER_AUTH_SERVICE_GITLAB {
- glu := model.GitLabUserFromJson(body)
- user = model.UserFromGitLabUser(glu)
+ provider := einterfaces.GetOauthProvider(service)
+ if provider == nil {
+ c.Err = model.NewAppError("signupCompleteOAuth", service+" oauth not avlailable on this server", "")
+ return
+ } else {
+ user = provider.GetUserFromJson(body)
}
if user == nil {
@@ -744,8 +754,9 @@ func signupCompleteOAuth(c *api.Context, w http.ResponseWriter, r *http.Request)
user.TeamId = team.Id
user.EmailVerified = true
- ruser := api.CreateUser(c, team, user)
- if c.Err != nil {
+ ruser, err := api.CreateUser(team, user)
+ if err != nil {
+ c.Err = err
return
}
@@ -799,9 +810,12 @@ func loginCompleteOAuth(c *api.Context, w http.ResponseWriter, r *http.Request)
return
} else {
authData := ""
- if service == model.USER_AUTH_SERVICE_GITLAB {
- glu := model.GitLabUserFromJson(body)
- authData = glu.GetAuthData()
+ provider := einterfaces.GetOauthProvider(service)
+ if provider == nil {
+ c.Err = model.NewAppError("signupCompleteOAuth", service+" oauth not avlailable on this server", "")
+ return
+ } else {
+ authData = provider.GetAuthDataFromJson(body)
}
if len(authData) == 0 {