Просмотр исходного кода

Added missing mysql driver package dependency

Torkel Ödegaard 11 лет назад
Родитель
Сommit
18ff1569b9
83 измененных файлов с 6993 добавлено и 5664 удалено
  1. 12 3
      Godeps/Godeps.json
  2. 8 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/.gitignore
  3. 9 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/.travis.yml
  4. 36 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/AUTHORS
  5. 83 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/CHANGELOG.md
  6. 40 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/CONTRIBUTING.md
  7. 373 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/LICENSE
  8. 346 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/README.md
  9. 19 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/appengine.go
  10. 208 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/benchmark_test.go
  11. 136 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/buffer.go
  12. 236 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/collations.go
  13. 268 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/connection.go
  14. 132 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/const.go
  15. 138 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/driver.go
  16. 1540 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/driver_test.go
  17. 129 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/errors.go
  18. 42 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/errors_test.go
  19. 162 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/infile.go
  20. 1122 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/packets.go
  21. 22 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/result.go
  22. 101 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/rows.go
  23. 112 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/statement.go
  24. 31 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/transaction.go
  25. 785 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/utils.go
  26. 212 0
      Godeps/_workspace/src/github.com/go-sql-driver/mysql/utils_test.go
  27. 0 63
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions.go
  28. 0 140
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/collections.go
  29. 0 103
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/collections_test.go
  30. 0 3
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/doc.go
  31. 0 281
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/equality.go
  32. 0 256
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/equality_test.go
  33. 0 22
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/filter.go
  34. 0 7
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/init.go
  35. 0 86
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/messages.go
  36. 0 115
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/panic.go
  37. 0 53
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/panic_test.go
  38. 0 141
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/quantity.go
  39. 0 145
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/quantity_test.go
  40. 0 31
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/serializer.go
  41. 0 28
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/serializer_test.go
  42. 0 183
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/strings.go
  43. 0 102
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/strings_test.go
  44. 0 202
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/time.go
  45. 0 159
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/time_test.go
  46. 0 112
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/type.go
  47. 0 76
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/type_test.go
  48. 0 75
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/utilities_for_test.go
  49. 0 179
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/context.go
  50. 0 57
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/discovery.go
  51. 0 178
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/doc.go
  52. 0 72
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/focused_execution_test.go
  53. 0 37
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/gotest/utils.go
  54. 0 72
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/init.go
  55. 0 742
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/isolated_execution_test.go
  56. 0 74
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/registration.go
  57. 0 16
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/console.go
  58. 0 5
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/doc.go
  59. 0 40
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/dot.go
  60. 0 40
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/dot_test.go
  61. 0 33
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/gotest.go
  62. 0 66
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/gotest_test.go
  63. 0 94
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/init.go
  64. 0 88
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/json.go
  65. 0 57
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/printer.go
  66. 0 181
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/printer_test.go
  67. 0 68
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/problems.go
  68. 0 46
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/problems_test.go
  69. 0 39
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/reporter.go
  70. 0 94
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/reporter_test.go
  71. 0 179
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/reports.go
  72. 0 79
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/statistics.go
  73. 0 65
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/story.go
  74. 0 270
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting_hooks_test.go
  75. 0 92
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/runner.go
  76. 0 116
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/scope.go
  77. 0 185
      Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/story_conventions_test.go
  78. 89 4
      Godeps/_workspace/src/gopkg.in/ini.v1/README.md
  79. 85 0
      Godeps/_workspace/src/gopkg.in/ini.v1/README_ZH.md
  80. 82 9
      Godeps/_workspace/src/gopkg.in/ini.v1/ini.go
  81. 38 1
      Godeps/_workspace/src/gopkg.in/ini.v1/ini_test.go
  82. 214 0
      Godeps/_workspace/src/gopkg.in/ini.v1/struct.go
  83. 183 0
      Godeps/_workspace/src/gopkg.in/ini.v1/struct_test.go

+ 12 - 3
Godeps/Godeps.json

@@ -19,6 +19,11 @@
 			"Comment": "1.2.0-38-g9908e96",
 			"Rev": "9908e96513e5a94de37004098a3974a567f18111"
 		},
+		{
+			"ImportPath": "github.com/go-sql-driver/mysql",
+			"Comment": "v1.2-26-g9543750",
+			"Rev": "9543750295406ef070f7de8ae9c43ccddd44e15e"
+		},
 		{
 			"ImportPath": "github.com/go-xorm/core",
 			"Rev": "a949e067ced1cb6e6ef5c38b6f28b074fa718f1e"
@@ -37,13 +42,17 @@
 			"Rev": "d10e2c8f62100097910367dee90a9bd89d426a44"
 		},
 		{
-			"ImportPath": "github.com/smartystreets/goconvey/convey",
-			"Comment": "1.5.0-254-g627707e",
-			"Rev": "627707e8db4a4e52f4e1fbbb4e10d98e79a3c946"
+			"ImportPath": "golang.org/x/net/context",
+			"Rev": "972f0c5fbe4ae29e666c3f78c3ed42ae7a448b0a"
 		},
 		{
 			"ImportPath": "golang.org/x/oauth2",
 			"Rev": "e5909d4679a1926c774c712b343f10b8298687a3"
+		},
+		{
+			"ImportPath": "gopkg.in/ini.v1",
+			"Comment": "v0-10-g28ad8c4",
+			"Rev": "28ad8c408ba20e5c86b06d64cd2cc9248f640a83"
 		}
 	]
 }

+ 8 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/.gitignore

@@ -0,0 +1,8 @@
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+Icon?
+ehthumbs.db
+Thumbs.db

+ 9 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/.travis.yml

@@ -0,0 +1,9 @@
+language: go
+go:
+  - 1.1
+  - 1.2
+  - 1.3
+  - tip
+
+before_script:
+  - mysql -e 'create database gotest;'

+ 36 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/AUTHORS

@@ -0,0 +1,36 @@
+# This is the official list of Go-MySQL-Driver authors for copyright purposes.
+
+# If you are submitting a patch, please add your name or the name of the
+# organization which holds the copyright to this list in alphabetical order.
+
+# Names should be added to this file as
+#	Name <email address>
+# The email address is not required for organizations.
+# Please keep the list sorted.
+
+
+# Individual Persons
+
+Aaron Hopkins <go-sql-driver at die.net>
+Arne Hormann <arnehormann at gmail.com>
+Carlos Nieto <jose.carlos at menteslibres.net>
+DisposaBoy <disposaboy at dby.me>
+Frederick Mayle <frederickmayle at gmail.com>
+Gustavo Kristic <gkristic at gmail.com>
+Hanno Braun <mail at hannobraun.com>
+Henri Yandell <flamefew at gmail.com>
+James Harr <james.harr at gmail.com>
+Jian Zhen <zhenjl at gmail.com>
+Julien Schmidt <go-sql-driver at julienschmidt.com>
+Leonardo YongUk Kim <dalinaum at gmail.com>
+Lucas Liu <extrafliu at gmail.com>
+Luke Scott <luke at webconnex.com>
+Michael Woolnough <michael.woolnough at gmail.com>
+Nicola Peduzzi <thenikso at gmail.com>
+Xiaobing Jiang <s7v7nislands at gmail.com>
+Xiuming Chen <cc at cxm.cc>
+
+# Organizations
+
+Barracuda Networks, Inc.
+Google Inc.

+ 83 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/CHANGELOG.md

@@ -0,0 +1,83 @@
+## HEAD
+
+Changes:
+
+ - Use decimals field from MySQL to format time types
+
+Bugfixes:
+
+ - Enable microsecond resolution on TIME, DATETIME and TIMESTAMP
+
+
+## Version 1.2 (2014-06-03)
+
+Changes:
+
+ - We switched back to a "rolling release". `go get` installs the current master branch again
+ - Version v1 of the driver will not be maintained anymore. Go 1.0 is no longer supported by this driver
+ - Exported errors to allow easy checking from application code
+ - Enabled TCP Keepalives on TCP connections
+ - Optimized INFILE handling (better buffer size calculation, lazy init, ...)
+ - The DSN parser also checks for a missing separating slash
+ - Faster binary date / datetime to string formatting
+ - Also exported the MySQLWarning type
+ - mysqlConn.Close returns the first error encountered instead of ignoring all errors
+ - writePacket() automatically writes the packet size to the header
+ - readPacket() uses an iterative approach instead of the recursive approach to merge splitted packets
+
+New Features:
+
+ - `RegisterDial` allows the usage of a custom dial function to establish the network connection
+ - Setting the connection collation is possible with the `collation` DSN parameter. This parameter should be preferred over the `charset` parameter
+ - Logging of critical errors is configurable with `SetLogger`
+ - Google CloudSQL support
+
+Bugfixes:
+
+ - Allow more than 32 parameters in prepared statements
+ - Various old_password fixes
+ - Fixed TestConcurrent test to pass Go's race detection
+ - Fixed appendLengthEncodedInteger for large numbers
+ - Renamed readLengthEnodedString to readLengthEncodedString and skipLengthEnodedString to skipLengthEncodedString (fixed typo)
+
+
+## Version 1.1 (2013-11-02)
+
+Changes:
+
+  - Go-MySQL-Driver now requires Go 1.1
+  - Connections now use the collation `utf8_general_ci` by default. Adding `&charset=UTF8` to the DSN should not be necessary anymore
+  - Made closing rows and connections error tolerant. This allows for example deferring rows.Close() without checking for errors
+  - `[]byte(nil)` is now treated as a NULL value. Before, it was treated like an empty string / `[]byte("")`
+  - DSN parameter values must now be url.QueryEscape'ed. This allows text values to contain special characters, such as '&'.
+  - Use the IO buffer also for writing. This results in zero allocations (by the driver) for most queries
+  - Optimized the buffer for reading
+  - stmt.Query now caches column metadata
+  - New Logo
+  - Changed the copyright header to include all contributors
+  - Improved the LOAD INFILE documentation
+  - The driver struct is now exported to make the driver directly accessible
+  - Refactored the driver tests
+  - Added more benchmarks and moved all to a separate file
+  - Other small refactoring
+
+New Features:
+
+  - Added *old_passwords* support: Required in some cases, but must be enabled by adding `allowOldPasswords=true` to the DSN since it is insecure
+  - Added a `clientFoundRows` parameter: Return the number of matching rows instead of the number of rows changed on UPDATEs
+  - Added TLS/SSL support: Use a TLS/SSL encrypted connection to the server. Custom TLS configs can be registered and used
+
+Bugfixes:
+
+  - Fixed MySQL 4.1 support: MySQL 4.1 sends packets with lengths which differ from the specification
+  - Convert to DB timezone when inserting `time.Time`
+  - Splitted packets (more than 16MB) are now merged correctly
+  - Fixed false positive `io.EOF` errors when the data was fully read
+  - Avoid panics on reuse of closed connections
+  - Fixed empty string producing false nil values
+  - Fixed sign byte for positive TIME fields
+
+
+## Version 1.0 (2013-05-14)
+
+Initial Release

+ 40 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/CONTRIBUTING.md

@@ -0,0 +1,40 @@
+# Contributing Guidelines
+
+## Reporting Issues
+
+Before creating a new Issue, please check first if a similar Issue [already exists](https://github.com/go-sql-driver/mysql/issues?state=open) or was [recently closed](https://github.com/go-sql-driver/mysql/issues?direction=desc&page=1&sort=updated&state=closed).
+
+Please provide the following minimum information:
+* Your Go-MySQL-Driver version (or git SHA)
+* Your Go version (run `go version` in your console)
+* A detailed issue description
+* Error Log if present
+* If possible, a short example
+
+
+## Contributing Code
+
+By contributing to this project, you share your code under the Mozilla Public License 2, as specified in the LICENSE file.
+Don't forget to add yourself to the AUTHORS file.
+
+### Pull Requests Checklist
+
+Please check the following points before submitting your pull request:
+- [x] Code compiles correctly
+- [x] Created tests, if possible
+- [x] All tests pass
+- [x] Extended the README / documentation, if necessary
+- [x] Added yourself to the AUTHORS file
+
+### Code Review
+
+Everyone is invited to review and comment on pull requests.
+If it looks fine to you, comment with "LGTM" (Looks good to me).
+
+If changes are required, notice the reviewers with "PTAL" (Please take another look) after committing the fixes.
+
+Before merging the Pull Request, at least one [team member](https://github.com/go-sql-driver?tab=members) must have commented with "LGTM".
+
+## Development Ideas
+
+If you are looking for ideas for code contributions, please check our [Development Ideas](https://github.com/go-sql-driver/mysql/wiki/Development-Ideas) Wiki page.

+ 373 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/LICENSE

@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in 
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.

+ 346 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/README.md

@@ -0,0 +1,346 @@
+# Go-MySQL-Driver
+
+A MySQL-Driver for Go's [database/sql](http://golang.org/pkg/database/sql) package
+
+![Go-MySQL-Driver logo](https://raw.github.com/wiki/go-sql-driver/mysql/gomysql_m.png "Golang Gopher holding the MySQL Dolphin")
+
+**Latest stable Release:** [Version 1.2 (June 03, 2014)](https://github.com/go-sql-driver/mysql/releases)
+
+[![Build Status](https://travis-ci.org/go-sql-driver/mysql.png?branch=master)](https://travis-ci.org/go-sql-driver/mysql)
+
+---------------------------------------
+  * [Features](#features)
+  * [Requirements](#requirements)
+  * [Installation](#installation)
+  * [Usage](#usage)
+    * [DSN (Data Source Name)](#dsn-data-source-name)
+      * [Password](#password)
+      * [Protocol](#protocol)
+      * [Address](#address)
+      * [Parameters](#parameters)
+      * [Examples](#examples)
+    * [LOAD DATA LOCAL INFILE support](#load-data-local-infile-support)
+    * [time.Time support](#timetime-support)
+    * [Unicode support](#unicode-support)
+  * [Testing / Development](#testing--development)
+  * [License](#license)
+
+---------------------------------------
+
+## Features
+  * Lightweight and [fast](https://github.com/go-sql-driver/sql-benchmark "golang MySQL-Driver performance")
+  * Native Go implementation. No C-bindings, just pure Go
+  * Connections over TCP/IPv4, TCP/IPv6 or Unix domain sockets
+  * Automatic handling of broken connections
+  * Automatic Connection Pooling *(by database/sql package)*
+  * Supports queries larger than 16MB
+  * Full [`sql.RawBytes`](http://golang.org/pkg/database/sql/#RawBytes) support.
+  * Intelligent `LONG DATA` handling in prepared statements
+  * Secure `LOAD DATA LOCAL INFILE` support with file Whitelisting and `io.Reader` support
+  * Optional `time.Time` parsing
+
+## Requirements
+  * Go 1.1 or higher
+  * MySQL (4.1+), MariaDB, Percona Server, Google CloudSQL or Sphinx (2.2.3+)
+
+---------------------------------------
+
+## Installation
+Simple install the package to your [$GOPATH](http://code.google.com/p/go-wiki/wiki/GOPATH "GOPATH") with the [go tool](http://golang.org/cmd/go/ "go command") from shell:
+```bash
+$ go get github.com/go-sql-driver/mysql
+```
+Make sure [Git is installed](http://git-scm.com/downloads) on your machine and in your system's `PATH`.
+
+## Usage
+_Go MySQL Driver_ is an implementation of Go's `database/sql/driver` interface. You only need to import the driver and can use the full [`database/sql`](http://golang.org/pkg/database/sql) API then.
+
+Use `mysql` as `driverName` and a valid [DSN](#dsn-data-source-name)  as `dataSourceName`:
+```go
+import "database/sql"
+import _ "github.com/go-sql-driver/mysql"
+
+db, err := sql.Open("mysql", "user:password@/dbname")
+```
+
+[Examples are available in our Wiki](https://github.com/go-sql-driver/mysql/wiki/Examples "Go-MySQL-Driver Examples").
+
+
+### DSN (Data Source Name)
+
+The Data Source Name has a common format, like e.g. [PEAR DB](http://pear.php.net/manual/en/package.database.db.intro-dsn.php) uses it, but without type-prefix (optional parts marked by squared brackets):
+```
+[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]
+```
+
+A DSN in its fullest form:
+```
+username:password@protocol(address)/dbname?param=value
+```
+
+Except for the databasename, all values are optional. So the minimal DSN is:
+```
+/dbname
+```
+
+If you do not want to preselect a database, leave `dbname` empty:
+```
+/
+```
+This has the same effect as an empty DSN string:
+```
+
+```
+
+#### Password
+Passwords can consist of any character. Escaping is **not** necessary.
+
+#### Protocol
+See [net.Dial](http://golang.org/pkg/net/#Dial) for more information which networks are available.
+In general you should use an Unix domain socket if available and TCP otherwise for best performance.
+
+#### Address
+For TCP and UDP networks, addresses have the form `host:port`.
+If `host` is a literal IPv6 address, it must be enclosed in square brackets.
+The functions [net.JoinHostPort](http://golang.org/pkg/net/#JoinHostPort) and [net.SplitHostPort](http://golang.org/pkg/net/#SplitHostPort) manipulate addresses in this form.
+
+For Unix domain sockets the address is the absolute path to the MySQL-Server-socket, e.g. `/var/run/mysqld/mysqld.sock` or `/tmp/mysql.sock`.
+
+#### Parameters
+*Parameters are case-sensitive!*
+
+Notice that any of `true`, `TRUE`, `True` or `1` is accepted to stand for a true boolean value. Not surprisingly, false can be specified as any of: `false`, `FALSE`, `False` or `0`.
+
+##### `allowAllFiles`
+
+```
+Type:           bool
+Valid Values:   true, false
+Default:        false
+```
+
+`allowAllFiles=true` disables the file Whitelist for `LOAD DATA LOCAL INFILE` and allows *all* files.
+[*Might be insecure!*](http://dev.mysql.com/doc/refman/5.7/en/load-data-local.html)
+
+##### `allowOldPasswords`
+
+```
+Type:           bool
+Valid Values:   true, false
+Default:        false
+```
+`allowOldPasswords=true` allows the usage of the insecure old password method. This should be avoided, but is necessary in some cases. See also [the old_passwords wiki page](https://github.com/go-sql-driver/mysql/wiki/old_passwords).
+
+##### `charset`
+
+```
+Type:           string
+Valid Values:   <name>
+Default:        none
+```
+
+Sets the charset used for client-server interaction (`"SET NAMES <value>"`). If multiple charsets are set (separated by a comma), the following charset is used if setting the charset failes. This enables for example support for `utf8mb4` ([introduced in MySQL 5.5.3](http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html)) with fallback to `utf8` for older servers (`charset=utf8mb4,utf8`).
+
+Usage of the `charset` parameter is discouraged because it issues additional queries to the server.
+Unless you need the fallback behavior, please use `collation` instead.
+
+##### `collation`
+
+```
+Type:           string
+Valid Values:   <name>
+Default:        utf8_general_ci
+```
+
+Sets the collation used for client-server interaction on connection. In contrast to `charset`, `collation` does not issue additional queries. If the specified collation is unavailable on the target server, the connection will fail.
+
+A list of valid charsets for a server is retrievable with `SHOW COLLATION`.
+
+##### `clientFoundRows`
+
+```
+Type:           bool
+Valid Values:   true, false
+Default:        false
+```
+
+`clientFoundRows=true` causes an UPDATE to return the number of matching rows instead of the number of rows changed.
+
+
+##### `loc`
+
+```
+Type:           string
+Valid Values:   <escaped name>
+Default:        UTC
+```
+
+Sets the location for time.Time values (when using `parseTime=true`). *"Local"* sets the system's location. See [time.LoadLocation](http://golang.org/pkg/time/#LoadLocation) for details.
+
+Please keep in mind, that param values must be [url.QueryEscape](http://golang.org/pkg/net/url/#QueryEscape)'ed. Alternatively you can manually replace the `/` with `%2F`. For example `US/Pacific` would be `loc=US%2FPacific`.
+
+
+##### `parseTime`
+
+```
+Type:           bool
+Valid Values:   true, false
+Default:        false
+```
+
+`parseTime=true` changes the output type of `DATE` and `DATETIME` values to `time.Time` instead of `[]byte` / `string`
+
+
+##### `strict`
+
+```
+Type:           bool
+Valid Values:   true, false
+Default:        false
+```
+
+`strict=true` enables the strict mode in which MySQL warnings are treated as errors.
+
+By default MySQL also treats notes as warnings. Use [`sql_notes=false`](http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_sql_notes) to ignore notes. See the [examples](#examples) for an DSN example.
+
+
+##### `timeout`
+
+```
+Type:           decimal number
+Default:        OS default
+```
+
+*Driver* side connection timeout. The value must be a string of decimal numbers, each with optional fraction and a unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. To set a server side timeout, use the parameter [`wait_timeout`](http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_wait_timeout).
+
+
+##### `tls`
+
+```
+Type:           bool / string
+Valid Values:   true, false, skip-verify, <name>
+Default:        false
+```
+
+`tls=true` enables TLS / SSL encrypted connection to the server. Use `skip-verify` if you want to use a self-signed or invalid certificate (server side). Use a custom value registered with [`mysql.RegisterTLSConfig`](http://godoc.org/github.com/go-sql-driver/mysql#RegisterTLSConfig).
+
+
+##### System Variables
+
+All other parameters are interpreted as system variables:
+  * `autocommit`: `"SET autocommit=<value>"`
+  * `time_zone`: `"SET time_zone=<value>"`
+  * [`tx_isolation`](https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_tx_isolation): `"SET tx_isolation=<value>"`
+  * `param`: `"SET <param>=<value>"`
+
+*The values must be [url.QueryEscape](http://golang.org/pkg/net/url/#QueryEscape)'ed!*
+
+#### Examples
+```
+user@unix(/path/to/socket)/dbname
+```
+
+```
+root:pw@unix(/tmp/mysql.sock)/myDatabase?loc=Local
+```
+
+```
+user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true
+```
+
+Use the [strict mode](#strict) but ignore notes:
+```
+user:password@/dbname?strict=true&sql_notes=false
+```
+
+TCP via IPv6:
+```
+user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s&collation=utf8mb4_unicode_ci
+```
+
+TCP on a remote host, e.g. Amazon RDS:
+```
+id:password@tcp(your-amazonaws-uri.com:3306)/dbname
+```
+
+Google Cloud SQL on App Engine:
+```
+user@cloudsql(project-id:instance-name)/dbname
+```
+
+TCP using default port (3306) on localhost:
+```
+user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped
+```
+
+Use the default protocol (tcp) and host (localhost:3306):
+```
+user:password@/dbname
+```
+
+No Database preselected:
+```
+user:password@/
+```
+
+### `LOAD DATA LOCAL INFILE` support
+For this feature you need direct access to the package. Therefore you must change the import path (no `_`):
+```go
+import "github.com/go-sql-driver/mysql"
+```
+
+Files must be whitelisted by registering them with `mysql.RegisterLocalFile(filepath)` (recommended) or the Whitelist check must be deactivated by using the DSN parameter `allowAllFiles=true` ([*Might be insecure!*](http://dev.mysql.com/doc/refman/5.7/en/load-data-local.html)).
+
+To use a `io.Reader` a handler function must be registered with `mysql.RegisterReaderHandler(name, handler)` which returns a `io.Reader` or `io.ReadCloser`. The Reader is available with the filepath `Reader::<name>` then.
+
+See the [godoc of Go-MySQL-Driver](http://godoc.org/github.com/go-sql-driver/mysql "golang mysql driver documentation") for details.
+
+
+### `time.Time` support
+The default internal output type of MySQL `DATE` and `DATETIME` values is `[]byte` which allows you to scan the value into a `[]byte`, `string` or `sql.RawBytes` variable in your programm.
+
+However, many want to scan MySQL `DATE` and `DATETIME` values into `time.Time` variables, which is the logical opposite in Go to `DATE` and `DATETIME` in MySQL. You can do that by changing the internal output type from `[]byte` to `time.Time` with the DSN parameter `parseTime=true`. You can set the default [`time.Time` location](http://golang.org/pkg/time/#Location) with the `loc` DSN parameter.
+
+**Caution:** As of Go 1.1, this makes `time.Time` the only variable type you can scan `DATE` and `DATETIME` values into. This breaks for example [`sql.RawBytes` support](https://github.com/go-sql-driver/mysql/wiki/Examples#rawbytes).
+
+Alternatively you can use the [`NullTime`](http://godoc.org/github.com/go-sql-driver/mysql#NullTime) type as the scan destination, which works with both `time.Time` and `string` / `[]byte`.
+
+
+### Unicode support
+Since version 1.1 Go-MySQL-Driver automatically uses the collation `utf8_general_ci` by default.
+
+Other collations / charsets can be set using the [`collation`](#collation) DSN parameter.
+
+Version 1.0 of the driver recommended adding `&charset=utf8` (alias for `SET NAMES utf8`) to the DSN to enable proper UTF-8 support. This is not necessary anymore. The [`collation`](#collation) parameter should be preferred to set another collation / charset than the default.
+
+See http://dev.mysql.com/doc/refman/5.7/en/charset-unicode.html for more details on MySQL's Unicode support.
+
+
+## Testing / Development
+To run the driver tests you may need to adjust the configuration. See the [Testing Wiki-Page](https://github.com/go-sql-driver/mysql/wiki/Testing "Testing") for details.
+
+Go-MySQL-Driver is not feature-complete yet. Your help is very appreciated.
+If you want to contribute, you can work on an [open issue](https://github.com/go-sql-driver/mysql/issues?state=open) or review a [pull request](https://github.com/go-sql-driver/mysql/pulls).
+
+See the [Contribution Guidelines](https://github.com/go-sql-driver/mysql/blob/master/CONTRIBUTING.md) for details.
+
+---------------------------------------
+
+## License
+Go-MySQL-Driver is licensed under the [Mozilla Public License Version 2.0](https://raw.github.com/go-sql-driver/mysql/master/LICENSE)
+
+Mozilla summarizes the license scope as follows:
+> MPL: The copyleft applies to any files containing MPLed code.
+
+
+That means:
+  * You can **use** the **unchanged** source code both in private and commercially
+  * When distributing, you **must publish** the source code of any **changed files** licensed under the MPL 2.0 under a) the MPL 2.0 itself or b) a compatible license (e.g. GPL 3.0 or Apache License 2.0)
+  * You **needn't publish** the source code of your library as long as the files licensed under the MPL 2.0 are **unchanged**
+
+Please read the [MPL 2.0 FAQ](http://www.mozilla.org/MPL/2.0/FAQ.html) if you have further questions regarding the license.
+
+You can read the full terms here: [LICENSE](https://raw.github.com/go-sql-driver/mysql/master/LICENSE)
+
+![Go Gopher and MySQL Dolphin](https://raw.github.com/wiki/go-sql-driver/mysql/go-mysql-driver_m.jpg "Golang Gopher transporting the MySQL Dolphin in a wheelbarrow")
+

+ 19 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/appengine.go

@@ -0,0 +1,19 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// +build appengine
+
+package mysql
+
+import (
+	"appengine/cloudsql"
+)
+
+func init() {
+	RegisterDial("cloudsql", cloudsql.Dial)
+}

+ 208 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/benchmark_test.go

@@ -0,0 +1,208 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"bytes"
+	"database/sql"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"testing"
+)
+
+type TB testing.B
+
+func (tb *TB) check(err error) {
+	if err != nil {
+		tb.Fatal(err)
+	}
+}
+
+func (tb *TB) checkDB(db *sql.DB, err error) *sql.DB {
+	tb.check(err)
+	return db
+}
+
+func (tb *TB) checkRows(rows *sql.Rows, err error) *sql.Rows {
+	tb.check(err)
+	return rows
+}
+
+func (tb *TB) checkStmt(stmt *sql.Stmt, err error) *sql.Stmt {
+	tb.check(err)
+	return stmt
+}
+
+func initDB(b *testing.B, queries ...string) *sql.DB {
+	tb := (*TB)(b)
+	db := tb.checkDB(sql.Open("mysql", dsn))
+	for _, query := range queries {
+		if _, err := db.Exec(query); err != nil {
+			b.Fatalf("Error on %q: %v", query, err)
+		}
+	}
+	return db
+}
+
+const concurrencyLevel = 10
+
+func BenchmarkQuery(b *testing.B) {
+	tb := (*TB)(b)
+	b.StopTimer()
+	b.ReportAllocs()
+	db := initDB(b,
+		"DROP TABLE IF EXISTS foo",
+		"CREATE TABLE foo (id INT PRIMARY KEY, val CHAR(50))",
+		`INSERT INTO foo VALUES (1, "one")`,
+		`INSERT INTO foo VALUES (2, "two")`,
+	)
+	db.SetMaxIdleConns(concurrencyLevel)
+	defer db.Close()
+
+	stmt := tb.checkStmt(db.Prepare("SELECT val FROM foo WHERE id=?"))
+	defer stmt.Close()
+
+	remain := int64(b.N)
+	var wg sync.WaitGroup
+	wg.Add(concurrencyLevel)
+	defer wg.Wait()
+	b.StartTimer()
+
+	for i := 0; i < concurrencyLevel; i++ {
+		go func() {
+			for {
+				if atomic.AddInt64(&remain, -1) < 0 {
+					wg.Done()
+					return
+				}
+
+				var got string
+				tb.check(stmt.QueryRow(1).Scan(&got))
+				if got != "one" {
+					b.Errorf("query = %q; want one", got)
+					wg.Done()
+					return
+				}
+			}
+		}()
+	}
+}
+
+func BenchmarkExec(b *testing.B) {
+	tb := (*TB)(b)
+	b.StopTimer()
+	b.ReportAllocs()
+	db := tb.checkDB(sql.Open("mysql", dsn))
+	db.SetMaxIdleConns(concurrencyLevel)
+	defer db.Close()
+
+	stmt := tb.checkStmt(db.Prepare("DO 1"))
+	defer stmt.Close()
+
+	remain := int64(b.N)
+	var wg sync.WaitGroup
+	wg.Add(concurrencyLevel)
+	defer wg.Wait()
+	b.StartTimer()
+
+	for i := 0; i < concurrencyLevel; i++ {
+		go func() {
+			for {
+				if atomic.AddInt64(&remain, -1) < 0 {
+					wg.Done()
+					return
+				}
+
+				if _, err := stmt.Exec(); err != nil {
+					b.Fatal(err.Error())
+				}
+			}
+		}()
+	}
+}
+
+// data, but no db writes
+var roundtripSample []byte
+
+func initRoundtripBenchmarks() ([]byte, int, int) {
+	if roundtripSample == nil {
+		roundtripSample = []byte(strings.Repeat("0123456789abcdef", 1024*1024))
+	}
+	return roundtripSample, 16, len(roundtripSample)
+}
+
+func BenchmarkRoundtripTxt(b *testing.B) {
+	b.StopTimer()
+	sample, min, max := initRoundtripBenchmarks()
+	sampleString := string(sample)
+	b.ReportAllocs()
+	tb := (*TB)(b)
+	db := tb.checkDB(sql.Open("mysql", dsn))
+	defer db.Close()
+	b.StartTimer()
+	var result string
+	for i := 0; i < b.N; i++ {
+		length := min + i
+		if length > max {
+			length = max
+		}
+		test := sampleString[0:length]
+		rows := tb.checkRows(db.Query(`SELECT "` + test + `"`))
+		if !rows.Next() {
+			rows.Close()
+			b.Fatalf("crashed")
+		}
+		err := rows.Scan(&result)
+		if err != nil {
+			rows.Close()
+			b.Fatalf("crashed")
+		}
+		if result != test {
+			rows.Close()
+			b.Errorf("mismatch")
+		}
+		rows.Close()
+	}
+}
+
+func BenchmarkRoundtripBin(b *testing.B) {
+	b.StopTimer()
+	sample, min, max := initRoundtripBenchmarks()
+	b.ReportAllocs()
+	tb := (*TB)(b)
+	db := tb.checkDB(sql.Open("mysql", dsn))
+	defer db.Close()
+	stmt := tb.checkStmt(db.Prepare("SELECT ?"))
+	defer stmt.Close()
+	b.StartTimer()
+	var result sql.RawBytes
+	for i := 0; i < b.N; i++ {
+		length := min + i
+		if length > max {
+			length = max
+		}
+		test := sample[0:length]
+		rows := tb.checkRows(stmt.Query(test))
+		if !rows.Next() {
+			rows.Close()
+			b.Fatalf("crashed")
+		}
+		err := rows.Scan(&result)
+		if err != nil {
+			rows.Close()
+			b.Fatalf("crashed")
+		}
+		if !bytes.Equal(result, test) {
+			rows.Close()
+			b.Errorf("mismatch")
+		}
+		rows.Close()
+	}
+}

+ 136 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/buffer.go

@@ -0,0 +1,136 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import "io"
+
+const defaultBufSize = 4096
+
+// A buffer which is used for both reading and writing.
+// This is possible since communication on each connection is synchronous.
+// In other words, we can't write and read simultaneously on the same connection.
+// The buffer is similar to bufio.Reader / Writer but zero-copy-ish
+// Also highly optimized for this particular use case.
+type buffer struct {
+	buf    []byte
+	rd     io.Reader
+	idx    int
+	length int
+}
+
+func newBuffer(rd io.Reader) buffer {
+	var b [defaultBufSize]byte
+	return buffer{
+		buf: b[:],
+		rd:  rd,
+	}
+}
+
+// fill reads into the buffer until at least _need_ bytes are in it
+func (b *buffer) fill(need int) error {
+	n := b.length
+
+	// move existing data to the beginning
+	if n > 0 && b.idx > 0 {
+		copy(b.buf[0:n], b.buf[b.idx:])
+	}
+
+	// grow buffer if necessary
+	// TODO: let the buffer shrink again at some point
+	//       Maybe keep the org buf slice and swap back?
+	if need > len(b.buf) {
+		// Round up to the next multiple of the default size
+		newBuf := make([]byte, ((need/defaultBufSize)+1)*defaultBufSize)
+		copy(newBuf, b.buf)
+		b.buf = newBuf
+	}
+
+	b.idx = 0
+
+	for {
+		nn, err := b.rd.Read(b.buf[n:])
+		n += nn
+
+		switch err {
+		case nil:
+			if n < need {
+				continue
+			}
+			b.length = n
+			return nil
+
+		case io.EOF:
+			if n >= need {
+				b.length = n
+				return nil
+			}
+			return io.ErrUnexpectedEOF
+
+		default:
+			return err
+		}
+	}
+}
+
+// returns next N bytes from buffer.
+// The returned slice is only guaranteed to be valid until the next read
+func (b *buffer) readNext(need int) ([]byte, error) {
+	if b.length < need {
+		// refill
+		if err := b.fill(need); err != nil {
+			return nil, err
+		}
+	}
+
+	offset := b.idx
+	b.idx += need
+	b.length -= need
+	return b.buf[offset:b.idx], nil
+}
+
+// returns a buffer with the requested size.
+// If possible, a slice from the existing buffer is returned.
+// Otherwise a bigger buffer is made.
+// Only one buffer (total) can be used at a time.
+func (b *buffer) takeBuffer(length int) []byte {
+	if b.length > 0 {
+		return nil
+	}
+
+	// test (cheap) general case first
+	if length <= defaultBufSize || length <= cap(b.buf) {
+		return b.buf[:length]
+	}
+
+	if length < maxPacketSize {
+		b.buf = make([]byte, length)
+		return b.buf
+	}
+	return make([]byte, length)
+}
+
+// shortcut which can be used if the requested buffer is guaranteed to be
+// smaller than defaultBufSize
+// Only one buffer (total) can be used at a time.
+func (b *buffer) takeSmallBuffer(length int) []byte {
+	if b.length == 0 {
+		return b.buf[:length]
+	}
+	return nil
+}
+
+// takeCompleteBuffer returns the complete existing buffer.
+// This can be used if the necessary buffer size is unknown.
+// Only one buffer (total) can be used at a time.
+func (b *buffer) takeCompleteBuffer() []byte {
+	if b.length == 0 {
+		return b.buf
+	}
+	return nil
+}

+ 236 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/collations.go

@@ -0,0 +1,236 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2014 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+const defaultCollation byte = 33 // utf8_general_ci
+
+// A list of available collations mapped to the internal ID.
+// To update this map use the following MySQL query:
+//     SELECT COLLATION_NAME, ID FROM information_schema.COLLATIONS
+var collations = map[string]byte{
+	"big5_chinese_ci":          1,
+	"latin2_czech_cs":          2,
+	"dec8_swedish_ci":          3,
+	"cp850_general_ci":         4,
+	"latin1_german1_ci":        5,
+	"hp8_english_ci":           6,
+	"koi8r_general_ci":         7,
+	"latin1_swedish_ci":        8,
+	"latin2_general_ci":        9,
+	"swe7_swedish_ci":          10,
+	"ascii_general_ci":         11,
+	"ujis_japanese_ci":         12,
+	"sjis_japanese_ci":         13,
+	"cp1251_bulgarian_ci":      14,
+	"latin1_danish_ci":         15,
+	"hebrew_general_ci":        16,
+	"tis620_thai_ci":           18,
+	"euckr_korean_ci":          19,
+	"latin7_estonian_cs":       20,
+	"latin2_hungarian_ci":      21,
+	"koi8u_general_ci":         22,
+	"cp1251_ukrainian_ci":      23,
+	"gb2312_chinese_ci":        24,
+	"greek_general_ci":         25,
+	"cp1250_general_ci":        26,
+	"latin2_croatian_ci":       27,
+	"gbk_chinese_ci":           28,
+	"cp1257_lithuanian_ci":     29,
+	"latin5_turkish_ci":        30,
+	"latin1_german2_ci":        31,
+	"armscii8_general_ci":      32,
+	"utf8_general_ci":          33,
+	"cp1250_czech_cs":          34,
+	"ucs2_general_ci":          35,
+	"cp866_general_ci":         36,
+	"keybcs2_general_ci":       37,
+	"macce_general_ci":         38,
+	"macroman_general_ci":      39,
+	"cp852_general_ci":         40,
+	"latin7_general_ci":        41,
+	"latin7_general_cs":        42,
+	"macce_bin":                43,
+	"cp1250_croatian_ci":       44,
+	"utf8mb4_general_ci":       45,
+	"utf8mb4_bin":              46,
+	"latin1_bin":               47,
+	"latin1_general_ci":        48,
+	"latin1_general_cs":        49,
+	"cp1251_bin":               50,
+	"cp1251_general_ci":        51,
+	"cp1251_general_cs":        52,
+	"macroman_bin":             53,
+	"utf16_general_ci":         54,
+	"utf16_bin":                55,
+	"utf16le_general_ci":       56,
+	"cp1256_general_ci":        57,
+	"cp1257_bin":               58,
+	"cp1257_general_ci":        59,
+	"utf32_general_ci":         60,
+	"utf32_bin":                61,
+	"utf16le_bin":              62,
+	"binary":                   63,
+	"armscii8_bin":             64,
+	"ascii_bin":                65,
+	"cp1250_bin":               66,
+	"cp1256_bin":               67,
+	"cp866_bin":                68,
+	"dec8_bin":                 69,
+	"greek_bin":                70,
+	"hebrew_bin":               71,
+	"hp8_bin":                  72,
+	"keybcs2_bin":              73,
+	"koi8r_bin":                74,
+	"koi8u_bin":                75,
+	"latin2_bin":               77,
+	"latin5_bin":               78,
+	"latin7_bin":               79,
+	"cp850_bin":                80,
+	"cp852_bin":                81,
+	"swe7_bin":                 82,
+	"utf8_bin":                 83,
+	"big5_bin":                 84,
+	"euckr_bin":                85,
+	"gb2312_bin":               86,
+	"gbk_bin":                  87,
+	"sjis_bin":                 88,
+	"tis620_bin":               89,
+	"ucs2_bin":                 90,
+	"ujis_bin":                 91,
+	"geostd8_general_ci":       92,
+	"geostd8_bin":              93,
+	"latin1_spanish_ci":        94,
+	"cp932_japanese_ci":        95,
+	"cp932_bin":                96,
+	"eucjpms_japanese_ci":      97,
+	"eucjpms_bin":              98,
+	"cp1250_polish_ci":         99,
+	"utf16_unicode_ci":         101,
+	"utf16_icelandic_ci":       102,
+	"utf16_latvian_ci":         103,
+	"utf16_romanian_ci":        104,
+	"utf16_slovenian_ci":       105,
+	"utf16_polish_ci":          106,
+	"utf16_estonian_ci":        107,
+	"utf16_spanish_ci":         108,
+	"utf16_swedish_ci":         109,
+	"utf16_turkish_ci":         110,
+	"utf16_czech_ci":           111,
+	"utf16_danish_ci":          112,
+	"utf16_lithuanian_ci":      113,
+	"utf16_slovak_ci":          114,
+	"utf16_spanish2_ci":        115,
+	"utf16_roman_ci":           116,
+	"utf16_persian_ci":         117,
+	"utf16_esperanto_ci":       118,
+	"utf16_hungarian_ci":       119,
+	"utf16_sinhala_ci":         120,
+	"utf16_german2_ci":         121,
+	"utf16_croatian_ci":        122,
+	"utf16_unicode_520_ci":     123,
+	"utf16_vietnamese_ci":      124,
+	"ucs2_unicode_ci":          128,
+	"ucs2_icelandic_ci":        129,
+	"ucs2_latvian_ci":          130,
+	"ucs2_romanian_ci":         131,
+	"ucs2_slovenian_ci":        132,
+	"ucs2_polish_ci":           133,
+	"ucs2_estonian_ci":         134,
+	"ucs2_spanish_ci":          135,
+	"ucs2_swedish_ci":          136,
+	"ucs2_turkish_ci":          137,
+	"ucs2_czech_ci":            138,
+	"ucs2_danish_ci":           139,
+	"ucs2_lithuanian_ci":       140,
+	"ucs2_slovak_ci":           141,
+	"ucs2_spanish2_ci":         142,
+	"ucs2_roman_ci":            143,
+	"ucs2_persian_ci":          144,
+	"ucs2_esperanto_ci":        145,
+	"ucs2_hungarian_ci":        146,
+	"ucs2_sinhala_ci":          147,
+	"ucs2_german2_ci":          148,
+	"ucs2_croatian_ci":         149,
+	"ucs2_unicode_520_ci":      150,
+	"ucs2_vietnamese_ci":       151,
+	"ucs2_general_mysql500_ci": 159,
+	"utf32_unicode_ci":         160,
+	"utf32_icelandic_ci":       161,
+	"utf32_latvian_ci":         162,
+	"utf32_romanian_ci":        163,
+	"utf32_slovenian_ci":       164,
+	"utf32_polish_ci":          165,
+	"utf32_estonian_ci":        166,
+	"utf32_spanish_ci":         167,
+	"utf32_swedish_ci":         168,
+	"utf32_turkish_ci":         169,
+	"utf32_czech_ci":           170,
+	"utf32_danish_ci":          171,
+	"utf32_lithuanian_ci":      172,
+	"utf32_slovak_ci":          173,
+	"utf32_spanish2_ci":        174,
+	"utf32_roman_ci":           175,
+	"utf32_persian_ci":         176,
+	"utf32_esperanto_ci":       177,
+	"utf32_hungarian_ci":       178,
+	"utf32_sinhala_ci":         179,
+	"utf32_german2_ci":         180,
+	"utf32_croatian_ci":        181,
+	"utf32_unicode_520_ci":     182,
+	"utf32_vietnamese_ci":      183,
+	"utf8_unicode_ci":          192,
+	"utf8_icelandic_ci":        193,
+	"utf8_latvian_ci":          194,
+	"utf8_romanian_ci":         195,
+	"utf8_slovenian_ci":        196,
+	"utf8_polish_ci":           197,
+	"utf8_estonian_ci":         198,
+	"utf8_spanish_ci":          199,
+	"utf8_swedish_ci":          200,
+	"utf8_turkish_ci":          201,
+	"utf8_czech_ci":            202,
+	"utf8_danish_ci":           203,
+	"utf8_lithuanian_ci":       204,
+	"utf8_slovak_ci":           205,
+	"utf8_spanish2_ci":         206,
+	"utf8_roman_ci":            207,
+	"utf8_persian_ci":          208,
+	"utf8_esperanto_ci":        209,
+	"utf8_hungarian_ci":        210,
+	"utf8_sinhala_ci":          211,
+	"utf8_german2_ci":          212,
+	"utf8_croatian_ci":         213,
+	"utf8_unicode_520_ci":      214,
+	"utf8_vietnamese_ci":       215,
+	"utf8_general_mysql500_ci": 223,
+	"utf8mb4_unicode_ci":       224,
+	"utf8mb4_icelandic_ci":     225,
+	"utf8mb4_latvian_ci":       226,
+	"utf8mb4_romanian_ci":      227,
+	"utf8mb4_slovenian_ci":     228,
+	"utf8mb4_polish_ci":        229,
+	"utf8mb4_estonian_ci":      230,
+	"utf8mb4_spanish_ci":       231,
+	"utf8mb4_swedish_ci":       232,
+	"utf8mb4_turkish_ci":       233,
+	"utf8mb4_czech_ci":         234,
+	"utf8mb4_danish_ci":        235,
+	"utf8mb4_lithuanian_ci":    236,
+	"utf8mb4_slovak_ci":        237,
+	"utf8mb4_spanish2_ci":      238,
+	"utf8mb4_roman_ci":         239,
+	"utf8mb4_persian_ci":       240,
+	"utf8mb4_esperanto_ci":     241,
+	"utf8mb4_hungarian_ci":     242,
+	"utf8mb4_sinhala_ci":       243,
+	"utf8mb4_german2_ci":       244,
+	"utf8mb4_croatian_ci":      245,
+	"utf8mb4_unicode_520_ci":   246,
+	"utf8mb4_vietnamese_ci":    247,
+}

+ 268 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/connection.go

@@ -0,0 +1,268 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"crypto/tls"
+	"database/sql/driver"
+	"errors"
+	"net"
+	"strings"
+	"time"
+)
+
+type mysqlConn struct {
+	buf              buffer
+	netConn          net.Conn
+	affectedRows     uint64
+	insertId         uint64
+	cfg              *config
+	maxPacketAllowed int
+	maxWriteSize     int
+	flags            clientFlag
+	sequence         uint8
+	parseTime        bool
+	strict           bool
+}
+
+type config struct {
+	user              string
+	passwd            string
+	net               string
+	addr              string
+	dbname            string
+	params            map[string]string
+	loc               *time.Location
+	tls               *tls.Config
+	timeout           time.Duration
+	collation         uint8
+	allowAllFiles     bool
+	allowOldPasswords bool
+	clientFoundRows   bool
+}
+
+// Handles parameters set in DSN after the connection is established
+func (mc *mysqlConn) handleParams() (err error) {
+	for param, val := range mc.cfg.params {
+		switch param {
+		// Charset
+		case "charset":
+			charsets := strings.Split(val, ",")
+			for i := range charsets {
+				// ignore errors here - a charset may not exist
+				err = mc.exec("SET NAMES " + charsets[i])
+				if err == nil {
+					break
+				}
+			}
+			if err != nil {
+				return
+			}
+
+		// time.Time parsing
+		case "parseTime":
+			var isBool bool
+			mc.parseTime, isBool = readBool(val)
+			if !isBool {
+				return errors.New("Invalid Bool value: " + val)
+			}
+
+		// Strict mode
+		case "strict":
+			var isBool bool
+			mc.strict, isBool = readBool(val)
+			if !isBool {
+				return errors.New("Invalid Bool value: " + val)
+			}
+
+		// Compression
+		case "compress":
+			err = errors.New("Compression not implemented yet")
+			return
+
+		// System Vars
+		default:
+			err = mc.exec("SET " + param + "=" + val + "")
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+func (mc *mysqlConn) Begin() (driver.Tx, error) {
+	if mc.netConn == nil {
+		errLog.Print(ErrInvalidConn)
+		return nil, driver.ErrBadConn
+	}
+	err := mc.exec("START TRANSACTION")
+	if err == nil {
+		return &mysqlTx{mc}, err
+	}
+
+	return nil, err
+}
+
+func (mc *mysqlConn) Close() (err error) {
+	// Makes Close idempotent
+	if mc.netConn != nil {
+		err = mc.writeCommandPacket(comQuit)
+		if err == nil {
+			err = mc.netConn.Close()
+		} else {
+			mc.netConn.Close()
+		}
+		mc.netConn = nil
+	}
+
+	mc.cfg = nil
+	mc.buf.rd = nil
+
+	return
+}
+
+func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {
+	if mc.netConn == nil {
+		errLog.Print(ErrInvalidConn)
+		return nil, driver.ErrBadConn
+	}
+	// Send command
+	err := mc.writeCommandPacketStr(comStmtPrepare, query)
+	if err != nil {
+		return nil, err
+	}
+
+	stmt := &mysqlStmt{
+		mc: mc,
+	}
+
+	// Read Result
+	columnCount, err := stmt.readPrepareResultPacket()
+	if err == nil {
+		if stmt.paramCount > 0 {
+			if err = mc.readUntilEOF(); err != nil {
+				return nil, err
+			}
+		}
+
+		if columnCount > 0 {
+			err = mc.readUntilEOF()
+		}
+	}
+
+	return stmt, err
+}
+
+func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, error) {
+	if mc.netConn == nil {
+		errLog.Print(ErrInvalidConn)
+		return nil, driver.ErrBadConn
+	}
+	if len(args) == 0 { // no args, fastpath
+		mc.affectedRows = 0
+		mc.insertId = 0
+
+		err := mc.exec(query)
+		if err == nil {
+			return &mysqlResult{
+				affectedRows: int64(mc.affectedRows),
+				insertId:     int64(mc.insertId),
+			}, err
+		}
+		return nil, err
+	}
+
+	// with args, must use prepared stmt
+	return nil, driver.ErrSkip
+
+}
+
+// Internal function to execute commands
+func (mc *mysqlConn) exec(query string) error {
+	// Send command
+	err := mc.writeCommandPacketStr(comQuery, query)
+	if err != nil {
+		return err
+	}
+
+	// Read Result
+	resLen, err := mc.readResultSetHeaderPacket()
+	if err == nil && resLen > 0 {
+		if err = mc.readUntilEOF(); err != nil {
+			return err
+		}
+
+		err = mc.readUntilEOF()
+	}
+
+	return err
+}
+
+func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, error) {
+	if mc.netConn == nil {
+		errLog.Print(ErrInvalidConn)
+		return nil, driver.ErrBadConn
+	}
+	if len(args) == 0 { // no args, fastpath
+		// Send command
+		err := mc.writeCommandPacketStr(comQuery, query)
+		if err == nil {
+			// Read Result
+			var resLen int
+			resLen, err = mc.readResultSetHeaderPacket()
+			if err == nil {
+				rows := new(textRows)
+				rows.mc = mc
+
+				if resLen == 0 {
+					// no columns, no more data
+					return emptyRows{}, nil
+				}
+				// Columns
+				rows.columns, err = mc.readColumns(resLen)
+				return rows, err
+			}
+		}
+		return nil, err
+	}
+
+	// with args, must use prepared stmt
+	return nil, driver.ErrSkip
+}
+
+// Gets the value of the given MySQL System Variable
+// The returned byte slice is only valid until the next read
+func (mc *mysqlConn) getSystemVar(name string) ([]byte, error) {
+	// Send command
+	if err := mc.writeCommandPacketStr(comQuery, "SELECT @@"+name); err != nil {
+		return nil, err
+	}
+
+	// Read Result
+	resLen, err := mc.readResultSetHeaderPacket()
+	if err == nil {
+		rows := new(textRows)
+		rows.mc = mc
+
+		if resLen > 0 {
+			// Columns
+			if err := mc.readUntilEOF(); err != nil {
+				return nil, err
+			}
+		}
+
+		dest := make([]driver.Value, resLen)
+		if err = rows.readRow(dest); err == nil {
+			return dest[0].([]byte), mc.readUntilEOF()
+		}
+	}
+	return nil, err
+}

+ 132 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/const.go

@@ -0,0 +1,132 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+const (
+	minProtocolVersion byte = 10
+	maxPacketSize           = 1<<24 - 1
+	timeFormat              = "2006-01-02 15:04:05.999999"
+)
+
+// MySQL constants documentation:
+// http://dev.mysql.com/doc/internals/en/client-server-protocol.html
+
+const (
+	iOK          byte = 0x00
+	iLocalInFile byte = 0xfb
+	iEOF         byte = 0xfe
+	iERR         byte = 0xff
+)
+
+type clientFlag uint32
+
+const (
+	clientLongPassword clientFlag = 1 << iota
+	clientFoundRows
+	clientLongFlag
+	clientConnectWithDB
+	clientNoSchema
+	clientCompress
+	clientODBC
+	clientLocalFiles
+	clientIgnoreSpace
+	clientProtocol41
+	clientInteractive
+	clientSSL
+	clientIgnoreSIGPIPE
+	clientTransactions
+	clientReserved
+	clientSecureConn
+	clientMultiStatements
+	clientMultiResults
+)
+
+const (
+	comQuit byte = iota + 1
+	comInitDB
+	comQuery
+	comFieldList
+	comCreateDB
+	comDropDB
+	comRefresh
+	comShutdown
+	comStatistics
+	comProcessInfo
+	comConnect
+	comProcessKill
+	comDebug
+	comPing
+	comTime
+	comDelayedInsert
+	comChangeUser
+	comBinlogDump
+	comTableDump
+	comConnectOut
+	comRegiserSlave
+	comStmtPrepare
+	comStmtExecute
+	comStmtSendLongData
+	comStmtClose
+	comStmtReset
+	comSetOption
+	comStmtFetch
+)
+
+const (
+	fieldTypeDecimal byte = iota
+	fieldTypeTiny
+	fieldTypeShort
+	fieldTypeLong
+	fieldTypeFloat
+	fieldTypeDouble
+	fieldTypeNULL
+	fieldTypeTimestamp
+	fieldTypeLongLong
+	fieldTypeInt24
+	fieldTypeDate
+	fieldTypeTime
+	fieldTypeDateTime
+	fieldTypeYear
+	fieldTypeNewDate
+	fieldTypeVarChar
+	fieldTypeBit
+)
+const (
+	fieldTypeNewDecimal byte = iota + 0xf6
+	fieldTypeEnum
+	fieldTypeSet
+	fieldTypeTinyBLOB
+	fieldTypeMediumBLOB
+	fieldTypeLongBLOB
+	fieldTypeBLOB
+	fieldTypeVarString
+	fieldTypeString
+	fieldTypeGeometry
+)
+
+type fieldFlag uint16
+
+const (
+	flagNotNULL fieldFlag = 1 << iota
+	flagPriKey
+	flagUniqueKey
+	flagMultipleKey
+	flagBLOB
+	flagUnsigned
+	flagZeroFill
+	flagBinary
+	flagEnum
+	flagAutoIncrement
+	flagTimestamp
+	flagSet
+	flagUnknown1
+	flagUnknown2
+	flagUnknown3
+	flagUnknown4
+)

+ 138 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/driver.go

@@ -0,0 +1,138 @@
+// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// The driver should be used via the database/sql package:
+//
+//  import "database/sql"
+//  import _ "github.com/go-sql-driver/mysql"
+//
+//  db, err := sql.Open("mysql", "user:password@/dbname")
+//
+// See https://github.com/go-sql-driver/mysql#usage for details
+package mysql
+
+import (
+	"database/sql"
+	"database/sql/driver"
+	"net"
+)
+
+// This struct is exported to make the driver directly accessible.
+// In general the driver is used via the database/sql package.
+type MySQLDriver struct{}
+
+// DialFunc is a function which can be used to establish the network connection.
+// Custom dial functions must be registered with RegisterDial
+type DialFunc func(addr string) (net.Conn, error)
+
+var dials map[string]DialFunc
+
+// RegisterDial registers a custom dial function. It can then be used by the
+// network address mynet(addr), where mynet is the registered new network.
+// addr is passed as a parameter to the dial function.
+func RegisterDial(net string, dial DialFunc) {
+	if dials == nil {
+		dials = make(map[string]DialFunc)
+	}
+	dials[net] = dial
+}
+
+// Open new Connection.
+// See https://github.com/go-sql-driver/mysql#dsn-data-source-name for how
+// the DSN string is formated
+func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
+	var err error
+
+	// New mysqlConn
+	mc := &mysqlConn{
+		maxPacketAllowed: maxPacketSize,
+		maxWriteSize:     maxPacketSize - 1,
+	}
+	mc.cfg, err = parseDSN(dsn)
+	if err != nil {
+		return nil, err
+	}
+
+	// Connect to Server
+	if dial, ok := dials[mc.cfg.net]; ok {
+		mc.netConn, err = dial(mc.cfg.addr)
+	} else {
+		nd := net.Dialer{Timeout: mc.cfg.timeout}
+		mc.netConn, err = nd.Dial(mc.cfg.net, mc.cfg.addr)
+	}
+	if err != nil {
+		return nil, err
+	}
+
+	// Enable TCP Keepalives on TCP connections
+	if tc, ok := mc.netConn.(*net.TCPConn); ok {
+		if err := tc.SetKeepAlive(true); err != nil {
+			mc.Close()
+			return nil, err
+		}
+	}
+
+	mc.buf = newBuffer(mc.netConn)
+
+	// Reading Handshake Initialization Packet
+	cipher, err := mc.readInitPacket()
+	if err != nil {
+		mc.Close()
+		return nil, err
+	}
+
+	// Send Client Authentication Packet
+	if err = mc.writeAuthPacket(cipher); err != nil {
+		mc.Close()
+		return nil, err
+	}
+
+	// Read Result Packet
+	err = mc.readResultOK()
+	if err != nil {
+		// Retry with old authentication method, if allowed
+		if mc.cfg != nil && mc.cfg.allowOldPasswords && err == ErrOldPassword {
+			if err = mc.writeOldAuthPacket(cipher); err != nil {
+				mc.Close()
+				return nil, err
+			}
+			if err = mc.readResultOK(); err != nil {
+				mc.Close()
+				return nil, err
+			}
+		} else {
+			mc.Close()
+			return nil, err
+		}
+
+	}
+
+	// Get max allowed packet size
+	maxap, err := mc.getSystemVar("max_allowed_packet")
+	if err != nil {
+		mc.Close()
+		return nil, err
+	}
+	mc.maxPacketAllowed = stringToInt(maxap) - 1
+	if mc.maxPacketAllowed < maxPacketSize {
+		mc.maxWriteSize = mc.maxPacketAllowed
+	}
+
+	// Handle DSN Params
+	err = mc.handleParams()
+	if err != nil {
+		mc.Close()
+		return nil, err
+	}
+
+	return mc, nil
+}
+
+func init() {
+	sql.Register("mysql", &MySQLDriver{})
+}

+ 1540 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/driver_test.go

@@ -0,0 +1,1540 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"crypto/tls"
+	"database/sql"
+	"database/sql/driver"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/url"
+	"os"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"testing"
+	"time"
+)
+
+var (
+	user      string
+	pass      string
+	prot      string
+	addr      string
+	dbname    string
+	dsn       string
+	netAddr   string
+	available bool
+)
+
+var (
+	tDate      = time.Date(2012, 6, 14, 0, 0, 0, 0, time.UTC)
+	sDate      = "2012-06-14"
+	tDateTime  = time.Date(2011, 11, 20, 21, 27, 37, 0, time.UTC)
+	sDateTime  = "2011-11-20 21:27:37"
+	tDate0     = time.Time{}
+	sDate0     = "0000-00-00"
+	sDateTime0 = "0000-00-00 00:00:00"
+)
+
+// See https://github.com/go-sql-driver/mysql/wiki/Testing
+func init() {
+	// get environment variables
+	env := func(key, defaultValue string) string {
+		if value := os.Getenv(key); value != "" {
+			return value
+		}
+		return defaultValue
+	}
+	user = env("MYSQL_TEST_USER", "root")
+	pass = env("MYSQL_TEST_PASS", "")
+	prot = env("MYSQL_TEST_PROT", "tcp")
+	addr = env("MYSQL_TEST_ADDR", "localhost:3306")
+	dbname = env("MYSQL_TEST_DBNAME", "gotest")
+	netAddr = fmt.Sprintf("%s(%s)", prot, addr)
+	dsn = fmt.Sprintf("%s:%s@%s/%s?timeout=30s&strict=true", user, pass, netAddr, dbname)
+	c, err := net.Dial(prot, addr)
+	if err == nil {
+		available = true
+		c.Close()
+	}
+}
+
+type DBTest struct {
+	*testing.T
+	db *sql.DB
+}
+
+func runTests(t *testing.T, dsn string, tests ...func(dbt *DBTest)) {
+	if !available {
+		t.Skipf("MySQL-Server not running on %s", netAddr)
+	}
+
+	db, err := sql.Open("mysql", dsn)
+	if err != nil {
+		t.Fatalf("Error connecting: %s", err.Error())
+	}
+	defer db.Close()
+
+	db.Exec("DROP TABLE IF EXISTS test")
+
+	dbt := &DBTest{t, db}
+	for _, test := range tests {
+		test(dbt)
+		dbt.db.Exec("DROP TABLE IF EXISTS test")
+	}
+}
+
+func (dbt *DBTest) fail(method, query string, err error) {
+	if len(query) > 300 {
+		query = "[query too large to print]"
+	}
+	dbt.Fatalf("Error on %s %s: %s", method, query, err.Error())
+}
+
+func (dbt *DBTest) mustExec(query string, args ...interface{}) (res sql.Result) {
+	res, err := dbt.db.Exec(query, args...)
+	if err != nil {
+		dbt.fail("Exec", query, err)
+	}
+	return res
+}
+
+func (dbt *DBTest) mustQuery(query string, args ...interface{}) (rows *sql.Rows) {
+	rows, err := dbt.db.Query(query, args...)
+	if err != nil {
+		dbt.fail("Query", query, err)
+	}
+	return rows
+}
+
+func TestEmptyQuery(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		// just a comment, no query
+		rows := dbt.mustQuery("--")
+		// will hang before #255
+		if rows.Next() {
+			dbt.Errorf("Next on rows must be false")
+		}
+	})
+}
+
+func TestCRUD(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		// Create Table
+		dbt.mustExec("CREATE TABLE test (value BOOL)")
+
+		// Test for unexpected data
+		var out bool
+		rows := dbt.mustQuery("SELECT * FROM test")
+		if rows.Next() {
+			dbt.Error("unexpected data in empty table")
+		}
+
+		// Create Data
+		res := dbt.mustExec("INSERT INTO test VALUES (1)")
+		count, err := res.RowsAffected()
+		if err != nil {
+			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
+		}
+		if count != 1 {
+			dbt.Fatalf("Expected 1 affected row, got %d", count)
+		}
+
+		id, err := res.LastInsertId()
+		if err != nil {
+			dbt.Fatalf("res.LastInsertId() returned error: %s", err.Error())
+		}
+		if id != 0 {
+			dbt.Fatalf("Expected InsertID 0, got %d", id)
+		}
+
+		// Read
+		rows = dbt.mustQuery("SELECT value FROM test")
+		if rows.Next() {
+			rows.Scan(&out)
+			if true != out {
+				dbt.Errorf("true != %t", out)
+			}
+
+			if rows.Next() {
+				dbt.Error("unexpected data")
+			}
+		} else {
+			dbt.Error("no data")
+		}
+
+		// Update
+		res = dbt.mustExec("UPDATE test SET value = ? WHERE value = ?", false, true)
+		count, err = res.RowsAffected()
+		if err != nil {
+			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
+		}
+		if count != 1 {
+			dbt.Fatalf("Expected 1 affected row, got %d", count)
+		}
+
+		// Check Update
+		rows = dbt.mustQuery("SELECT value FROM test")
+		if rows.Next() {
+			rows.Scan(&out)
+			if false != out {
+				dbt.Errorf("false != %t", out)
+			}
+
+			if rows.Next() {
+				dbt.Error("unexpected data")
+			}
+		} else {
+			dbt.Error("no data")
+		}
+
+		// Delete
+		res = dbt.mustExec("DELETE FROM test WHERE value = ?", false)
+		count, err = res.RowsAffected()
+		if err != nil {
+			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
+		}
+		if count != 1 {
+			dbt.Fatalf("Expected 1 affected row, got %d", count)
+		}
+
+		// Check for unexpected rows
+		res = dbt.mustExec("DELETE FROM test")
+		count, err = res.RowsAffected()
+		if err != nil {
+			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
+		}
+		if count != 0 {
+			dbt.Fatalf("Expected 0 affected row, got %d", count)
+		}
+	})
+}
+
+func TestInt(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		types := [5]string{"TINYINT", "SMALLINT", "MEDIUMINT", "INT", "BIGINT"}
+		in := int64(42)
+		var out int64
+		var rows *sql.Rows
+
+		// SIGNED
+		for _, v := range types {
+			dbt.mustExec("CREATE TABLE test (value " + v + ")")
+
+			dbt.mustExec("INSERT INTO test VALUES (?)", in)
+
+			rows = dbt.mustQuery("SELECT value FROM test")
+			if rows.Next() {
+				rows.Scan(&out)
+				if in != out {
+					dbt.Errorf("%s: %d != %d", v, in, out)
+				}
+			} else {
+				dbt.Errorf("%s: no data", v)
+			}
+
+			dbt.mustExec("DROP TABLE IF EXISTS test")
+		}
+
+		// UNSIGNED ZEROFILL
+		for _, v := range types {
+			dbt.mustExec("CREATE TABLE test (value " + v + " ZEROFILL)")
+
+			dbt.mustExec("INSERT INTO test VALUES (?)", in)
+
+			rows = dbt.mustQuery("SELECT value FROM test")
+			if rows.Next() {
+				rows.Scan(&out)
+				if in != out {
+					dbt.Errorf("%s ZEROFILL: %d != %d", v, in, out)
+				}
+			} else {
+				dbt.Errorf("%s ZEROFILL: no data", v)
+			}
+
+			dbt.mustExec("DROP TABLE IF EXISTS test")
+		}
+	})
+}
+
+func TestFloat(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		types := [2]string{"FLOAT", "DOUBLE"}
+		in := float32(42.23)
+		var out float32
+		var rows *sql.Rows
+		for _, v := range types {
+			dbt.mustExec("CREATE TABLE test (value " + v + ")")
+			dbt.mustExec("INSERT INTO test VALUES (?)", in)
+			rows = dbt.mustQuery("SELECT value FROM test")
+			if rows.Next() {
+				rows.Scan(&out)
+				if in != out {
+					dbt.Errorf("%s: %g != %g", v, in, out)
+				}
+			} else {
+				dbt.Errorf("%s: no data", v)
+			}
+			dbt.mustExec("DROP TABLE IF EXISTS test")
+		}
+	})
+}
+
+func TestString(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		types := [6]string{"CHAR(255)", "VARCHAR(255)", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT"}
+		in := "κόσμε üöäßñóùéàâÿœ'îë Árvíztűrő いろはにほへとちりぬるを イロハニホヘト דג סקרן чащах  น่าฟังเอย"
+		var out string
+		var rows *sql.Rows
+
+		for _, v := range types {
+			dbt.mustExec("CREATE TABLE test (value " + v + ") CHARACTER SET utf8")
+
+			dbt.mustExec("INSERT INTO test VALUES (?)", in)
+
+			rows = dbt.mustQuery("SELECT value FROM test")
+			if rows.Next() {
+				rows.Scan(&out)
+				if in != out {
+					dbt.Errorf("%s: %s != %s", v, in, out)
+				}
+			} else {
+				dbt.Errorf("%s: no data", v)
+			}
+
+			dbt.mustExec("DROP TABLE IF EXISTS test")
+		}
+
+		// BLOB
+		dbt.mustExec("CREATE TABLE test (id int, value BLOB) CHARACTER SET utf8")
+
+		id := 2
+		in = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " +
+			"sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " +
+			"sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. " +
+			"Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. " +
+			"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " +
+			"sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " +
+			"sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. " +
+			"Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
+		dbt.mustExec("INSERT INTO test VALUES (?, ?)", id, in)
+
+		err := dbt.db.QueryRow("SELECT value FROM test WHERE id = ?", id).Scan(&out)
+		if err != nil {
+			dbt.Fatalf("Error on BLOB-Query: %s", err.Error())
+		} else if out != in {
+			dbt.Errorf("BLOB: %s != %s", in, out)
+		}
+	})
+}
+
+type timeTests struct {
+	dbtype  string
+	tlayout string
+	tests   []timeTest
+}
+
+type timeTest struct {
+	s string // leading "!": do not use t as value in queries
+	t time.Time
+}
+
+type timeMode byte
+
+func (t timeMode) String() string {
+	switch t {
+	case binaryString:
+		return "binary:string"
+	case binaryTime:
+		return "binary:time.Time"
+	case textString:
+		return "text:string"
+	}
+	panic("unsupported timeMode")
+}
+
+func (t timeMode) Binary() bool {
+	switch t {
+	case binaryString, binaryTime:
+		return true
+	}
+	return false
+}
+
+const (
+	binaryString timeMode = iota
+	binaryTime
+	textString
+)
+
+func (t timeTest) genQuery(dbtype string, mode timeMode) string {
+	var inner string
+	if mode.Binary() {
+		inner = "?"
+	} else {
+		inner = `"%s"`
+	}
+	return `SELECT cast(` + inner + ` as ` + dbtype + `)`
+}
+
+func (t timeTest) run(dbt *DBTest, dbtype, tlayout string, mode timeMode) {
+	var rows *sql.Rows
+	query := t.genQuery(dbtype, mode)
+	switch mode {
+	case binaryString:
+		rows = dbt.mustQuery(query, t.s)
+	case binaryTime:
+		rows = dbt.mustQuery(query, t.t)
+	case textString:
+		query = fmt.Sprintf(query, t.s)
+		rows = dbt.mustQuery(query)
+	default:
+		panic("unsupported mode")
+	}
+	defer rows.Close()
+	var err error
+	if !rows.Next() {
+		err = rows.Err()
+		if err == nil {
+			err = fmt.Errorf("no data")
+		}
+		dbt.Errorf("%s [%s]: %s", dbtype, mode, err)
+		return
+	}
+	var dst interface{}
+	err = rows.Scan(&dst)
+	if err != nil {
+		dbt.Errorf("%s [%s]: %s", dbtype, mode, err)
+		return
+	}
+	switch val := dst.(type) {
+	case []uint8:
+		str := string(val)
+		if str == t.s {
+			return
+		}
+		if mode.Binary() && dbtype == "DATETIME" && len(str) == 26 && str[:19] == t.s {
+			// a fix mainly for TravisCI:
+			// accept full microsecond resolution in result for DATETIME columns
+			// where the binary protocol was used
+			return
+		}
+		dbt.Errorf("%s [%s] to string: expected %q, got %q",
+			dbtype, mode,
+			t.s, str,
+		)
+	case time.Time:
+		if val == t.t {
+			return
+		}
+		dbt.Errorf("%s [%s] to string: expected %q, got %q",
+			dbtype, mode,
+			t.s, val.Format(tlayout),
+		)
+	default:
+		fmt.Printf("%#v\n", []interface{}{dbtype, tlayout, mode, t.s, t.t})
+		dbt.Errorf("%s [%s]: unhandled type %T (is '%v')",
+			dbtype, mode,
+			val, val,
+		)
+	}
+}
+
+func TestDateTime(t *testing.T) {
+	afterTime := func(t time.Time, d string) time.Time {
+		dur, err := time.ParseDuration(d)
+		if err != nil {
+			panic(err)
+		}
+		return t.Add(dur)
+	}
+	// NOTE: MySQL rounds DATETIME(x) up - but that's not included in the tests
+	format := "2006-01-02 15:04:05.999999"
+	t0 := time.Time{}
+	tstr0 := "0000-00-00 00:00:00.000000"
+	testcases := []timeTests{
+		{"DATE", format[:10], []timeTest{
+			{t: time.Date(2011, 11, 20, 0, 0, 0, 0, time.UTC)},
+			{t: t0, s: tstr0[:10]},
+		}},
+		{"DATETIME", format[:19], []timeTest{
+			{t: time.Date(2011, 11, 20, 21, 27, 37, 0, time.UTC)},
+			{t: t0, s: tstr0[:19]},
+		}},
+		{"DATETIME(0)", format[:21], []timeTest{
+			{t: time.Date(2011, 11, 20, 21, 27, 37, 0, time.UTC)},
+			{t: t0, s: tstr0[:19]},
+		}},
+		{"DATETIME(1)", format[:21], []timeTest{
+			{t: time.Date(2011, 11, 20, 21, 27, 37, 100000000, time.UTC)},
+			{t: t0, s: tstr0[:21]},
+		}},
+		{"DATETIME(6)", format, []timeTest{
+			{t: time.Date(2011, 11, 20, 21, 27, 37, 123456000, time.UTC)},
+			{t: t0, s: tstr0},
+		}},
+		{"TIME", format[11:19], []timeTest{
+			{t: afterTime(t0, "12345s")},
+			{s: "!-12:34:56"},
+			{s: "!-838:59:59"},
+			{s: "!838:59:59"},
+			{t: t0, s: tstr0[11:19]},
+		}},
+		{"TIME(0)", format[11:19], []timeTest{
+			{t: afterTime(t0, "12345s")},
+			{s: "!-12:34:56"},
+			{s: "!-838:59:59"},
+			{s: "!838:59:59"},
+			{t: t0, s: tstr0[11:19]},
+		}},
+		{"TIME(1)", format[11:21], []timeTest{
+			{t: afterTime(t0, "12345600ms")},
+			{s: "!-12:34:56.7"},
+			{s: "!-838:59:58.9"},
+			{s: "!838:59:58.9"},
+			{t: t0, s: tstr0[11:21]},
+		}},
+		{"TIME(6)", format[11:], []timeTest{
+			{t: afterTime(t0, "1234567890123000ns")},
+			{s: "!-12:34:56.789012"},
+			{s: "!-838:59:58.999999"},
+			{s: "!838:59:58.999999"},
+			{t: t0, s: tstr0[11:]},
+		}},
+	}
+	dsns := []string{
+		dsn + "&parseTime=true",
+		dsn + "&parseTime=false",
+	}
+	for _, testdsn := range dsns {
+		runTests(t, testdsn, func(dbt *DBTest) {
+			microsecsSupported := false
+			zeroDateSupported := false
+			var rows *sql.Rows
+			var err error
+			rows, err = dbt.db.Query(`SELECT cast("00:00:00.1" as TIME(1)) = "00:00:00.1"`)
+			if err == nil {
+				rows.Scan(&microsecsSupported)
+				rows.Close()
+			}
+			rows, err = dbt.db.Query(`SELECT cast("0000-00-00" as DATE) = "0000-00-00"`)
+			if err == nil {
+				rows.Scan(&zeroDateSupported)
+				rows.Close()
+			}
+			for _, setups := range testcases {
+				if t := setups.dbtype; !microsecsSupported && t[len(t)-1:] == ")" {
+					// skip fractional second tests if unsupported by server
+					continue
+				}
+				for _, setup := range setups.tests {
+					allowBinTime := true
+					if setup.s == "" {
+						// fill time string whereever Go can reliable produce it
+						setup.s = setup.t.Format(setups.tlayout)
+					} else if setup.s[0] == '!' {
+						// skip tests using setup.t as source in queries
+						allowBinTime = false
+						// fix setup.s - remove the "!"
+						setup.s = setup.s[1:]
+					}
+					if !zeroDateSupported && setup.s == tstr0[:len(setup.s)] {
+						// skip disallowed 0000-00-00 date
+						continue
+					}
+					setup.run(dbt, setups.dbtype, setups.tlayout, textString)
+					setup.run(dbt, setups.dbtype, setups.tlayout, binaryString)
+					if allowBinTime {
+						setup.run(dbt, setups.dbtype, setups.tlayout, binaryTime)
+					}
+				}
+			}
+		})
+	}
+}
+
+func TestTimestampMicros(t *testing.T) {
+	format := "2006-01-02 15:04:05.999999"
+	f0 := format[:19]
+	f1 := format[:21]
+	f6 := format[:26]
+	runTests(t, dsn, func(dbt *DBTest) {
+		// check if microseconds are supported.
+		// Do not use timestamp(x) for that check - before 5.5.6, x would mean display width
+		// and not precision.
+		// Se last paragraph at http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
+		microsecsSupported := false
+		if rows, err := dbt.db.Query(`SELECT cast("00:00:00.1" as TIME(1)) = "00:00:00.1"`); err == nil {
+			rows.Scan(&microsecsSupported)
+			rows.Close()
+		}
+		if !microsecsSupported {
+			// skip test
+			return
+		}
+		_, err := dbt.db.Exec(`
+			CREATE TABLE test (
+				value0 TIMESTAMP NOT NULL DEFAULT '` + f0 + `',
+				value1 TIMESTAMP(1) NOT NULL DEFAULT '` + f1 + `',
+				value6 TIMESTAMP(6) NOT NULL DEFAULT '` + f6 + `'
+			)`,
+		)
+		if err != nil {
+			dbt.Error(err)
+		}
+		defer dbt.mustExec("DROP TABLE IF EXISTS test")
+		dbt.mustExec("INSERT INTO test SET value0=?, value1=?, value6=?", f0, f1, f6)
+		var res0, res1, res6 string
+		rows := dbt.mustQuery("SELECT * FROM test")
+		if !rows.Next() {
+			dbt.Errorf("test contained no selectable values")
+		}
+		err = rows.Scan(&res0, &res1, &res6)
+		if err != nil {
+			dbt.Error(err)
+		}
+		if res0 != f0 {
+			dbt.Errorf("expected %q, got %q", f0, res0)
+		}
+		if res1 != f1 {
+			dbt.Errorf("expected %q, got %q", f1, res1)
+		}
+		if res6 != f6 {
+			dbt.Errorf("expected %q, got %q", f6, res6)
+		}
+	})
+}
+
+func TestNULL(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		nullStmt, err := dbt.db.Prepare("SELECT NULL")
+		if err != nil {
+			dbt.Fatal(err)
+		}
+		defer nullStmt.Close()
+
+		nonNullStmt, err := dbt.db.Prepare("SELECT 1")
+		if err != nil {
+			dbt.Fatal(err)
+		}
+		defer nonNullStmt.Close()
+
+		// NullBool
+		var nb sql.NullBool
+		// Invalid
+		if err = nullStmt.QueryRow().Scan(&nb); err != nil {
+			dbt.Fatal(err)
+		}
+		if nb.Valid {
+			dbt.Error("Valid NullBool which should be invalid")
+		}
+		// Valid
+		if err = nonNullStmt.QueryRow().Scan(&nb); err != nil {
+			dbt.Fatal(err)
+		}
+		if !nb.Valid {
+			dbt.Error("Invalid NullBool which should be valid")
+		} else if nb.Bool != true {
+			dbt.Errorf("Unexpected NullBool value: %t (should be true)", nb.Bool)
+		}
+
+		// NullFloat64
+		var nf sql.NullFloat64
+		// Invalid
+		if err = nullStmt.QueryRow().Scan(&nf); err != nil {
+			dbt.Fatal(err)
+		}
+		if nf.Valid {
+			dbt.Error("Valid NullFloat64 which should be invalid")
+		}
+		// Valid
+		if err = nonNullStmt.QueryRow().Scan(&nf); err != nil {
+			dbt.Fatal(err)
+		}
+		if !nf.Valid {
+			dbt.Error("Invalid NullFloat64 which should be valid")
+		} else if nf.Float64 != float64(1) {
+			dbt.Errorf("Unexpected NullFloat64 value: %f (should be 1.0)", nf.Float64)
+		}
+
+		// NullInt64
+		var ni sql.NullInt64
+		// Invalid
+		if err = nullStmt.QueryRow().Scan(&ni); err != nil {
+			dbt.Fatal(err)
+		}
+		if ni.Valid {
+			dbt.Error("Valid NullInt64 which should be invalid")
+		}
+		// Valid
+		if err = nonNullStmt.QueryRow().Scan(&ni); err != nil {
+			dbt.Fatal(err)
+		}
+		if !ni.Valid {
+			dbt.Error("Invalid NullInt64 which should be valid")
+		} else if ni.Int64 != int64(1) {
+			dbt.Errorf("Unexpected NullInt64 value: %d (should be 1)", ni.Int64)
+		}
+
+		// NullString
+		var ns sql.NullString
+		// Invalid
+		if err = nullStmt.QueryRow().Scan(&ns); err != nil {
+			dbt.Fatal(err)
+		}
+		if ns.Valid {
+			dbt.Error("Valid NullString which should be invalid")
+		}
+		// Valid
+		if err = nonNullStmt.QueryRow().Scan(&ns); err != nil {
+			dbt.Fatal(err)
+		}
+		if !ns.Valid {
+			dbt.Error("Invalid NullString which should be valid")
+		} else if ns.String != `1` {
+			dbt.Error("Unexpected NullString value:" + ns.String + " (should be `1`)")
+		}
+
+		// nil-bytes
+		var b []byte
+		// Read nil
+		if err = nullStmt.QueryRow().Scan(&b); err != nil {
+			dbt.Fatal(err)
+		}
+		if b != nil {
+			dbt.Error("Non-nil []byte wich should be nil")
+		}
+		// Read non-nil
+		if err = nonNullStmt.QueryRow().Scan(&b); err != nil {
+			dbt.Fatal(err)
+		}
+		if b == nil {
+			dbt.Error("Nil []byte wich should be non-nil")
+		}
+		// Insert nil
+		b = nil
+		success := false
+		if err = dbt.db.QueryRow("SELECT ? IS NULL", b).Scan(&success); err != nil {
+			dbt.Fatal(err)
+		}
+		if !success {
+			dbt.Error("Inserting []byte(nil) as NULL failed")
+		}
+		// Check input==output with input==nil
+		b = nil
+		if err = dbt.db.QueryRow("SELECT ?", b).Scan(&b); err != nil {
+			dbt.Fatal(err)
+		}
+		if b != nil {
+			dbt.Error("Non-nil echo from nil input")
+		}
+		// Check input==output with input!=nil
+		b = []byte("")
+		if err = dbt.db.QueryRow("SELECT ?", b).Scan(&b); err != nil {
+			dbt.Fatal(err)
+		}
+		if b == nil {
+			dbt.Error("nil echo from non-nil input")
+		}
+
+		// Insert NULL
+		dbt.mustExec("CREATE TABLE test (dummmy1 int, value int, dummy2 int)")
+
+		dbt.mustExec("INSERT INTO test VALUES (?, ?, ?)", 1, nil, 2)
+
+		var out interface{}
+		rows := dbt.mustQuery("SELECT * FROM test")
+		if rows.Next() {
+			rows.Scan(&out)
+			if out != nil {
+				dbt.Errorf("%v != nil", out)
+			}
+		} else {
+			dbt.Error("no data")
+		}
+	})
+}
+
+func TestLongData(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		var maxAllowedPacketSize int
+		err := dbt.db.QueryRow("select @@max_allowed_packet").Scan(&maxAllowedPacketSize)
+		if err != nil {
+			dbt.Fatal(err)
+		}
+		maxAllowedPacketSize--
+
+		// don't get too ambitious
+		if maxAllowedPacketSize > 1<<25 {
+			maxAllowedPacketSize = 1 << 25
+		}
+
+		dbt.mustExec("CREATE TABLE test (value LONGBLOB)")
+
+		in := strings.Repeat(`a`, maxAllowedPacketSize+1)
+		var out string
+		var rows *sql.Rows
+
+		// Long text data
+		const nonDataQueryLen = 28 // length query w/o value
+		inS := in[:maxAllowedPacketSize-nonDataQueryLen]
+		dbt.mustExec("INSERT INTO test VALUES('" + inS + "')")
+		rows = dbt.mustQuery("SELECT value FROM test")
+		if rows.Next() {
+			rows.Scan(&out)
+			if inS != out {
+				dbt.Fatalf("LONGBLOB: length in: %d, length out: %d", len(inS), len(out))
+			}
+			if rows.Next() {
+				dbt.Error("LONGBLOB: unexpexted row")
+			}
+		} else {
+			dbt.Fatalf("LONGBLOB: no data")
+		}
+
+		// Empty table
+		dbt.mustExec("TRUNCATE TABLE test")
+
+		// Long binary data
+		dbt.mustExec("INSERT INTO test VALUES(?)", in)
+		rows = dbt.mustQuery("SELECT value FROM test WHERE 1=?", 1)
+		if rows.Next() {
+			rows.Scan(&out)
+			if in != out {
+				dbt.Fatalf("LONGBLOB: length in: %d, length out: %d", len(in), len(out))
+			}
+			if rows.Next() {
+				dbt.Error("LONGBLOB: unexpexted row")
+			}
+		} else {
+			if err = rows.Err(); err != nil {
+				dbt.Fatalf("LONGBLOB: no data (err: %s)", err.Error())
+			} else {
+				dbt.Fatal("LONGBLOB: no data (err: <nil>)")
+			}
+		}
+	})
+}
+
+func TestLoadData(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		verifyLoadDataResult := func() {
+			rows, err := dbt.db.Query("SELECT * FROM test")
+			if err != nil {
+				dbt.Fatal(err.Error())
+			}
+
+			i := 0
+			values := [4]string{
+				"a string",
+				"a string containing a \t",
+				"a string containing a \n",
+				"a string containing both \t\n",
+			}
+
+			var id int
+			var value string
+
+			for rows.Next() {
+				i++
+				err = rows.Scan(&id, &value)
+				if err != nil {
+					dbt.Fatal(err.Error())
+				}
+				if i != id {
+					dbt.Fatalf("%d != %d", i, id)
+				}
+				if values[i-1] != value {
+					dbt.Fatalf("%s != %s", values[i-1], value)
+				}
+			}
+			err = rows.Err()
+			if err != nil {
+				dbt.Fatal(err.Error())
+			}
+
+			if i != 4 {
+				dbt.Fatalf("Rows count mismatch. Got %d, want 4", i)
+			}
+		}
+		file, err := ioutil.TempFile("", "gotest")
+		defer os.Remove(file.Name())
+		if err != nil {
+			dbt.Fatal(err)
+		}
+		file.WriteString("1\ta string\n2\ta string containing a \\t\n3\ta string containing a \\n\n4\ta string containing both \\t\\n\n")
+		file.Close()
+
+		dbt.db.Exec("DROP TABLE IF EXISTS test")
+		dbt.mustExec("CREATE TABLE test (id INT NOT NULL PRIMARY KEY, value TEXT NOT NULL) CHARACTER SET utf8")
+
+		// Local File
+		RegisterLocalFile(file.Name())
+		dbt.mustExec(fmt.Sprintf("LOAD DATA LOCAL INFILE '%q' INTO TABLE test", file.Name()))
+		verifyLoadDataResult()
+		// negative test
+		_, err = dbt.db.Exec("LOAD DATA LOCAL INFILE 'doesnotexist' INTO TABLE test")
+		if err == nil {
+			dbt.Fatal("Load non-existent file didn't fail")
+		} else if err.Error() != "Local File 'doesnotexist' is not registered. Use the DSN parameter 'allowAllFiles=true' to allow all files" {
+			dbt.Fatal(err.Error())
+		}
+
+		// Empty table
+		dbt.mustExec("TRUNCATE TABLE test")
+
+		// Reader
+		RegisterReaderHandler("test", func() io.Reader {
+			file, err = os.Open(file.Name())
+			if err != nil {
+				dbt.Fatal(err)
+			}
+			return file
+		})
+		dbt.mustExec("LOAD DATA LOCAL INFILE 'Reader::test' INTO TABLE test")
+		verifyLoadDataResult()
+		// negative test
+		_, err = dbt.db.Exec("LOAD DATA LOCAL INFILE 'Reader::doesnotexist' INTO TABLE test")
+		if err == nil {
+			dbt.Fatal("Load non-existent Reader didn't fail")
+		} else if err.Error() != "Reader 'doesnotexist' is not registered" {
+			dbt.Fatal(err.Error())
+		}
+	})
+}
+
+func TestFoundRows(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		dbt.mustExec("CREATE TABLE test (id INT NOT NULL ,data INT NOT NULL)")
+		dbt.mustExec("INSERT INTO test (id, data) VALUES (0, 0),(0, 0),(1, 0),(1, 0),(1, 1)")
+
+		res := dbt.mustExec("UPDATE test SET data = 1 WHERE id = 0")
+		count, err := res.RowsAffected()
+		if err != nil {
+			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
+		}
+		if count != 2 {
+			dbt.Fatalf("Expected 2 affected rows, got %d", count)
+		}
+		res = dbt.mustExec("UPDATE test SET data = 1 WHERE id = 1")
+		count, err = res.RowsAffected()
+		if err != nil {
+			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
+		}
+		if count != 2 {
+			dbt.Fatalf("Expected 2 affected rows, got %d", count)
+		}
+	})
+	runTests(t, dsn+"&clientFoundRows=true", func(dbt *DBTest) {
+		dbt.mustExec("CREATE TABLE test (id INT NOT NULL ,data INT NOT NULL)")
+		dbt.mustExec("INSERT INTO test (id, data) VALUES (0, 0),(0, 0),(1, 0),(1, 0),(1, 1)")
+
+		res := dbt.mustExec("UPDATE test SET data = 1 WHERE id = 0")
+		count, err := res.RowsAffected()
+		if err != nil {
+			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
+		}
+		if count != 2 {
+			dbt.Fatalf("Expected 2 matched rows, got %d", count)
+		}
+		res = dbt.mustExec("UPDATE test SET data = 1 WHERE id = 1")
+		count, err = res.RowsAffected()
+		if err != nil {
+			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
+		}
+		if count != 3 {
+			dbt.Fatalf("Expected 3 matched rows, got %d", count)
+		}
+	})
+}
+
+func TestStrict(t *testing.T) {
+	// ALLOW_INVALID_DATES to get rid of stricter modes - we want to test for warnings, not errors
+	relaxedDsn := dsn + "&sql_mode=ALLOW_INVALID_DATES"
+	// make sure the MySQL version is recent enough with a separate connection
+	// before running the test
+	conn, err := MySQLDriver{}.Open(relaxedDsn)
+	if conn != nil {
+		conn.Close()
+	}
+	if me, ok := err.(*MySQLError); ok && me.Number == 1231 {
+		// Error 1231: Variable 'sql_mode' can't be set to the value of 'ALLOW_INVALID_DATES'
+		// => skip test, MySQL server version is too old
+		return
+	}
+	runTests(t, relaxedDsn, func(dbt *DBTest) {
+		dbt.mustExec("CREATE TABLE test (a TINYINT NOT NULL, b CHAR(4))")
+
+		var queries = [...]struct {
+			in    string
+			codes []string
+		}{
+			{"DROP TABLE IF EXISTS no_such_table", []string{"1051"}},
+			{"INSERT INTO test VALUES(10,'mysql'),(NULL,'test'),(300,'Open Source')", []string{"1265", "1048", "1264", "1265"}},
+		}
+		var err error
+
+		var checkWarnings = func(err error, mode string, idx int) {
+			if err == nil {
+				dbt.Errorf("Expected STRICT error on query [%s] %s", mode, queries[idx].in)
+			}
+
+			if warnings, ok := err.(MySQLWarnings); ok {
+				var codes = make([]string, len(warnings))
+				for i := range warnings {
+					codes[i] = warnings[i].Code
+				}
+				if len(codes) != len(queries[idx].codes) {
+					dbt.Errorf("Unexpected STRICT error count on query [%s] %s: Wanted %v, Got %v", mode, queries[idx].in, queries[idx].codes, codes)
+				}
+
+				for i := range warnings {
+					if codes[i] != queries[idx].codes[i] {
+						dbt.Errorf("Unexpected STRICT error codes on query [%s] %s: Wanted %v, Got %v", mode, queries[idx].in, queries[idx].codes, codes)
+						return
+					}
+				}
+
+			} else {
+				dbt.Errorf("Unexpected error on query [%s] %s: %s", mode, queries[idx].in, err.Error())
+			}
+		}
+
+		// text protocol
+		for i := range queries {
+			_, err = dbt.db.Exec(queries[i].in)
+			checkWarnings(err, "text", i)
+		}
+
+		var stmt *sql.Stmt
+
+		// binary protocol
+		for i := range queries {
+			stmt, err = dbt.db.Prepare(queries[i].in)
+			if err != nil {
+				dbt.Errorf("Error on preparing query %s: %s", queries[i].in, err.Error())
+			}
+
+			_, err = stmt.Exec()
+			checkWarnings(err, "binary", i)
+
+			err = stmt.Close()
+			if err != nil {
+				dbt.Errorf("Error on closing stmt for query %s: %s", queries[i].in, err.Error())
+			}
+		}
+	})
+}
+
+func TestTLS(t *testing.T) {
+	tlsTest := func(dbt *DBTest) {
+		if err := dbt.db.Ping(); err != nil {
+			if err == ErrNoTLS {
+				dbt.Skip("Server does not support TLS")
+			} else {
+				dbt.Fatalf("Error on Ping: %s", err.Error())
+			}
+		}
+
+		rows := dbt.mustQuery("SHOW STATUS LIKE 'Ssl_cipher'")
+
+		var variable, value *sql.RawBytes
+		for rows.Next() {
+			if err := rows.Scan(&variable, &value); err != nil {
+				dbt.Fatal(err.Error())
+			}
+
+			if value == nil {
+				dbt.Fatal("No Cipher")
+			}
+		}
+	}
+
+	runTests(t, dsn+"&tls=skip-verify", tlsTest)
+
+	// Verify that registering / using a custom cfg works
+	RegisterTLSConfig("custom-skip-verify", &tls.Config{
+		InsecureSkipVerify: true,
+	})
+	runTests(t, dsn+"&tls=custom-skip-verify", tlsTest)
+}
+
+func TestReuseClosedConnection(t *testing.T) {
+	// this test does not use sql.database, it uses the driver directly
+	if !available {
+		t.Skipf("MySQL-Server not running on %s", netAddr)
+	}
+
+	md := &MySQLDriver{}
+	conn, err := md.Open(dsn)
+	if err != nil {
+		t.Fatalf("Error connecting: %s", err.Error())
+	}
+	stmt, err := conn.Prepare("DO 1")
+	if err != nil {
+		t.Fatalf("Error preparing statement: %s", err.Error())
+	}
+	_, err = stmt.Exec(nil)
+	if err != nil {
+		t.Fatalf("Error executing statement: %s", err.Error())
+	}
+	err = conn.Close()
+	if err != nil {
+		t.Fatalf("Error closing connection: %s", err.Error())
+	}
+
+	defer func() {
+		if err := recover(); err != nil {
+			t.Errorf("Panic after reusing a closed connection: %v", err)
+		}
+	}()
+	_, err = stmt.Exec(nil)
+	if err != nil && err != driver.ErrBadConn {
+		t.Errorf("Unexpected error '%s', expected '%s'",
+			err.Error(), driver.ErrBadConn.Error())
+	}
+}
+
+func TestCharset(t *testing.T) {
+	if !available {
+		t.Skipf("MySQL-Server not running on %s", netAddr)
+	}
+
+	mustSetCharset := func(charsetParam, expected string) {
+		runTests(t, dsn+"&"+charsetParam, func(dbt *DBTest) {
+			rows := dbt.mustQuery("SELECT @@character_set_connection")
+			defer rows.Close()
+
+			if !rows.Next() {
+				dbt.Fatalf("Error getting connection charset: %s", rows.Err())
+			}
+
+			var got string
+			rows.Scan(&got)
+
+			if got != expected {
+				dbt.Fatalf("Expected connection charset %s but got %s", expected, got)
+			}
+		})
+	}
+
+	// non utf8 test
+	mustSetCharset("charset=ascii", "ascii")
+
+	// when the first charset is invalid, use the second
+	mustSetCharset("charset=none,utf8", "utf8")
+
+	// when the first charset is valid, use it
+	mustSetCharset("charset=ascii,utf8", "ascii")
+	mustSetCharset("charset=utf8,ascii", "utf8")
+}
+
+func TestFailingCharset(t *testing.T) {
+	runTests(t, dsn+"&charset=none", func(dbt *DBTest) {
+		// run query to really establish connection...
+		_, err := dbt.db.Exec("SELECT 1")
+		if err == nil {
+			dbt.db.Close()
+			t.Fatalf("Connection must not succeed without a valid charset")
+		}
+	})
+}
+
+func TestCollation(t *testing.T) {
+	if !available {
+		t.Skipf("MySQL-Server not running on %s", netAddr)
+	}
+
+	defaultCollation := "utf8_general_ci"
+	testCollations := []string{
+		"",               // do not set
+		defaultCollation, // driver default
+		"latin1_general_ci",
+		"binary",
+		"utf8_unicode_ci",
+		"cp1257_bin",
+	}
+
+	for _, collation := range testCollations {
+		var expected, tdsn string
+		if collation != "" {
+			tdsn = dsn + "&collation=" + collation
+			expected = collation
+		} else {
+			tdsn = dsn
+			expected = defaultCollation
+		}
+
+		runTests(t, tdsn, func(dbt *DBTest) {
+			var got string
+			if err := dbt.db.QueryRow("SELECT @@collation_connection").Scan(&got); err != nil {
+				dbt.Fatal(err)
+			}
+
+			if got != expected {
+				dbt.Fatalf("Expected connection collation %s but got %s", expected, got)
+			}
+		})
+	}
+}
+
+func TestRawBytesResultExceedsBuffer(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		// defaultBufSize from buffer.go
+		expected := strings.Repeat("abc", defaultBufSize)
+
+		rows := dbt.mustQuery("SELECT '" + expected + "'")
+		defer rows.Close()
+		if !rows.Next() {
+			dbt.Error("expected result, got none")
+		}
+		var result sql.RawBytes
+		rows.Scan(&result)
+		if expected != string(result) {
+			dbt.Error("result did not match expected value")
+		}
+	})
+}
+
+func TestTimezoneConversion(t *testing.T) {
+	zones := []string{"UTC", "US/Central", "US/Pacific", "Local"}
+
+	// Regression test for timezone handling
+	tzTest := func(dbt *DBTest) {
+
+		// Create table
+		dbt.mustExec("CREATE TABLE test (ts TIMESTAMP)")
+
+		// Insert local time into database (should be converted)
+		usCentral, _ := time.LoadLocation("US/Central")
+		reftime := time.Date(2014, 05, 30, 18, 03, 17, 0, time.UTC).In(usCentral)
+		dbt.mustExec("INSERT INTO test VALUE (?)", reftime)
+
+		// Retrieve time from DB
+		rows := dbt.mustQuery("SELECT ts FROM test")
+		if !rows.Next() {
+			dbt.Fatal("Didn't get any rows out")
+		}
+
+		var dbTime time.Time
+		err := rows.Scan(&dbTime)
+		if err != nil {
+			dbt.Fatal("Err", err)
+		}
+
+		// Check that dates match
+		if reftime.Unix() != dbTime.Unix() {
+			dbt.Errorf("Times don't match.\n")
+			dbt.Errorf(" Now(%v)=%v\n", usCentral, reftime)
+			dbt.Errorf(" Now(UTC)=%v\n", dbTime)
+		}
+	}
+
+	for _, tz := range zones {
+		runTests(t, dsn+"&parseTime=true&loc="+url.QueryEscape(tz), tzTest)
+	}
+}
+
+// Special cases
+
+func TestRowsClose(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		rows, err := dbt.db.Query("SELECT 1")
+		if err != nil {
+			dbt.Fatal(err)
+		}
+
+		err = rows.Close()
+		if err != nil {
+			dbt.Fatal(err)
+		}
+
+		if rows.Next() {
+			dbt.Fatal("Unexpected row after rows.Close()")
+		}
+
+		err = rows.Err()
+		if err != nil {
+			dbt.Fatal(err)
+		}
+	})
+}
+
+// dangling statements
+// http://code.google.com/p/go/issues/detail?id=3865
+func TestCloseStmtBeforeRows(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		stmt, err := dbt.db.Prepare("SELECT 1")
+		if err != nil {
+			dbt.Fatal(err)
+		}
+
+		rows, err := stmt.Query()
+		if err != nil {
+			stmt.Close()
+			dbt.Fatal(err)
+		}
+		defer rows.Close()
+
+		err = stmt.Close()
+		if err != nil {
+			dbt.Fatal(err)
+		}
+
+		if !rows.Next() {
+			dbt.Fatal("Getting row failed")
+		} else {
+			err = rows.Err()
+			if err != nil {
+				dbt.Fatal(err)
+			}
+
+			var out bool
+			err = rows.Scan(&out)
+			if err != nil {
+				dbt.Fatalf("Error on rows.Scan(): %s", err.Error())
+			}
+			if out != true {
+				dbt.Errorf("true != %t", out)
+			}
+		}
+	})
+}
+
+// It is valid to have multiple Rows for the same Stmt
+// http://code.google.com/p/go/issues/detail?id=3734
+func TestStmtMultiRows(t *testing.T) {
+	runTests(t, dsn, func(dbt *DBTest) {
+		stmt, err := dbt.db.Prepare("SELECT 1 UNION SELECT 0")
+		if err != nil {
+			dbt.Fatal(err)
+		}
+
+		rows1, err := stmt.Query()
+		if err != nil {
+			stmt.Close()
+			dbt.Fatal(err)
+		}
+		defer rows1.Close()
+
+		rows2, err := stmt.Query()
+		if err != nil {
+			stmt.Close()
+			dbt.Fatal(err)
+		}
+		defer rows2.Close()
+
+		var out bool
+
+		// 1
+		if !rows1.Next() {
+			dbt.Fatal("1st rows1.Next failed")
+		} else {
+			err = rows1.Err()
+			if err != nil {
+				dbt.Fatal(err)
+			}
+
+			err = rows1.Scan(&out)
+			if err != nil {
+				dbt.Fatalf("Error on rows.Scan(): %s", err.Error())
+			}
+			if out != true {
+				dbt.Errorf("true != %t", out)
+			}
+		}
+
+		if !rows2.Next() {
+			dbt.Fatal("1st rows2.Next failed")
+		} else {
+			err = rows2.Err()
+			if err != nil {
+				dbt.Fatal(err)
+			}
+
+			err = rows2.Scan(&out)
+			if err != nil {
+				dbt.Fatalf("Error on rows.Scan(): %s", err.Error())
+			}
+			if out != true {
+				dbt.Errorf("true != %t", out)
+			}
+		}
+
+		// 2
+		if !rows1.Next() {
+			dbt.Fatal("2nd rows1.Next failed")
+		} else {
+			err = rows1.Err()
+			if err != nil {
+				dbt.Fatal(err)
+			}
+
+			err = rows1.Scan(&out)
+			if err != nil {
+				dbt.Fatalf("Error on rows.Scan(): %s", err.Error())
+			}
+			if out != false {
+				dbt.Errorf("false != %t", out)
+			}
+
+			if rows1.Next() {
+				dbt.Fatal("Unexpected row on rows1")
+			}
+			err = rows1.Close()
+			if err != nil {
+				dbt.Fatal(err)
+			}
+		}
+
+		if !rows2.Next() {
+			dbt.Fatal("2nd rows2.Next failed")
+		} else {
+			err = rows2.Err()
+			if err != nil {
+				dbt.Fatal(err)
+			}
+
+			err = rows2.Scan(&out)
+			if err != nil {
+				dbt.Fatalf("Error on rows.Scan(): %s", err.Error())
+			}
+			if out != false {
+				dbt.Errorf("false != %t", out)
+			}
+
+			if rows2.Next() {
+				dbt.Fatal("Unexpected row on rows2")
+			}
+			err = rows2.Close()
+			if err != nil {
+				dbt.Fatal(err)
+			}
+		}
+	})
+}
+
+// Regression test for
+// * more than 32 NULL parameters (issue 209)
+// * more parameters than fit into the buffer (issue 201)
+func TestPreparedManyCols(t *testing.T) {
+	const numParams = defaultBufSize
+	runTests(t, dsn, func(dbt *DBTest) {
+		query := "SELECT ?" + strings.Repeat(",?", numParams-1)
+		stmt, err := dbt.db.Prepare(query)
+		if err != nil {
+			dbt.Fatal(err)
+		}
+		defer stmt.Close()
+		// create more parameters than fit into the buffer
+		// which will take nil-values
+		params := make([]interface{}, numParams)
+		rows, err := stmt.Query(params...)
+		if err != nil {
+			stmt.Close()
+			dbt.Fatal(err)
+		}
+		defer rows.Close()
+	})
+}
+
+func TestConcurrent(t *testing.T) {
+	if enabled, _ := readBool(os.Getenv("MYSQL_TEST_CONCURRENT")); !enabled {
+		t.Skip("MYSQL_TEST_CONCURRENT env var not set")
+	}
+
+	runTests(t, dsn, func(dbt *DBTest) {
+		var max int
+		err := dbt.db.QueryRow("SELECT @@max_connections").Scan(&max)
+		if err != nil {
+			dbt.Fatalf("%s", err.Error())
+		}
+		dbt.Logf("Testing up to %d concurrent connections \r\n", max)
+
+		var remaining, succeeded int32 = int32(max), 0
+
+		var wg sync.WaitGroup
+		wg.Add(max)
+
+		var fatalError string
+		var once sync.Once
+		fatalf := func(s string, vals ...interface{}) {
+			once.Do(func() {
+				fatalError = fmt.Sprintf(s, vals...)
+			})
+		}
+
+		for i := 0; i < max; i++ {
+			go func(id int) {
+				defer wg.Done()
+
+				tx, err := dbt.db.Begin()
+				atomic.AddInt32(&remaining, -1)
+
+				if err != nil {
+					if err.Error() != "Error 1040: Too many connections" {
+						fatalf("Error on Conn %d: %s", id, err.Error())
+					}
+					return
+				}
+
+				// keep the connection busy until all connections are open
+				for remaining > 0 {
+					if _, err = tx.Exec("DO 1"); err != nil {
+						fatalf("Error on Conn %d: %s", id, err.Error())
+						return
+					}
+				}
+
+				if err = tx.Commit(); err != nil {
+					fatalf("Error on Conn %d: %s", id, err.Error())
+					return
+				}
+
+				// everything went fine with this connection
+				atomic.AddInt32(&succeeded, 1)
+			}(i)
+		}
+
+		// wait until all conections are open
+		wg.Wait()
+
+		if fatalError != "" {
+			dbt.Fatal(fatalError)
+		}
+
+		dbt.Logf("Reached %d concurrent connections\r\n", succeeded)
+	})
+}
+
+// Tests custom dial functions
+func TestCustomDial(t *testing.T) {
+	if !available {
+		t.Skipf("MySQL-Server not running on %s", netAddr)
+	}
+
+	// our custom dial function which justs wraps net.Dial here
+	RegisterDial("mydial", func(addr string) (net.Conn, error) {
+		return net.Dial(prot, addr)
+	})
+
+	db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@mydial(%s)/%s?timeout=30s&strict=true", user, pass, addr, dbname))
+	if err != nil {
+		t.Fatalf("Error connecting: %s", err.Error())
+	}
+	defer db.Close()
+
+	if _, err = db.Exec("DO 1"); err != nil {
+		t.Fatalf("Connection failed: %s", err.Error())
+	}
+}

+ 129 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/errors.go

@@ -0,0 +1,129 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"database/sql/driver"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"os"
+)
+
+// Various errors the driver might return. Can change between driver versions.
+var (
+	ErrInvalidConn = errors.New("Invalid Connection")
+	ErrMalformPkt  = errors.New("Malformed Packet")
+	ErrNoTLS       = errors.New("TLS encryption requested but server does not support TLS")
+	ErrOldPassword = errors.New("This server only supports the insecure old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords")
+	ErrOldProtocol = errors.New("MySQL-Server does not support required Protocol 41+")
+	ErrPktSync     = errors.New("Commands out of sync. You can't run this command now")
+	ErrPktSyncMul  = errors.New("Commands out of sync. Did you run multiple statements at once?")
+	ErrPktTooLarge = errors.New("Packet for query is too large. You can change this value on the server by adjusting the 'max_allowed_packet' variable.")
+	ErrBusyBuffer  = errors.New("Busy buffer")
+)
+
+var errLog Logger = log.New(os.Stderr, "[MySQL] ", log.Ldate|log.Ltime|log.Lshortfile)
+
+// Logger is used to log critical error messages.
+type Logger interface {
+	Print(v ...interface{})
+}
+
+// SetLogger is used to set the logger for critical errors.
+// The initial logger is os.Stderr.
+func SetLogger(logger Logger) error {
+	if logger == nil {
+		return errors.New("logger is nil")
+	}
+	errLog = logger
+	return nil
+}
+
+// MySQLError is an error type which represents a single MySQL error
+type MySQLError struct {
+	Number  uint16
+	Message string
+}
+
+func (me *MySQLError) Error() string {
+	return fmt.Sprintf("Error %d: %s", me.Number, me.Message)
+}
+
+// MySQLWarnings is an error type which represents a group of one or more MySQL
+// warnings
+type MySQLWarnings []MySQLWarning
+
+func (mws MySQLWarnings) Error() string {
+	var msg string
+	for i, warning := range mws {
+		if i > 0 {
+			msg += "\r\n"
+		}
+		msg += fmt.Sprintf(
+			"%s %s: %s",
+			warning.Level,
+			warning.Code,
+			warning.Message,
+		)
+	}
+	return msg
+}
+
+// MySQLWarning is an error type which represents a single MySQL warning.
+// Warnings are returned in groups only. See MySQLWarnings
+type MySQLWarning struct {
+	Level   string
+	Code    string
+	Message string
+}
+
+func (mc *mysqlConn) getWarnings() (err error) {
+	rows, err := mc.Query("SHOW WARNINGS", nil)
+	if err != nil {
+		return
+	}
+
+	var warnings = MySQLWarnings{}
+	var values = make([]driver.Value, 3)
+
+	for {
+		err = rows.Next(values)
+		switch err {
+		case nil:
+			warning := MySQLWarning{}
+
+			if raw, ok := values[0].([]byte); ok {
+				warning.Level = string(raw)
+			} else {
+				warning.Level = fmt.Sprintf("%s", values[0])
+			}
+			if raw, ok := values[1].([]byte); ok {
+				warning.Code = string(raw)
+			} else {
+				warning.Code = fmt.Sprintf("%s", values[1])
+			}
+			if raw, ok := values[2].([]byte); ok {
+				warning.Message = string(raw)
+			} else {
+				warning.Message = fmt.Sprintf("%s", values[0])
+			}
+
+			warnings = append(warnings, warning)
+
+		case io.EOF:
+			return warnings
+
+		default:
+			rows.Close()
+			return
+		}
+	}
+}

+ 42 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/errors_test.go

@@ -0,0 +1,42 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"bytes"
+	"log"
+	"testing"
+)
+
+func TestErrorsSetLogger(t *testing.T) {
+	previous := errLog
+	defer func() {
+		errLog = previous
+	}()
+
+	// set up logger
+	const expected = "prefix: test\n"
+	buffer := bytes.NewBuffer(make([]byte, 0, 64))
+	logger := log.New(buffer, "prefix: ", 0)
+
+	// print
+	SetLogger(logger)
+	errLog.Print("test")
+
+	// check result
+	if actual := buffer.String(); actual != expected {
+		t.Errorf("expected %q, got %q", expected, actual)
+	}
+}
+
+func TestErrorsStrictIgnoreNotes(t *testing.T) {
+	runTests(t, dsn+"&sql_notes=false", func(dbt *DBTest) {
+		dbt.mustExec("DROP TABLE IF EXISTS does_not_exist")
+	})
+}

+ 162 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/infile.go

@@ -0,0 +1,162 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"strings"
+)
+
+var (
+	fileRegister   map[string]bool
+	readerRegister map[string]func() io.Reader
+)
+
+// RegisterLocalFile adds the given file to the file whitelist,
+// so that it can be used by "LOAD DATA LOCAL INFILE <filepath>".
+// Alternatively you can allow the use of all local files with
+// the DSN parameter 'allowAllFiles=true'
+//
+//  filePath := "/home/gopher/data.csv"
+//  mysql.RegisterLocalFile(filePath)
+//  err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo")
+//  if err != nil {
+//  ...
+//
+func RegisterLocalFile(filePath string) {
+	// lazy map init
+	if fileRegister == nil {
+		fileRegister = make(map[string]bool)
+	}
+
+	fileRegister[strings.Trim(filePath, `"`)] = true
+}
+
+// DeregisterLocalFile removes the given filepath from the whitelist.
+func DeregisterLocalFile(filePath string) {
+	delete(fileRegister, strings.Trim(filePath, `"`))
+}
+
+// RegisterReaderHandler registers a handler function which is used
+// to receive a io.Reader.
+// The Reader can be used by "LOAD DATA LOCAL INFILE Reader::<name>".
+// If the handler returns a io.ReadCloser Close() is called when the
+// request is finished.
+//
+//  mysql.RegisterReaderHandler("data", func() io.Reader {
+//  	var csvReader io.Reader // Some Reader that returns CSV data
+//  	... // Open Reader here
+//  	return csvReader
+//  })
+//  err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo")
+//  if err != nil {
+//  ...
+//
+func RegisterReaderHandler(name string, handler func() io.Reader) {
+	// lazy map init
+	if readerRegister == nil {
+		readerRegister = make(map[string]func() io.Reader)
+	}
+
+	readerRegister[name] = handler
+}
+
+// DeregisterReaderHandler removes the ReaderHandler function with
+// the given name from the registry.
+func DeregisterReaderHandler(name string) {
+	delete(readerRegister, name)
+}
+
+func deferredClose(err *error, closer io.Closer) {
+	closeErr := closer.Close()
+	if *err == nil {
+		*err = closeErr
+	}
+}
+
+func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
+	var rdr io.Reader
+	var data []byte
+
+	if strings.HasPrefix(name, "Reader::") { // io.Reader
+		name = name[8:]
+		if handler, inMap := readerRegister[name]; inMap {
+			rdr = handler()
+			if rdr != nil {
+				data = make([]byte, 4+mc.maxWriteSize)
+
+				if cl, ok := rdr.(io.Closer); ok {
+					defer deferredClose(&err, cl)
+				}
+			} else {
+				err = fmt.Errorf("Reader '%s' is <nil>", name)
+			}
+		} else {
+			err = fmt.Errorf("Reader '%s' is not registered", name)
+		}
+	} else { // File
+		name = strings.Trim(name, `"`)
+		if mc.cfg.allowAllFiles || fileRegister[name] {
+			var file *os.File
+			var fi os.FileInfo
+
+			if file, err = os.Open(name); err == nil {
+				defer deferredClose(&err, file)
+
+				// get file size
+				if fi, err = file.Stat(); err == nil {
+					rdr = file
+					if fileSize := int(fi.Size()); fileSize <= mc.maxWriteSize {
+						data = make([]byte, 4+fileSize)
+					} else if fileSize <= mc.maxPacketAllowed {
+						data = make([]byte, 4+mc.maxWriteSize)
+					} else {
+						err = fmt.Errorf("Local File '%s' too large: Size: %d, Max: %d", name, fileSize, mc.maxPacketAllowed)
+					}
+				}
+			}
+		} else {
+			err = fmt.Errorf("Local File '%s' is not registered. Use the DSN parameter 'allowAllFiles=true' to allow all files", name)
+		}
+	}
+
+	// send content packets
+	if err == nil {
+		var n int
+		for err == nil {
+			n, err = rdr.Read(data[4:])
+			if n > 0 {
+				if ioErr := mc.writePacket(data[:4+n]); ioErr != nil {
+					return ioErr
+				}
+			}
+		}
+		if err == io.EOF {
+			err = nil
+		}
+	}
+
+	// send empty packet (termination)
+	if data == nil {
+		data = make([]byte, 4)
+	}
+	if ioErr := mc.writePacket(data[:4]); ioErr != nil {
+		return ioErr
+	}
+
+	// read OK packet
+	if err == nil {
+		return mc.readResultOK()
+	} else {
+		mc.readPacket()
+	}
+	return err
+}

+ 1122 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/packets.go

@@ -0,0 +1,1122 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"bytes"
+	"crypto/tls"
+	"database/sql/driver"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"math"
+	"time"
+)
+
+// Packets documentation:
+// http://dev.mysql.com/doc/internals/en/client-server-protocol.html
+
+// Read packet to buffer 'data'
+func (mc *mysqlConn) readPacket() ([]byte, error) {
+	var payload []byte
+	for {
+		// Read packet header
+		data, err := mc.buf.readNext(4)
+		if err != nil {
+			errLog.Print(err)
+			mc.Close()
+			return nil, driver.ErrBadConn
+		}
+
+		// Packet Length [24 bit]
+		pktLen := int(uint32(data[0]) | uint32(data[1])<<8 | uint32(data[2])<<16)
+
+		if pktLen < 1 {
+			errLog.Print(ErrMalformPkt)
+			mc.Close()
+			return nil, driver.ErrBadConn
+		}
+
+		// Check Packet Sync [8 bit]
+		if data[3] != mc.sequence {
+			if data[3] > mc.sequence {
+				return nil, ErrPktSyncMul
+			} else {
+				return nil, ErrPktSync
+			}
+		}
+		mc.sequence++
+
+		// Read packet body [pktLen bytes]
+		data, err = mc.buf.readNext(pktLen)
+		if err != nil {
+			errLog.Print(err)
+			mc.Close()
+			return nil, driver.ErrBadConn
+		}
+
+		isLastPacket := (pktLen < maxPacketSize)
+
+		// Zero allocations for non-splitting packets
+		if isLastPacket && payload == nil {
+			return data, nil
+		}
+
+		payload = append(payload, data...)
+
+		if isLastPacket {
+			return payload, nil
+		}
+	}
+}
+
+// Write packet buffer 'data'
+func (mc *mysqlConn) writePacket(data []byte) error {
+	pktLen := len(data) - 4
+
+	if pktLen > mc.maxPacketAllowed {
+		return ErrPktTooLarge
+	}
+
+	for {
+		var size int
+		if pktLen >= maxPacketSize {
+			data[0] = 0xff
+			data[1] = 0xff
+			data[2] = 0xff
+			size = maxPacketSize
+		} else {
+			data[0] = byte(pktLen)
+			data[1] = byte(pktLen >> 8)
+			data[2] = byte(pktLen >> 16)
+			size = pktLen
+		}
+		data[3] = mc.sequence
+
+		// Write packet
+		n, err := mc.netConn.Write(data[:4+size])
+		if err == nil && n == 4+size {
+			mc.sequence++
+			if size != maxPacketSize {
+				return nil
+			}
+			pktLen -= size
+			data = data[size:]
+			continue
+		}
+
+		// Handle error
+		if err == nil { // n != len(data)
+			errLog.Print(ErrMalformPkt)
+		} else {
+			errLog.Print(err)
+		}
+		return driver.ErrBadConn
+	}
+}
+
+/******************************************************************************
+*                           Initialisation Process                            *
+******************************************************************************/
+
+// Handshake Initialization Packet
+// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
+func (mc *mysqlConn) readInitPacket() ([]byte, error) {
+	data, err := mc.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	if data[0] == iERR {
+		return nil, mc.handleErrorPacket(data)
+	}
+
+	// protocol version [1 byte]
+	if data[0] < minProtocolVersion {
+		return nil, fmt.Errorf(
+			"Unsupported MySQL Protocol Version %d. Protocol Version %d or higher is required",
+			data[0],
+			minProtocolVersion,
+		)
+	}
+
+	// server version [null terminated string]
+	// connection id [4 bytes]
+	pos := 1 + bytes.IndexByte(data[1:], 0x00) + 1 + 4
+
+	// first part of the password cipher [8 bytes]
+	cipher := data[pos : pos+8]
+
+	// (filler) always 0x00 [1 byte]
+	pos += 8 + 1
+
+	// capability flags (lower 2 bytes) [2 bytes]
+	mc.flags = clientFlag(binary.LittleEndian.Uint16(data[pos : pos+2]))
+	if mc.flags&clientProtocol41 == 0 {
+		return nil, ErrOldProtocol
+	}
+	if mc.flags&clientSSL == 0 && mc.cfg.tls != nil {
+		return nil, ErrNoTLS
+	}
+	pos += 2
+
+	if len(data) > pos {
+		// character set [1 byte]
+		// status flags [2 bytes]
+		// capability flags (upper 2 bytes) [2 bytes]
+		// length of auth-plugin-data [1 byte]
+		// reserved (all [00]) [10 bytes]
+		pos += 1 + 2 + 2 + 1 + 10
+
+		// second part of the password cipher [mininum 13 bytes],
+		// where len=MAX(13, length of auth-plugin-data - 8)
+		//
+		// The web documentation is ambiguous about the length. However,
+		// according to mysql-5.7/sql/auth/sql_authentication.cc line 538,
+		// the 13th byte is "\0 byte, terminating the second part of
+		// a scramble". So the second part of the password cipher is
+		// a NULL terminated string that's at least 13 bytes with the
+		// last byte being NULL.
+		//
+		// The official Python library uses the fixed length 12
+		// which seems to work but technically could have a hidden bug.
+		cipher = append(cipher, data[pos:pos+12]...)
+
+		// TODO: Verify string termination
+		// EOF if version (>= 5.5.7 and < 5.5.10) or (>= 5.6.0 and < 5.6.2)
+		// \NUL otherwise
+		//
+		//if data[len(data)-1] == 0 {
+		//	return
+		//}
+		//return ErrMalformPkt
+		return cipher, nil
+	}
+
+	// make a memory safe copy of the cipher slice
+	var b [8]byte
+	copy(b[:], cipher)
+	return b[:], nil
+}
+
+// Client Authentication Packet
+// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
+func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
+	// Adjust client flags based on server support
+	clientFlags := clientProtocol41 |
+		clientSecureConn |
+		clientLongPassword |
+		clientTransactions |
+		clientLocalFiles |
+		mc.flags&clientLongFlag
+
+	if mc.cfg.clientFoundRows {
+		clientFlags |= clientFoundRows
+	}
+
+	// To enable TLS / SSL
+	if mc.cfg.tls != nil {
+		clientFlags |= clientSSL
+	}
+
+	// User Password
+	scrambleBuff := scramblePassword(cipher, []byte(mc.cfg.passwd))
+
+	pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.user) + 1 + 1 + len(scrambleBuff)
+
+	// To specify a db name
+	if n := len(mc.cfg.dbname); n > 0 {
+		clientFlags |= clientConnectWithDB
+		pktLen += n + 1
+	}
+
+	// Calculate packet length and get buffer with that size
+	data := mc.buf.takeSmallBuffer(pktLen + 4)
+	if data == nil {
+		// can not take the buffer. Something must be wrong with the connection
+		errLog.Print(ErrBusyBuffer)
+		return driver.ErrBadConn
+	}
+
+	// ClientFlags [32 bit]
+	data[4] = byte(clientFlags)
+	data[5] = byte(clientFlags >> 8)
+	data[6] = byte(clientFlags >> 16)
+	data[7] = byte(clientFlags >> 24)
+
+	// MaxPacketSize [32 bit] (none)
+	data[8] = 0x00
+	data[9] = 0x00
+	data[10] = 0x00
+	data[11] = 0x00
+
+	// Charset [1 byte]
+	data[12] = mc.cfg.collation
+
+	// SSL Connection Request Packet
+	// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest
+	if mc.cfg.tls != nil {
+		// Send TLS / SSL request packet
+		if err := mc.writePacket(data[:(4+4+1+23)+4]); err != nil {
+			return err
+		}
+
+		// Switch to TLS
+		tlsConn := tls.Client(mc.netConn, mc.cfg.tls)
+		if err := tlsConn.Handshake(); err != nil {
+			return err
+		}
+		mc.netConn = tlsConn
+		mc.buf.rd = tlsConn
+	}
+
+	// Filler [23 bytes] (all 0x00)
+	pos := 13 + 23
+
+	// User [null terminated string]
+	if len(mc.cfg.user) > 0 {
+		pos += copy(data[pos:], mc.cfg.user)
+	}
+	data[pos] = 0x00
+	pos++
+
+	// ScrambleBuffer [length encoded integer]
+	data[pos] = byte(len(scrambleBuff))
+	pos += 1 + copy(data[pos+1:], scrambleBuff)
+
+	// Databasename [null terminated string]
+	if len(mc.cfg.dbname) > 0 {
+		pos += copy(data[pos:], mc.cfg.dbname)
+		data[pos] = 0x00
+	}
+
+	// Send Auth packet
+	return mc.writePacket(data)
+}
+
+//  Client old authentication packet
+// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse
+func (mc *mysqlConn) writeOldAuthPacket(cipher []byte) error {
+	// User password
+	scrambleBuff := scrambleOldPassword(cipher, []byte(mc.cfg.passwd))
+
+	// Calculate the packet lenght and add a tailing 0
+	pktLen := len(scrambleBuff) + 1
+	data := mc.buf.takeSmallBuffer(4 + pktLen)
+	if data == nil {
+		// can not take the buffer. Something must be wrong with the connection
+		errLog.Print(ErrBusyBuffer)
+		return driver.ErrBadConn
+	}
+
+	// Add the scrambled password [null terminated string]
+	copy(data[4:], scrambleBuff)
+	data[4+pktLen-1] = 0x00
+
+	return mc.writePacket(data)
+}
+
+/******************************************************************************
+*                             Command Packets                                 *
+******************************************************************************/
+
+func (mc *mysqlConn) writeCommandPacket(command byte) error {
+	// Reset Packet Sequence
+	mc.sequence = 0
+
+	data := mc.buf.takeSmallBuffer(4 + 1)
+	if data == nil {
+		// can not take the buffer. Something must be wrong with the connection
+		errLog.Print(ErrBusyBuffer)
+		return driver.ErrBadConn
+	}
+
+	// Add command byte
+	data[4] = command
+
+	// Send CMD packet
+	return mc.writePacket(data)
+}
+
+func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) error {
+	// Reset Packet Sequence
+	mc.sequence = 0
+
+	pktLen := 1 + len(arg)
+	data := mc.buf.takeBuffer(pktLen + 4)
+	if data == nil {
+		// can not take the buffer. Something must be wrong with the connection
+		errLog.Print(ErrBusyBuffer)
+		return driver.ErrBadConn
+	}
+
+	// Add command byte
+	data[4] = command
+
+	// Add arg
+	copy(data[5:], arg)
+
+	// Send CMD packet
+	return mc.writePacket(data)
+}
+
+func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {
+	// Reset Packet Sequence
+	mc.sequence = 0
+
+	data := mc.buf.takeSmallBuffer(4 + 1 + 4)
+	if data == nil {
+		// can not take the buffer. Something must be wrong with the connection
+		errLog.Print(ErrBusyBuffer)
+		return driver.ErrBadConn
+	}
+
+	// Add command byte
+	data[4] = command
+
+	// Add arg [32 bit]
+	data[5] = byte(arg)
+	data[6] = byte(arg >> 8)
+	data[7] = byte(arg >> 16)
+	data[8] = byte(arg >> 24)
+
+	// Send CMD packet
+	return mc.writePacket(data)
+}
+
+/******************************************************************************
+*                              Result Packets                                 *
+******************************************************************************/
+
+// Returns error if Packet is not an 'Result OK'-Packet
+func (mc *mysqlConn) readResultOK() error {
+	data, err := mc.readPacket()
+	if err == nil {
+		// packet indicator
+		switch data[0] {
+
+		case iOK:
+			return mc.handleOkPacket(data)
+
+		case iEOF:
+			// someone is using old_passwords
+			return ErrOldPassword
+
+		default: // Error otherwise
+			return mc.handleErrorPacket(data)
+		}
+	}
+	return err
+}
+
+// Result Set Header Packet
+// http://dev.mysql.com/doc/internals/en/com-query-response.html#packet-ProtocolText::Resultset
+func (mc *mysqlConn) readResultSetHeaderPacket() (int, error) {
+	data, err := mc.readPacket()
+	if err == nil {
+		switch data[0] {
+
+		case iOK:
+			return 0, mc.handleOkPacket(data)
+
+		case iERR:
+			return 0, mc.handleErrorPacket(data)
+
+		case iLocalInFile:
+			return 0, mc.handleInFileRequest(string(data[1:]))
+		}
+
+		// column count
+		num, _, n := readLengthEncodedInteger(data)
+		if n-len(data) == 0 {
+			return int(num), nil
+		}
+
+		return 0, ErrMalformPkt
+	}
+	return 0, err
+}
+
+// Error Packet
+// http://dev.mysql.com/doc/internals/en/generic-response-packets.html#packet-ERR_Packet
+func (mc *mysqlConn) handleErrorPacket(data []byte) error {
+	if data[0] != iERR {
+		return ErrMalformPkt
+	}
+
+	// 0xff [1 byte]
+
+	// Error Number [16 bit uint]
+	errno := binary.LittleEndian.Uint16(data[1:3])
+
+	pos := 3
+
+	// SQL State [optional: # + 5bytes string]
+	if data[3] == 0x23 {
+		//sqlstate := string(data[4 : 4+5])
+		pos = 9
+	}
+
+	// Error Message [string]
+	return &MySQLError{
+		Number:  errno,
+		Message: string(data[pos:]),
+	}
+}
+
+// Ok Packet
+// http://dev.mysql.com/doc/internals/en/generic-response-packets.html#packet-OK_Packet
+func (mc *mysqlConn) handleOkPacket(data []byte) error {
+	var n, m int
+
+	// 0x00 [1 byte]
+
+	// Affected rows [Length Coded Binary]
+	mc.affectedRows, _, n = readLengthEncodedInteger(data[1:])
+
+	// Insert id [Length Coded Binary]
+	mc.insertId, _, m = readLengthEncodedInteger(data[1+n:])
+
+	// server_status [2 bytes]
+
+	// warning count [2 bytes]
+	if !mc.strict {
+		return nil
+	} else {
+		pos := 1 + n + m + 2
+		if binary.LittleEndian.Uint16(data[pos:pos+2]) > 0 {
+			return mc.getWarnings()
+		}
+		return nil
+	}
+}
+
+// Read Packets as Field Packets until EOF-Packet or an Error appears
+// http://dev.mysql.com/doc/internals/en/com-query-response.html#packet-Protocol::ColumnDefinition41
+func (mc *mysqlConn) readColumns(count int) ([]mysqlField, error) {
+	columns := make([]mysqlField, count)
+
+	for i := 0; ; i++ {
+		data, err := mc.readPacket()
+		if err != nil {
+			return nil, err
+		}
+
+		// EOF Packet
+		if data[0] == iEOF && (len(data) == 5 || len(data) == 1) {
+			if i == count {
+				return columns, nil
+			}
+			return nil, fmt.Errorf("ColumnsCount mismatch n:%d len:%d", count, len(columns))
+		}
+
+		// Catalog
+		pos, err := skipLengthEncodedString(data)
+		if err != nil {
+			return nil, err
+		}
+
+		// Database [len coded string]
+		n, err := skipLengthEncodedString(data[pos:])
+		if err != nil {
+			return nil, err
+		}
+		pos += n
+
+		// Table [len coded string]
+		n, err = skipLengthEncodedString(data[pos:])
+		if err != nil {
+			return nil, err
+		}
+		pos += n
+
+		// Original table [len coded string]
+		n, err = skipLengthEncodedString(data[pos:])
+		if err != nil {
+			return nil, err
+		}
+		pos += n
+
+		// Name [len coded string]
+		name, _, n, err := readLengthEncodedString(data[pos:])
+		if err != nil {
+			return nil, err
+		}
+		columns[i].name = string(name)
+		pos += n
+
+		// Original name [len coded string]
+		n, err = skipLengthEncodedString(data[pos:])
+		if err != nil {
+			return nil, err
+		}
+
+		// Filler [uint8]
+		// Charset [charset, collation uint8]
+		// Length [uint32]
+		pos += n + 1 + 2 + 4
+
+		// Field type [uint8]
+		columns[i].fieldType = data[pos]
+		pos++
+
+		// Flags [uint16]
+		columns[i].flags = fieldFlag(binary.LittleEndian.Uint16(data[pos : pos+2]))
+		pos += 2
+
+		// Decimals [uint8]
+		columns[i].decimals = data[pos]
+		//pos++
+
+		// Default value [len coded binary]
+		//if pos < len(data) {
+		//	defaultVal, _, err = bytesToLengthCodedBinary(data[pos:])
+		//}
+	}
+}
+
+// Read Packets as Field Packets until EOF-Packet or an Error appears
+// http://dev.mysql.com/doc/internals/en/com-query-response.html#packet-ProtocolText::ResultsetRow
+func (rows *textRows) readRow(dest []driver.Value) error {
+	mc := rows.mc
+
+	data, err := mc.readPacket()
+	if err != nil {
+		return err
+	}
+
+	// EOF Packet
+	if data[0] == iEOF && len(data) == 5 {
+		return io.EOF
+	}
+
+	// RowSet Packet
+	var n int
+	var isNull bool
+	pos := 0
+
+	for i := range dest {
+		// Read bytes and convert to string
+		dest[i], isNull, n, err = readLengthEncodedString(data[pos:])
+		pos += n
+		if err == nil {
+			if !isNull {
+				if !mc.parseTime {
+					continue
+				} else {
+					switch rows.columns[i].fieldType {
+					case fieldTypeTimestamp, fieldTypeDateTime,
+						fieldTypeDate, fieldTypeNewDate:
+						dest[i], err = parseDateTime(
+							string(dest[i].([]byte)),
+							mc.cfg.loc,
+						)
+						if err == nil {
+							continue
+						}
+					default:
+						continue
+					}
+				}
+
+			} else {
+				dest[i] = nil
+				continue
+			}
+		}
+		return err // err != nil
+	}
+
+	return nil
+}
+
+// Reads Packets until EOF-Packet or an Error appears. Returns count of Packets read
+func (mc *mysqlConn) readUntilEOF() error {
+	for {
+		data, err := mc.readPacket()
+
+		// No Err and no EOF Packet
+		if err == nil && data[0] != iEOF {
+			continue
+		}
+		return err // Err or EOF
+	}
+}
+
+/******************************************************************************
+*                           Prepared Statements                               *
+******************************************************************************/
+
+// Prepare Result Packets
+// http://dev.mysql.com/doc/internals/en/com-stmt-prepare-response.html
+func (stmt *mysqlStmt) readPrepareResultPacket() (uint16, error) {
+	data, err := stmt.mc.readPacket()
+	if err == nil {
+		// packet indicator [1 byte]
+		if data[0] != iOK {
+			return 0, stmt.mc.handleErrorPacket(data)
+		}
+
+		// statement id [4 bytes]
+		stmt.id = binary.LittleEndian.Uint32(data[1:5])
+
+		// Column count [16 bit uint]
+		columnCount := binary.LittleEndian.Uint16(data[5:7])
+
+		// Param count [16 bit uint]
+		stmt.paramCount = int(binary.LittleEndian.Uint16(data[7:9]))
+
+		// Reserved [8 bit]
+
+		// Warning count [16 bit uint]
+		if !stmt.mc.strict {
+			return columnCount, nil
+		} else {
+			// Check for warnings count > 0, only available in MySQL > 4.1
+			if len(data) >= 12 && binary.LittleEndian.Uint16(data[10:12]) > 0 {
+				return columnCount, stmt.mc.getWarnings()
+			}
+			return columnCount, nil
+		}
+	}
+	return 0, err
+}
+
+// http://dev.mysql.com/doc/internals/en/com-stmt-send-long-data.html
+func (stmt *mysqlStmt) writeCommandLongData(paramID int, arg []byte) error {
+	maxLen := stmt.mc.maxPacketAllowed - 1
+	pktLen := maxLen
+
+	// After the header (bytes 0-3) follows before the data:
+	// 1 byte command
+	// 4 bytes stmtID
+	// 2 bytes paramID
+	const dataOffset = 1 + 4 + 2
+
+	// Can not use the write buffer since
+	// a) the buffer is too small
+	// b) it is in use
+	data := make([]byte, 4+1+4+2+len(arg))
+
+	copy(data[4+dataOffset:], arg)
+
+	for argLen := len(arg); argLen > 0; argLen -= pktLen - dataOffset {
+		if dataOffset+argLen < maxLen {
+			pktLen = dataOffset + argLen
+		}
+
+		stmt.mc.sequence = 0
+		// Add command byte [1 byte]
+		data[4] = comStmtSendLongData
+
+		// Add stmtID [32 bit]
+		data[5] = byte(stmt.id)
+		data[6] = byte(stmt.id >> 8)
+		data[7] = byte(stmt.id >> 16)
+		data[8] = byte(stmt.id >> 24)
+
+		// Add paramID [16 bit]
+		data[9] = byte(paramID)
+		data[10] = byte(paramID >> 8)
+
+		// Send CMD packet
+		err := stmt.mc.writePacket(data[:4+pktLen])
+		if err == nil {
+			data = data[pktLen-dataOffset:]
+			continue
+		}
+		return err
+
+	}
+
+	// Reset Packet Sequence
+	stmt.mc.sequence = 0
+	return nil
+}
+
+// Execute Prepared Statement
+// http://dev.mysql.com/doc/internals/en/com-stmt-execute.html
+func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
+	if len(args) != stmt.paramCount {
+		return fmt.Errorf(
+			"Arguments count mismatch (Got: %d Has: %d)",
+			len(args),
+			stmt.paramCount,
+		)
+	}
+
+	const minPktLen = 4 + 1 + 4 + 1 + 4
+	mc := stmt.mc
+
+	// Reset packet-sequence
+	mc.sequence = 0
+
+	var data []byte
+
+	if len(args) == 0 {
+		data = mc.buf.takeBuffer(minPktLen)
+	} else {
+		data = mc.buf.takeCompleteBuffer()
+	}
+	if data == nil {
+		// can not take the buffer. Something must be wrong with the connection
+		errLog.Print(ErrBusyBuffer)
+		return driver.ErrBadConn
+	}
+
+	// command [1 byte]
+	data[4] = comStmtExecute
+
+	// statement_id [4 bytes]
+	data[5] = byte(stmt.id)
+	data[6] = byte(stmt.id >> 8)
+	data[7] = byte(stmt.id >> 16)
+	data[8] = byte(stmt.id >> 24)
+
+	// flags (0: CURSOR_TYPE_NO_CURSOR) [1 byte]
+	data[9] = 0x00
+
+	// iteration_count (uint32(1)) [4 bytes]
+	data[10] = 0x01
+	data[11] = 0x00
+	data[12] = 0x00
+	data[13] = 0x00
+
+	if len(args) > 0 {
+		pos := minPktLen
+
+		var nullMask []byte
+		if maskLen, typesLen := (len(args)+7)/8, 1+2*len(args); pos+maskLen+typesLen >= len(data) {
+			// buffer has to be extended but we don't know by how much so
+			// we depend on append after all data with known sizes fit.
+			// We stop at that because we deal with a lot of columns here
+			// which makes the required allocation size hard to guess.
+			tmp := make([]byte, pos+maskLen+typesLen)
+			copy(tmp[:pos], data[:pos])
+			data = tmp
+			nullMask = data[pos : pos+maskLen]
+			pos += maskLen
+		} else {
+			nullMask = data[pos : pos+maskLen]
+			for i := 0; i < maskLen; i++ {
+				nullMask[i] = 0
+			}
+			pos += maskLen
+		}
+
+		// newParameterBoundFlag 1 [1 byte]
+		data[pos] = 0x01
+		pos++
+
+		// type of each parameter [len(args)*2 bytes]
+		paramTypes := data[pos:]
+		pos += len(args) * 2
+
+		// value of each parameter [n bytes]
+		paramValues := data[pos:pos]
+		valuesCap := cap(paramValues)
+
+		for i, arg := range args {
+			// build NULL-bitmap
+			if arg == nil {
+				nullMask[i/8] |= 1 << (uint(i) & 7)
+				paramTypes[i+i] = fieldTypeNULL
+				paramTypes[i+i+1] = 0x00
+				continue
+			}
+
+			// cache types and values
+			switch v := arg.(type) {
+			case int64:
+				paramTypes[i+i] = fieldTypeLongLong
+				paramTypes[i+i+1] = 0x00
+
+				if cap(paramValues)-len(paramValues)-8 >= 0 {
+					paramValues = paramValues[:len(paramValues)+8]
+					binary.LittleEndian.PutUint64(
+						paramValues[len(paramValues)-8:],
+						uint64(v),
+					)
+				} else {
+					paramValues = append(paramValues,
+						uint64ToBytes(uint64(v))...,
+					)
+				}
+
+			case float64:
+				paramTypes[i+i] = fieldTypeDouble
+				paramTypes[i+i+1] = 0x00
+
+				if cap(paramValues)-len(paramValues)-8 >= 0 {
+					paramValues = paramValues[:len(paramValues)+8]
+					binary.LittleEndian.PutUint64(
+						paramValues[len(paramValues)-8:],
+						math.Float64bits(v),
+					)
+				} else {
+					paramValues = append(paramValues,
+						uint64ToBytes(math.Float64bits(v))...,
+					)
+				}
+
+			case bool:
+				paramTypes[i+i] = fieldTypeTiny
+				paramTypes[i+i+1] = 0x00
+
+				if v {
+					paramValues = append(paramValues, 0x01)
+				} else {
+					paramValues = append(paramValues, 0x00)
+				}
+
+			case []byte:
+				// Common case (non-nil value) first
+				if v != nil {
+					paramTypes[i+i] = fieldTypeString
+					paramTypes[i+i+1] = 0x00
+
+					if len(v) < mc.maxPacketAllowed-pos-len(paramValues)-(len(args)-(i+1))*64 {
+						paramValues = appendLengthEncodedInteger(paramValues,
+							uint64(len(v)),
+						)
+						paramValues = append(paramValues, v...)
+					} else {
+						if err := stmt.writeCommandLongData(i, v); err != nil {
+							return err
+						}
+					}
+					continue
+				}
+
+				// Handle []byte(nil) as a NULL value
+				nullMask[i/8] |= 1 << (uint(i) & 7)
+				paramTypes[i+i] = fieldTypeNULL
+				paramTypes[i+i+1] = 0x00
+
+			case string:
+				paramTypes[i+i] = fieldTypeString
+				paramTypes[i+i+1] = 0x00
+
+				if len(v) < mc.maxPacketAllowed-pos-len(paramValues)-(len(args)-(i+1))*64 {
+					paramValues = appendLengthEncodedInteger(paramValues,
+						uint64(len(v)),
+					)
+					paramValues = append(paramValues, v...)
+				} else {
+					if err := stmt.writeCommandLongData(i, []byte(v)); err != nil {
+						return err
+					}
+				}
+
+			case time.Time:
+				paramTypes[i+i] = fieldTypeString
+				paramTypes[i+i+1] = 0x00
+
+				var val []byte
+				if v.IsZero() {
+					val = []byte("0000-00-00")
+				} else {
+					val = []byte(v.In(mc.cfg.loc).Format(timeFormat))
+				}
+
+				paramValues = appendLengthEncodedInteger(paramValues,
+					uint64(len(val)),
+				)
+				paramValues = append(paramValues, val...)
+
+			default:
+				return fmt.Errorf("Can't convert type: %T", arg)
+			}
+		}
+
+		// Check if param values exceeded the available buffer
+		// In that case we must build the data packet with the new values buffer
+		if valuesCap != cap(paramValues) {
+			data = append(data[:pos], paramValues...)
+			mc.buf.buf = data
+		}
+
+		pos += len(paramValues)
+		data = data[:pos]
+	}
+
+	return mc.writePacket(data)
+}
+
+// http://dev.mysql.com/doc/internals/en/binary-protocol-resultset-row.html
+func (rows *binaryRows) readRow(dest []driver.Value) error {
+	data, err := rows.mc.readPacket()
+	if err != nil {
+		return err
+	}
+
+	// packet indicator [1 byte]
+	if data[0] != iOK {
+		// EOF Packet
+		if data[0] == iEOF && len(data) == 5 {
+			return io.EOF
+		}
+
+		// Error otherwise
+		return rows.mc.handleErrorPacket(data)
+	}
+
+	// NULL-bitmap,  [(column-count + 7 + 2) / 8 bytes]
+	pos := 1 + (len(dest)+7+2)>>3
+	nullMask := data[1:pos]
+
+	for i := range dest {
+		// Field is NULL
+		// (byte >> bit-pos) % 2 == 1
+		if ((nullMask[(i+2)>>3] >> uint((i+2)&7)) & 1) == 1 {
+			dest[i] = nil
+			continue
+		}
+
+		// Convert to byte-coded string
+		switch rows.columns[i].fieldType {
+		case fieldTypeNULL:
+			dest[i] = nil
+			continue
+
+		// Numeric Types
+		case fieldTypeTiny:
+			if rows.columns[i].flags&flagUnsigned != 0 {
+				dest[i] = int64(data[pos])
+			} else {
+				dest[i] = int64(int8(data[pos]))
+			}
+			pos++
+			continue
+
+		case fieldTypeShort, fieldTypeYear:
+			if rows.columns[i].flags&flagUnsigned != 0 {
+				dest[i] = int64(binary.LittleEndian.Uint16(data[pos : pos+2]))
+			} else {
+				dest[i] = int64(int16(binary.LittleEndian.Uint16(data[pos : pos+2])))
+			}
+			pos += 2
+			continue
+
+		case fieldTypeInt24, fieldTypeLong:
+			if rows.columns[i].flags&flagUnsigned != 0 {
+				dest[i] = int64(binary.LittleEndian.Uint32(data[pos : pos+4]))
+			} else {
+				dest[i] = int64(int32(binary.LittleEndian.Uint32(data[pos : pos+4])))
+			}
+			pos += 4
+			continue
+
+		case fieldTypeLongLong:
+			if rows.columns[i].flags&flagUnsigned != 0 {
+				val := binary.LittleEndian.Uint64(data[pos : pos+8])
+				if val > math.MaxInt64 {
+					dest[i] = uint64ToString(val)
+				} else {
+					dest[i] = int64(val)
+				}
+			} else {
+				dest[i] = int64(binary.LittleEndian.Uint64(data[pos : pos+8]))
+			}
+			pos += 8
+			continue
+
+		case fieldTypeFloat:
+			dest[i] = float64(math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4])))
+			pos += 4
+			continue
+
+		case fieldTypeDouble:
+			dest[i] = math.Float64frombits(binary.LittleEndian.Uint64(data[pos : pos+8]))
+			pos += 8
+			continue
+
+		// Length coded Binary Strings
+		case fieldTypeDecimal, fieldTypeNewDecimal, fieldTypeVarChar,
+			fieldTypeBit, fieldTypeEnum, fieldTypeSet, fieldTypeTinyBLOB,
+			fieldTypeMediumBLOB, fieldTypeLongBLOB, fieldTypeBLOB,
+			fieldTypeVarString, fieldTypeString, fieldTypeGeometry:
+			var isNull bool
+			var n int
+			dest[i], isNull, n, err = readLengthEncodedString(data[pos:])
+			pos += n
+			if err == nil {
+				if !isNull {
+					continue
+				} else {
+					dest[i] = nil
+					continue
+				}
+			}
+			return err
+
+		case
+			fieldTypeDate, fieldTypeNewDate, // Date YYYY-MM-DD
+			fieldTypeTime,                         // Time [-][H]HH:MM:SS[.fractal]
+			fieldTypeTimestamp, fieldTypeDateTime: // Timestamp YYYY-MM-DD HH:MM:SS[.fractal]
+
+			num, isNull, n := readLengthEncodedInteger(data[pos:])
+			pos += n
+
+			switch {
+			case isNull:
+				dest[i] = nil
+				continue
+			case rows.columns[i].fieldType == fieldTypeTime:
+				// database/sql does not support an equivalent to TIME, return a string
+				var dstlen uint8
+				switch decimals := rows.columns[i].decimals; decimals {
+				case 0x00, 0x1f:
+					dstlen = 8
+				case 1, 2, 3, 4, 5, 6:
+					dstlen = 8 + 1 + decimals
+				default:
+					return fmt.Errorf(
+						"MySQL protocol error, illegal decimals value %d",
+						rows.columns[i].decimals,
+					)
+				}
+				dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, true)
+			case rows.mc.parseTime:
+				dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.loc)
+			default:
+				var dstlen uint8
+				if rows.columns[i].fieldType == fieldTypeDate {
+					dstlen = 10
+				} else {
+					switch decimals := rows.columns[i].decimals; decimals {
+					case 0x00, 0x1f:
+						dstlen = 19
+					case 1, 2, 3, 4, 5, 6:
+						dstlen = 19 + 1 + decimals
+					default:
+						return fmt.Errorf(
+							"MySQL protocol error, illegal decimals value %d",
+							rows.columns[i].decimals,
+						)
+					}
+				}
+				dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, false)
+			}
+
+			if err == nil {
+				pos += int(num)
+				continue
+			} else {
+				return err
+			}
+
+		// Please report if this happens!
+		default:
+			return fmt.Errorf("Unknown FieldType %d", rows.columns[i].fieldType)
+		}
+	}
+
+	return nil
+}

+ 22 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/result.go

@@ -0,0 +1,22 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+type mysqlResult struct {
+	affectedRows int64
+	insertId     int64
+}
+
+func (res *mysqlResult) LastInsertId() (int64, error) {
+	return res.insertId, nil
+}
+
+func (res *mysqlResult) RowsAffected() (int64, error) {
+	return res.affectedRows, nil
+}

+ 101 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/rows.go

@@ -0,0 +1,101 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"database/sql/driver"
+	"io"
+)
+
+type mysqlField struct {
+	name      string
+	flags     fieldFlag
+	fieldType byte
+	decimals  byte
+}
+
+type mysqlRows struct {
+	mc      *mysqlConn
+	columns []mysqlField
+}
+
+type binaryRows struct {
+	mysqlRows
+}
+
+type textRows struct {
+	mysqlRows
+}
+
+type emptyRows struct{}
+
+func (rows *mysqlRows) Columns() []string {
+	columns := make([]string, len(rows.columns))
+	for i := range columns {
+		columns[i] = rows.columns[i].name
+	}
+	return columns
+}
+
+func (rows *mysqlRows) Close() error {
+	mc := rows.mc
+	if mc == nil {
+		return nil
+	}
+	if mc.netConn == nil {
+		return ErrInvalidConn
+	}
+
+	// Remove unread packets from stream
+	err := mc.readUntilEOF()
+	rows.mc = nil
+	return err
+}
+
+func (rows *binaryRows) Next(dest []driver.Value) error {
+	if mc := rows.mc; mc != nil {
+		if mc.netConn == nil {
+			return ErrInvalidConn
+		}
+
+		// Fetch next row from stream
+		if err := rows.readRow(dest); err != io.EOF {
+			return err
+		}
+		rows.mc = nil
+	}
+	return io.EOF
+}
+
+func (rows *textRows) Next(dest []driver.Value) error {
+	if mc := rows.mc; mc != nil {
+		if mc.netConn == nil {
+			return ErrInvalidConn
+		}
+
+		// Fetch next row from stream
+		if err := rows.readRow(dest); err != io.EOF {
+			return err
+		}
+		rows.mc = nil
+	}
+	return io.EOF
+}
+
+func (rows emptyRows) Columns() []string {
+	return nil
+}
+
+func (rows emptyRows) Close() error {
+	return nil
+}
+
+func (rows emptyRows) Next(dest []driver.Value) error {
+	return io.EOF
+}

+ 112 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/statement.go

@@ -0,0 +1,112 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"database/sql/driver"
+)
+
+type mysqlStmt struct {
+	mc         *mysqlConn
+	id         uint32
+	paramCount int
+	columns    []mysqlField // cached from the first query
+}
+
+func (stmt *mysqlStmt) Close() error {
+	if stmt.mc == nil || stmt.mc.netConn == nil {
+		errLog.Print(ErrInvalidConn)
+		return driver.ErrBadConn
+	}
+
+	err := stmt.mc.writeCommandPacketUint32(comStmtClose, stmt.id)
+	stmt.mc = nil
+	return err
+}
+
+func (stmt *mysqlStmt) NumInput() int {
+	return stmt.paramCount
+}
+
+func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
+	if stmt.mc.netConn == nil {
+		errLog.Print(ErrInvalidConn)
+		return nil, driver.ErrBadConn
+	}
+	// Send command
+	err := stmt.writeExecutePacket(args)
+	if err != nil {
+		return nil, err
+	}
+
+	mc := stmt.mc
+
+	mc.affectedRows = 0
+	mc.insertId = 0
+
+	// Read Result
+	resLen, err := mc.readResultSetHeaderPacket()
+	if err == nil {
+		if resLen > 0 {
+			// Columns
+			err = mc.readUntilEOF()
+			if err != nil {
+				return nil, err
+			}
+
+			// Rows
+			err = mc.readUntilEOF()
+		}
+		if err == nil {
+			return &mysqlResult{
+				affectedRows: int64(mc.affectedRows),
+				insertId:     int64(mc.insertId),
+			}, nil
+		}
+	}
+
+	return nil, err
+}
+
+func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
+	if stmt.mc.netConn == nil {
+		errLog.Print(ErrInvalidConn)
+		return nil, driver.ErrBadConn
+	}
+	// Send command
+	err := stmt.writeExecutePacket(args)
+	if err != nil {
+		return nil, err
+	}
+
+	mc := stmt.mc
+
+	// Read Result
+	resLen, err := mc.readResultSetHeaderPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	rows := new(binaryRows)
+	rows.mc = mc
+
+	if resLen > 0 {
+		// Columns
+		// If not cached, read them and cache them
+		if stmt.columns == nil {
+			rows.columns, err = mc.readColumns(resLen)
+			stmt.columns = rows.columns
+		} else {
+			rows.columns = stmt.columns
+			err = mc.readUntilEOF()
+		}
+	}
+
+	return rows, err
+}

+ 31 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/transaction.go

@@ -0,0 +1,31 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+type mysqlTx struct {
+	mc *mysqlConn
+}
+
+func (tx *mysqlTx) Commit() (err error) {
+	if tx.mc == nil || tx.mc.netConn == nil {
+		return ErrInvalidConn
+	}
+	err = tx.mc.exec("COMMIT")
+	tx.mc = nil
+	return
+}
+
+func (tx *mysqlTx) Rollback() (err error) {
+	if tx.mc == nil || tx.mc.netConn == nil {
+		return ErrInvalidConn
+	}
+	err = tx.mc.exec("ROLLBACK")
+	tx.mc = nil
+	return
+}

+ 785 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/utils.go

@@ -0,0 +1,785 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"crypto/sha1"
+	"crypto/tls"
+	"database/sql/driver"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"net/url"
+	"strings"
+	"time"
+)
+
+var (
+	tlsConfigRegister map[string]*tls.Config // Register for custom tls.Configs
+
+	errInvalidDSNUnescaped = errors.New("Invalid DSN: Did you forget to escape a param value?")
+	errInvalidDSNAddr      = errors.New("Invalid DSN: Network Address not terminated (missing closing brace)")
+	errInvalidDSNNoSlash   = errors.New("Invalid DSN: Missing the slash separating the database name")
+)
+
+func init() {
+	tlsConfigRegister = make(map[string]*tls.Config)
+}
+
+// RegisterTLSConfig registers a custom tls.Config to be used with sql.Open.
+// Use the key as a value in the DSN where tls=value.
+//
+//  rootCertPool := x509.NewCertPool()
+//  pem, err := ioutil.ReadFile("/path/ca-cert.pem")
+//  if err != nil {
+//      log.Fatal(err)
+//  }
+//  if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
+//      log.Fatal("Failed to append PEM.")
+//  }
+//  clientCert := make([]tls.Certificate, 0, 1)
+//  certs, err := tls.LoadX509KeyPair("/path/client-cert.pem", "/path/client-key.pem")
+//  if err != nil {
+//      log.Fatal(err)
+//  }
+//  clientCert = append(clientCert, certs)
+//  mysql.RegisterTLSConfig("custom", &tls.Config{
+//      RootCAs: rootCertPool,
+//      Certificates: clientCert,
+//  })
+//  db, err := sql.Open("mysql", "user@tcp(localhost:3306)/test?tls=custom")
+//
+func RegisterTLSConfig(key string, config *tls.Config) error {
+	if _, isBool := readBool(key); isBool || strings.ToLower(key) == "skip-verify" {
+		return fmt.Errorf("Key '%s' is reserved", key)
+	}
+
+	tlsConfigRegister[key] = config
+	return nil
+}
+
+// DeregisterTLSConfig removes the tls.Config associated with key.
+func DeregisterTLSConfig(key string) {
+	delete(tlsConfigRegister, key)
+}
+
+// parseDSN parses the DSN string to a config
+func parseDSN(dsn string) (cfg *config, err error) {
+	// New config with some default values
+	cfg = &config{
+		loc:       time.UTC,
+		collation: defaultCollation,
+	}
+
+	// TODO: use strings.IndexByte when we can depend on Go 1.2
+
+	// [user[:password]@][net[(addr)]]/dbname[?param1=value1&paramN=valueN]
+	// Find the last '/' (since the password or the net addr might contain a '/')
+	foundSlash := false
+	for i := len(dsn) - 1; i >= 0; i-- {
+		if dsn[i] == '/' {
+			foundSlash = true
+			var j, k int
+
+			// left part is empty if i <= 0
+			if i > 0 {
+				// [username[:password]@][protocol[(address)]]
+				// Find the last '@' in dsn[:i]
+				for j = i; j >= 0; j-- {
+					if dsn[j] == '@' {
+						// username[:password]
+						// Find the first ':' in dsn[:j]
+						for k = 0; k < j; k++ {
+							if dsn[k] == ':' {
+								cfg.passwd = dsn[k+1 : j]
+								break
+							}
+						}
+						cfg.user = dsn[:k]
+
+						break
+					}
+				}
+
+				// [protocol[(address)]]
+				// Find the first '(' in dsn[j+1:i]
+				for k = j + 1; k < i; k++ {
+					if dsn[k] == '(' {
+						// dsn[i-1] must be == ')' if an address is specified
+						if dsn[i-1] != ')' {
+							if strings.ContainsRune(dsn[k+1:i], ')') {
+								return nil, errInvalidDSNUnescaped
+							}
+							return nil, errInvalidDSNAddr
+						}
+						cfg.addr = dsn[k+1 : i-1]
+						break
+					}
+				}
+				cfg.net = dsn[j+1 : k]
+			}
+
+			// dbname[?param1=value1&...&paramN=valueN]
+			// Find the first '?' in dsn[i+1:]
+			for j = i + 1; j < len(dsn); j++ {
+				if dsn[j] == '?' {
+					if err = parseDSNParams(cfg, dsn[j+1:]); err != nil {
+						return
+					}
+					break
+				}
+			}
+			cfg.dbname = dsn[i+1 : j]
+
+			break
+		}
+	}
+
+	if !foundSlash && len(dsn) > 0 {
+		return nil, errInvalidDSNNoSlash
+	}
+
+	// Set default network if empty
+	if cfg.net == "" {
+		cfg.net = "tcp"
+	}
+
+	// Set default address if empty
+	if cfg.addr == "" {
+		switch cfg.net {
+		case "tcp":
+			cfg.addr = "127.0.0.1:3306"
+		case "unix":
+			cfg.addr = "/tmp/mysql.sock"
+		default:
+			return nil, errors.New("Default addr for network '" + cfg.net + "' unknown")
+		}
+
+	}
+
+	return
+}
+
+// parseDSNParams parses the DSN "query string"
+// Values must be url.QueryEscape'ed
+func parseDSNParams(cfg *config, params string) (err error) {
+	for _, v := range strings.Split(params, "&") {
+		param := strings.SplitN(v, "=", 2)
+		if len(param) != 2 {
+			continue
+		}
+
+		// cfg params
+		switch value := param[1]; param[0] {
+
+		// Disable INFILE whitelist / enable all files
+		case "allowAllFiles":
+			var isBool bool
+			cfg.allowAllFiles, isBool = readBool(value)
+			if !isBool {
+				return fmt.Errorf("Invalid Bool value: %s", value)
+			}
+
+		// Use old authentication mode (pre MySQL 4.1)
+		case "allowOldPasswords":
+			var isBool bool
+			cfg.allowOldPasswords, isBool = readBool(value)
+			if !isBool {
+				return fmt.Errorf("Invalid Bool value: %s", value)
+			}
+
+		// Switch "rowsAffected" mode
+		case "clientFoundRows":
+			var isBool bool
+			cfg.clientFoundRows, isBool = readBool(value)
+			if !isBool {
+				return fmt.Errorf("Invalid Bool value: %s", value)
+			}
+
+		// Collation
+		case "collation":
+			collation, ok := collations[value]
+			if !ok {
+				// Note possibility for false negatives:
+				// could be triggered  although the collation is valid if the
+				// collations map does not contain entries the server supports.
+				err = errors.New("unknown collation")
+				return
+			}
+			cfg.collation = collation
+			break
+
+		// Time Location
+		case "loc":
+			if value, err = url.QueryUnescape(value); err != nil {
+				return
+			}
+			cfg.loc, err = time.LoadLocation(value)
+			if err != nil {
+				return
+			}
+
+		// Dial Timeout
+		case "timeout":
+			cfg.timeout, err = time.ParseDuration(value)
+			if err != nil {
+				return
+			}
+
+		// TLS-Encryption
+		case "tls":
+			boolValue, isBool := readBool(value)
+			if isBool {
+				if boolValue {
+					cfg.tls = &tls.Config{}
+				}
+			} else {
+				if strings.ToLower(value) == "skip-verify" {
+					cfg.tls = &tls.Config{InsecureSkipVerify: true}
+				} else if tlsConfig, ok := tlsConfigRegister[value]; ok {
+					cfg.tls = tlsConfig
+				} else {
+					return fmt.Errorf("Invalid value / unknown config name: %s", value)
+				}
+			}
+
+		default:
+			// lazy init
+			if cfg.params == nil {
+				cfg.params = make(map[string]string)
+			}
+
+			if cfg.params[param[0]], err = url.QueryUnescape(value); err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// Returns the bool value of the input.
+// The 2nd return value indicates if the input was a valid bool value
+func readBool(input string) (value bool, valid bool) {
+	switch input {
+	case "1", "true", "TRUE", "True":
+		return true, true
+	case "0", "false", "FALSE", "False":
+		return false, true
+	}
+
+	// Not a valid bool value
+	return
+}
+
+/******************************************************************************
+*                             Authentication                                  *
+******************************************************************************/
+
+// Encrypt password using 4.1+ method
+func scramblePassword(scramble, password []byte) []byte {
+	if len(password) == 0 {
+		return nil
+	}
+
+	// stage1Hash = SHA1(password)
+	crypt := sha1.New()
+	crypt.Write(password)
+	stage1 := crypt.Sum(nil)
+
+	// scrambleHash = SHA1(scramble + SHA1(stage1Hash))
+	// inner Hash
+	crypt.Reset()
+	crypt.Write(stage1)
+	hash := crypt.Sum(nil)
+
+	// outer Hash
+	crypt.Reset()
+	crypt.Write(scramble)
+	crypt.Write(hash)
+	scramble = crypt.Sum(nil)
+
+	// token = scrambleHash XOR stage1Hash
+	for i := range scramble {
+		scramble[i] ^= stage1[i]
+	}
+	return scramble
+}
+
+// Encrypt password using pre 4.1 (old password) method
+// https://github.com/atcurtis/mariadb/blob/master/mysys/my_rnd.c
+type myRnd struct {
+	seed1, seed2 uint32
+}
+
+const myRndMaxVal = 0x3FFFFFFF
+
+// Pseudo random number generator
+func newMyRnd(seed1, seed2 uint32) *myRnd {
+	return &myRnd{
+		seed1: seed1 % myRndMaxVal,
+		seed2: seed2 % myRndMaxVal,
+	}
+}
+
+// Tested to be equivalent to MariaDB's floating point variant
+// http://play.golang.org/p/QHvhd4qved
+// http://play.golang.org/p/RG0q4ElWDx
+func (r *myRnd) NextByte() byte {
+	r.seed1 = (r.seed1*3 + r.seed2) % myRndMaxVal
+	r.seed2 = (r.seed1 + r.seed2 + 33) % myRndMaxVal
+
+	return byte(uint64(r.seed1) * 31 / myRndMaxVal)
+}
+
+// Generate binary hash from byte string using insecure pre 4.1 method
+func pwHash(password []byte) (result [2]uint32) {
+	var add uint32 = 7
+	var tmp uint32
+
+	result[0] = 1345345333
+	result[1] = 0x12345671
+
+	for _, c := range password {
+		// skip spaces and tabs in password
+		if c == ' ' || c == '\t' {
+			continue
+		}
+
+		tmp = uint32(c)
+		result[0] ^= (((result[0] & 63) + add) * tmp) + (result[0] << 8)
+		result[1] += (result[1] << 8) ^ result[0]
+		add += tmp
+	}
+
+	// Remove sign bit (1<<31)-1)
+	result[0] &= 0x7FFFFFFF
+	result[1] &= 0x7FFFFFFF
+
+	return
+}
+
+// Encrypt password using insecure pre 4.1 method
+func scrambleOldPassword(scramble, password []byte) []byte {
+	if len(password) == 0 {
+		return nil
+	}
+
+	scramble = scramble[:8]
+
+	hashPw := pwHash(password)
+	hashSc := pwHash(scramble)
+
+	r := newMyRnd(hashPw[0]^hashSc[0], hashPw[1]^hashSc[1])
+
+	var out [8]byte
+	for i := range out {
+		out[i] = r.NextByte() + 64
+	}
+
+	mask := r.NextByte()
+	for i := range out {
+		out[i] ^= mask
+	}
+
+	return out[:]
+}
+
+/******************************************************************************
+*                           Time related utils                                *
+******************************************************************************/
+
+// NullTime represents a time.Time that may be NULL.
+// NullTime implements the Scanner interface so
+// it can be used as a scan destination:
+//
+//  var nt NullTime
+//  err := db.QueryRow("SELECT time FROM foo WHERE id=?", id).Scan(&nt)
+//  ...
+//  if nt.Valid {
+//     // use nt.Time
+//  } else {
+//     // NULL value
+//  }
+//
+// This NullTime implementation is not driver-specific
+type NullTime struct {
+	Time  time.Time
+	Valid bool // Valid is true if Time is not NULL
+}
+
+// Scan implements the Scanner interface.
+// The value type must be time.Time or string / []byte (formatted time-string),
+// otherwise Scan fails.
+func (nt *NullTime) Scan(value interface{}) (err error) {
+	if value == nil {
+		nt.Time, nt.Valid = time.Time{}, false
+		return
+	}
+
+	switch v := value.(type) {
+	case time.Time:
+		nt.Time, nt.Valid = v, true
+		return
+	case []byte:
+		nt.Time, err = parseDateTime(string(v), time.UTC)
+		nt.Valid = (err == nil)
+		return
+	case string:
+		nt.Time, err = parseDateTime(v, time.UTC)
+		nt.Valid = (err == nil)
+		return
+	}
+
+	nt.Valid = false
+	return fmt.Errorf("Can't convert %T to time.Time", value)
+}
+
+// Value implements the driver Valuer interface.
+func (nt NullTime) Value() (driver.Value, error) {
+	if !nt.Valid {
+		return nil, nil
+	}
+	return nt.Time, nil
+}
+
+func parseDateTime(str string, loc *time.Location) (t time.Time, err error) {
+	base := "0000-00-00 00:00:00.0000000"
+	switch len(str) {
+	case 10, 19, 21, 22, 23, 24, 25, 26: // up to "YYYY-MM-DD HH:MM:SS.MMMMMM"
+		if str == base[:len(str)] {
+			return
+		}
+		t, err = time.Parse(timeFormat[:len(str)], str)
+	default:
+		err = fmt.Errorf("Invalid Time-String: %s", str)
+		return
+	}
+
+	// Adjust location
+	if err == nil && loc != time.UTC {
+		y, mo, d := t.Date()
+		h, mi, s := t.Clock()
+		t, err = time.Date(y, mo, d, h, mi, s, t.Nanosecond(), loc), nil
+	}
+
+	return
+}
+
+func parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Value, error) {
+	switch num {
+	case 0:
+		return time.Time{}, nil
+	case 4:
+		return time.Date(
+			int(binary.LittleEndian.Uint16(data[:2])), // year
+			time.Month(data[2]),                       // month
+			int(data[3]),                              // day
+			0, 0, 0, 0,
+			loc,
+		), nil
+	case 7:
+		return time.Date(
+			int(binary.LittleEndian.Uint16(data[:2])), // year
+			time.Month(data[2]),                       // month
+			int(data[3]),                              // day
+			int(data[4]),                              // hour
+			int(data[5]),                              // minutes
+			int(data[6]),                              // seconds
+			0,
+			loc,
+		), nil
+	case 11:
+		return time.Date(
+			int(binary.LittleEndian.Uint16(data[:2])), // year
+			time.Month(data[2]),                       // month
+			int(data[3]),                              // day
+			int(data[4]),                              // hour
+			int(data[5]),                              // minutes
+			int(data[6]),                              // seconds
+			int(binary.LittleEndian.Uint32(data[7:11]))*1000, // nanoseconds
+			loc,
+		), nil
+	}
+	return nil, fmt.Errorf("Invalid DATETIME-packet length %d", num)
+}
+
+// zeroDateTime is used in formatBinaryDateTime to avoid an allocation
+// if the DATE or DATETIME has the zero value.
+// It must never be changed.
+// The current behavior depends on database/sql copying the result.
+var zeroDateTime = []byte("0000-00-00 00:00:00.000000")
+
+func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value, error) {
+	// length expects the deterministic length of the zero value,
+	// negative time and 100+ hours are automatically added if needed
+	const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
+	const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
+	if len(src) == 0 {
+		if justTime {
+			return zeroDateTime[11 : 11+length], nil
+		}
+		return zeroDateTime[:length], nil
+	}
+	var dst []byte          // return value
+	var pt, p1, p2, p3 byte // current digit pair
+	var zOffs byte          // offset of value in zeroDateTime
+	if justTime {
+		switch length {
+		case
+			8,                      // time (can be up to 10 when negative and 100+ hours)
+			10, 11, 12, 13, 14, 15: // time with fractional seconds
+		default:
+			return nil, fmt.Errorf("illegal TIME length %d", length)
+		}
+		switch len(src) {
+		case 8, 12:
+		default:
+			return nil, fmt.Errorf("Invalid TIME-packet length %d", len(src))
+		}
+		// +2 to enable negative time and 100+ hours
+		dst = make([]byte, 0, length+2)
+		if src[0] == 1 {
+			dst = append(dst, '-')
+		}
+		if src[1] != 0 {
+			hour := uint16(src[1])*24 + uint16(src[5])
+			pt = byte(hour / 100)
+			p1 = byte(hour - 100*uint16(pt))
+			dst = append(dst, digits01[pt])
+		} else {
+			p1 = src[5]
+		}
+		zOffs = 11
+		src = src[6:]
+	} else {
+		switch length {
+		case 10, 19, 21, 22, 23, 24, 25, 26:
+		default:
+			t := "DATE"
+			if length > 10 {
+				t += "TIME"
+			}
+			return nil, fmt.Errorf("illegal %s length %d", t, length)
+		}
+		switch len(src) {
+		case 4, 7, 11:
+		default:
+			t := "DATE"
+			if length > 10 {
+				t += "TIME"
+			}
+			return nil, fmt.Errorf("illegal %s-packet length %d", t, len(src))
+		}
+		dst = make([]byte, 0, length)
+		// start with the date
+		year := binary.LittleEndian.Uint16(src[:2])
+		pt = byte(year / 100)
+		p1 = byte(year - 100*uint16(pt))
+		p2, p3 = src[2], src[3]
+		dst = append(dst,
+			digits10[pt], digits01[pt],
+			digits10[p1], digits01[p1], '-',
+			digits10[p2], digits01[p2], '-',
+			digits10[p3], digits01[p3],
+		)
+		if length == 10 {
+			return dst, nil
+		}
+		if len(src) == 4 {
+			return append(dst, zeroDateTime[10:length]...), nil
+		}
+		dst = append(dst, ' ')
+		p1 = src[4] // hour
+		src = src[5:]
+	}
+	// p1 is 2-digit hour, src is after hour
+	p2, p3 = src[0], src[1]
+	dst = append(dst,
+		digits10[p1], digits01[p1], ':',
+		digits10[p2], digits01[p2], ':',
+		digits10[p3], digits01[p3],
+	)
+	if length <= byte(len(dst)) {
+		return dst, nil
+	}
+	src = src[2:]
+	if len(src) == 0 {
+		return append(dst, zeroDateTime[19:zOffs+length]...), nil
+	}
+	microsecs := binary.LittleEndian.Uint32(src[:4])
+	p1 = byte(microsecs / 10000)
+	microsecs -= 10000 * uint32(p1)
+	p2 = byte(microsecs / 100)
+	microsecs -= 100 * uint32(p2)
+	p3 = byte(microsecs)
+	switch decimals := zOffs + length - 20; decimals {
+	default:
+		return append(dst, '.',
+			digits10[p1], digits01[p1],
+			digits10[p2], digits01[p2],
+			digits10[p3], digits01[p3],
+		), nil
+	case 1:
+		return append(dst, '.',
+			digits10[p1],
+		), nil
+	case 2:
+		return append(dst, '.',
+			digits10[p1], digits01[p1],
+		), nil
+	case 3:
+		return append(dst, '.',
+			digits10[p1], digits01[p1],
+			digits10[p2],
+		), nil
+	case 4:
+		return append(dst, '.',
+			digits10[p1], digits01[p1],
+			digits10[p2], digits01[p2],
+		), nil
+	case 5:
+		return append(dst, '.',
+			digits10[p1], digits01[p1],
+			digits10[p2], digits01[p2],
+			digits10[p3],
+		), nil
+	}
+}
+
+/******************************************************************************
+*                       Convert from and to bytes                             *
+******************************************************************************/
+
+func uint64ToBytes(n uint64) []byte {
+	return []byte{
+		byte(n),
+		byte(n >> 8),
+		byte(n >> 16),
+		byte(n >> 24),
+		byte(n >> 32),
+		byte(n >> 40),
+		byte(n >> 48),
+		byte(n >> 56),
+	}
+}
+
+func uint64ToString(n uint64) []byte {
+	var a [20]byte
+	i := 20
+
+	// U+0030 = 0
+	// ...
+	// U+0039 = 9
+
+	var q uint64
+	for n >= 10 {
+		i--
+		q = n / 10
+		a[i] = uint8(n-q*10) + 0x30
+		n = q
+	}
+
+	i--
+	a[i] = uint8(n) + 0x30
+
+	return a[i:]
+}
+
+// treats string value as unsigned integer representation
+func stringToInt(b []byte) int {
+	val := 0
+	for i := range b {
+		val *= 10
+		val += int(b[i] - 0x30)
+	}
+	return val
+}
+
+// returns the string read as a bytes slice, wheter the value is NULL,
+// the number of bytes read and an error, in case the string is longer than
+// the input slice
+func readLengthEncodedString(b []byte) ([]byte, bool, int, error) {
+	// Get length
+	num, isNull, n := readLengthEncodedInteger(b)
+	if num < 1 {
+		return b[n:n], isNull, n, nil
+	}
+
+	n += int(num)
+
+	// Check data length
+	if len(b) >= n {
+		return b[n-int(num) : n], false, n, nil
+	}
+	return nil, false, n, io.EOF
+}
+
+// returns the number of bytes skipped and an error, in case the string is
+// longer than the input slice
+func skipLengthEncodedString(b []byte) (int, error) {
+	// Get length
+	num, _, n := readLengthEncodedInteger(b)
+	if num < 1 {
+		return n, nil
+	}
+
+	n += int(num)
+
+	// Check data length
+	if len(b) >= n {
+		return n, nil
+	}
+	return n, io.EOF
+}
+
+// returns the number read, whether the value is NULL and the number of bytes read
+func readLengthEncodedInteger(b []byte) (uint64, bool, int) {
+	switch b[0] {
+
+	// 251: NULL
+	case 0xfb:
+		return 0, true, 1
+
+	// 252: value of following 2
+	case 0xfc:
+		return uint64(b[1]) | uint64(b[2])<<8, false, 3
+
+	// 253: value of following 3
+	case 0xfd:
+		return uint64(b[1]) | uint64(b[2])<<8 | uint64(b[3])<<16, false, 4
+
+	// 254: value of following 8
+	case 0xfe:
+		return uint64(b[1]) | uint64(b[2])<<8 | uint64(b[3])<<16 |
+				uint64(b[4])<<24 | uint64(b[5])<<32 | uint64(b[6])<<40 |
+				uint64(b[7])<<48 | uint64(b[8])<<56,
+			false, 9
+	}
+
+	// 0-250: value of first byte
+	return uint64(b[0]), false, 1
+}
+
+// encodes a uint64 value and appends it to the given bytes slice
+func appendLengthEncodedInteger(b []byte, n uint64) []byte {
+	switch {
+	case n <= 250:
+		return append(b, byte(n))
+
+	case n <= 0xffff:
+		return append(b, 0xfc, byte(n), byte(n>>8))
+
+	case n <= 0xffffff:
+		return append(b, 0xfd, byte(n), byte(n>>8), byte(n>>16))
+	}
+	return append(b, 0xfe, byte(n), byte(n>>8), byte(n>>16), byte(n>>24),
+		byte(n>>32), byte(n>>40), byte(n>>48), byte(n>>56))
+}

+ 212 - 0
Godeps/_workspace/src/github.com/go-sql-driver/mysql/utils_test.go

@@ -0,0 +1,212 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package mysql
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"testing"
+	"time"
+)
+
+var testDSNs = []struct {
+	in  string
+	out string
+	loc *time.Location
+}{
+	{"username:password@protocol(address)/dbname?param=value", "&{user:username passwd:password net:protocol addr:address dbname:dbname params:map[param:value] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
+	{"user@unix(/path/to/socket)/dbname?charset=utf8", "&{user:user passwd: net:unix addr:/path/to/socket dbname:dbname params:map[charset:utf8] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
+	{"user:password@tcp(localhost:5555)/dbname?charset=utf8&tls=true", "&{user:user passwd:password net:tcp addr:localhost:5555 dbname:dbname params:map[charset:utf8] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
+	{"user:password@tcp(localhost:5555)/dbname?charset=utf8mb4,utf8&tls=skip-verify", "&{user:user passwd:password net:tcp addr:localhost:5555 dbname:dbname params:map[charset:utf8mb4,utf8] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
+	{"user:password@/dbname?loc=UTC&timeout=30s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci", "&{user:user passwd:password net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:30000000000 collation:224 allowAllFiles:true allowOldPasswords:true clientFoundRows:true}", time.UTC},
+	{"user:p@ss(word)@tcp([de:ad:be:ef::ca:fe]:80)/dbname?loc=Local", "&{user:user passwd:p@ss(word) net:tcp addr:[de:ad:be:ef::ca:fe]:80 dbname:dbname params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.Local},
+	{"/dbname", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
+	{"@/", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
+	{"/", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
+	{"", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
+	{"user:p@/ssword@/", "&{user:user passwd:p@/ssword net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
+	{"unix/?arg=%2Fsome%2Fpath.ext", "&{user: passwd: net:unix addr:/tmp/mysql.sock dbname: params:map[arg:/some/path.ext] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
+}
+
+func TestDSNParser(t *testing.T) {
+	var cfg *config
+	var err error
+	var res string
+
+	for i, tst := range testDSNs {
+		cfg, err = parseDSN(tst.in)
+		if err != nil {
+			t.Error(err.Error())
+		}
+
+		// pointer not static
+		cfg.tls = nil
+
+		res = fmt.Sprintf("%+v", cfg)
+		if res != fmt.Sprintf(tst.out, tst.loc) {
+			t.Errorf("%d. parseDSN(%q) => %q, want %q", i, tst.in, res, fmt.Sprintf(tst.out, tst.loc))
+		}
+	}
+}
+
+func TestDSNParserInvalid(t *testing.T) {
+	var invalidDSNs = []string{
+		"@net(addr/",                  // no closing brace
+		"@tcp(/",                      // no closing brace
+		"tcp(/",                       // no closing brace
+		"(/",                          // no closing brace
+		"net(addr)//",                 // unescaped
+		"user:pass@tcp(1.2.3.4:3306)", // no trailing slash
+		//"/dbname?arg=/some/unescaped/path",
+	}
+
+	for i, tst := range invalidDSNs {
+		if _, err := parseDSN(tst); err == nil {
+			t.Errorf("invalid DSN #%d. (%s) didn't error!", i, tst)
+		}
+	}
+}
+
+func BenchmarkParseDSN(b *testing.B) {
+	b.ReportAllocs()
+
+	for i := 0; i < b.N; i++ {
+		for _, tst := range testDSNs {
+			if _, err := parseDSN(tst.in); err != nil {
+				b.Error(err.Error())
+			}
+		}
+	}
+}
+
+func TestScanNullTime(t *testing.T) {
+	var scanTests = []struct {
+		in    interface{}
+		error bool
+		valid bool
+		time  time.Time
+	}{
+		{tDate, false, true, tDate},
+		{sDate, false, true, tDate},
+		{[]byte(sDate), false, true, tDate},
+		{tDateTime, false, true, tDateTime},
+		{sDateTime, false, true, tDateTime},
+		{[]byte(sDateTime), false, true, tDateTime},
+		{tDate0, false, true, tDate0},
+		{sDate0, false, true, tDate0},
+		{[]byte(sDate0), false, true, tDate0},
+		{sDateTime0, false, true, tDate0},
+		{[]byte(sDateTime0), false, true, tDate0},
+		{"", true, false, tDate0},
+		{"1234", true, false, tDate0},
+		{0, true, false, tDate0},
+	}
+
+	var nt = NullTime{}
+	var err error
+
+	for _, tst := range scanTests {
+		err = nt.Scan(tst.in)
+		if (err != nil) != tst.error {
+			t.Errorf("%v: expected error status %t, got %t", tst.in, tst.error, (err != nil))
+		}
+		if nt.Valid != tst.valid {
+			t.Errorf("%v: expected valid status %t, got %t", tst.in, tst.valid, nt.Valid)
+		}
+		if nt.Time != tst.time {
+			t.Errorf("%v: expected time %v, got %v", tst.in, tst.time, nt.Time)
+		}
+	}
+}
+
+func TestLengthEncodedInteger(t *testing.T) {
+	var integerTests = []struct {
+		num     uint64
+		encoded []byte
+	}{
+		{0x0000000000000000, []byte{0x00}},
+		{0x0000000000000012, []byte{0x12}},
+		{0x00000000000000fa, []byte{0xfa}},
+		{0x0000000000000100, []byte{0xfc, 0x00, 0x01}},
+		{0x0000000000001234, []byte{0xfc, 0x34, 0x12}},
+		{0x000000000000ffff, []byte{0xfc, 0xff, 0xff}},
+		{0x0000000000010000, []byte{0xfd, 0x00, 0x00, 0x01}},
+		{0x0000000000123456, []byte{0xfd, 0x56, 0x34, 0x12}},
+		{0x0000000000ffffff, []byte{0xfd, 0xff, 0xff, 0xff}},
+		{0x0000000001000000, []byte{0xfe, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}},
+		{0x123456789abcdef0, []byte{0xfe, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12}},
+		{0xffffffffffffffff, []byte{0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
+	}
+
+	for _, tst := range integerTests {
+		num, isNull, numLen := readLengthEncodedInteger(tst.encoded)
+		if isNull {
+			t.Errorf("%x: expected %d, got NULL", tst.encoded, tst.num)
+		}
+		if num != tst.num {
+			t.Errorf("%x: expected %d, got %d", tst.encoded, tst.num, num)
+		}
+		if numLen != len(tst.encoded) {
+			t.Errorf("%x: expected size %d, got %d", tst.encoded, len(tst.encoded), numLen)
+		}
+		encoded := appendLengthEncodedInteger(nil, num)
+		if !bytes.Equal(encoded, tst.encoded) {
+			t.Errorf("%v: expected %x, got %x", num, tst.encoded, encoded)
+		}
+	}
+}
+
+func TestOldPass(t *testing.T) {
+	scramble := []byte{9, 8, 7, 6, 5, 4, 3, 2}
+	vectors := []struct {
+		pass string
+		out  string
+	}{
+		{" pass", "47575c5a435b4251"},
+		{"pass ", "47575c5a435b4251"},
+		{"123\t456", "575c47505b5b5559"},
+		{"C0mpl!ca ted#PASS123", "5d5d554849584a45"},
+	}
+	for _, tuple := range vectors {
+		ours := scrambleOldPassword(scramble, []byte(tuple.pass))
+		if tuple.out != fmt.Sprintf("%x", ours) {
+			t.Errorf("Failed old password %q", tuple.pass)
+		}
+	}
+}
+
+func TestFormatBinaryDateTime(t *testing.T) {
+	rawDate := [11]byte{}
+	binary.LittleEndian.PutUint16(rawDate[:2], 1978)   // years
+	rawDate[2] = 12                                    // months
+	rawDate[3] = 30                                    // days
+	rawDate[4] = 15                                    // hours
+	rawDate[5] = 46                                    // minutes
+	rawDate[6] = 23                                    // seconds
+	binary.LittleEndian.PutUint32(rawDate[7:], 987654) // microseconds
+	expect := func(expected string, inlen, outlen uint8) {
+		actual, _ := formatBinaryDateTime(rawDate[:inlen], outlen, false)
+		bytes, ok := actual.([]byte)
+		if !ok {
+			t.Errorf("formatBinaryDateTime must return []byte, was %T", actual)
+		}
+		if string(bytes) != expected {
+			t.Errorf(
+				"expected %q, got %q for length in %d, out %d",
+				bytes, actual, inlen, outlen,
+			)
+		}
+	}
+	expect("0000-00-00", 0, 10)
+	expect("0000-00-00 00:00:00", 0, 19)
+	expect("1978-12-30", 4, 10)
+	expect("1978-12-30 15:46:23", 7, 19)
+	expect("1978-12-30 15:46:23.987654", 11, 26)
+}

+ 0 - 63
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions.go

@@ -1,63 +0,0 @@
-package convey
-
-import "github.com/smartystreets/goconvey/convey/assertions"
-
-var (
-	ShouldEqual          = assertions.ShouldEqual
-	ShouldNotEqual       = assertions.ShouldNotEqual
-	ShouldAlmostEqual    = assertions.ShouldAlmostEqual
-	ShouldNotAlmostEqual = assertions.ShouldNotAlmostEqual
-	ShouldResemble       = assertions.ShouldResemble
-	ShouldNotResemble    = assertions.ShouldNotResemble
-	ShouldPointTo        = assertions.ShouldPointTo
-	ShouldNotPointTo     = assertions.ShouldNotPointTo
-	ShouldBeNil          = assertions.ShouldBeNil
-	ShouldNotBeNil       = assertions.ShouldNotBeNil
-	ShouldBeTrue         = assertions.ShouldBeTrue
-	ShouldBeFalse        = assertions.ShouldBeFalse
-	ShouldBeZeroValue    = assertions.ShouldBeZeroValue
-
-	ShouldBeGreaterThan          = assertions.ShouldBeGreaterThan
-	ShouldBeGreaterThanOrEqualTo = assertions.ShouldBeGreaterThanOrEqualTo
-	ShouldBeLessThan             = assertions.ShouldBeLessThan
-	ShouldBeLessThanOrEqualTo    = assertions.ShouldBeLessThanOrEqualTo
-	ShouldBeBetween              = assertions.ShouldBeBetween
-	ShouldNotBeBetween           = assertions.ShouldNotBeBetween
-
-	ShouldContain    = assertions.ShouldContain
-	ShouldNotContain = assertions.ShouldNotContain
-	ShouldBeIn       = assertions.ShouldBeIn
-	ShouldNotBeIn    = assertions.ShouldNotBeIn
-	ShouldBeEmpty    = assertions.ShouldBeEmpty
-	ShouldNotBeEmpty = assertions.ShouldNotBeEmpty
-
-	ShouldStartWith           = assertions.ShouldStartWith
-	ShouldNotStartWith        = assertions.ShouldNotStartWith
-	ShouldEndWith             = assertions.ShouldEndWith
-	ShouldNotEndWith          = assertions.ShouldNotEndWith
-	ShouldBeBlank             = assertions.ShouldBeBlank
-	ShouldNotBeBlank          = assertions.ShouldNotBeBlank
-	ShouldContainSubstring    = assertions.ShouldContainSubstring
-	ShouldNotContainSubstring = assertions.ShouldNotContainSubstring
-
-	ShouldPanic        = assertions.ShouldPanic
-	ShouldNotPanic     = assertions.ShouldNotPanic
-	ShouldPanicWith    = assertions.ShouldPanicWith
-	ShouldNotPanicWith = assertions.ShouldNotPanicWith
-
-	ShouldHaveSameTypeAs    = assertions.ShouldHaveSameTypeAs
-	ShouldNotHaveSameTypeAs = assertions.ShouldNotHaveSameTypeAs
-	ShouldImplement         = assertions.ShouldImplement
-	ShouldNotImplement      = assertions.ShouldNotImplement
-
-	ShouldHappenBefore         = assertions.ShouldHappenBefore
-	ShouldHappenOnOrBefore     = assertions.ShouldHappenOnOrBefore
-	ShouldHappenAfter          = assertions.ShouldHappenAfter
-	ShouldHappenOnOrAfter      = assertions.ShouldHappenOnOrAfter
-	ShouldHappenBetween        = assertions.ShouldHappenBetween
-	ShouldHappenOnOrBetween    = assertions.ShouldHappenOnOrBetween
-	ShouldNotHappenOnOrBetween = assertions.ShouldNotHappenOnOrBetween
-	ShouldHappenWithin         = assertions.ShouldHappenWithin
-	ShouldNotHappenWithin      = assertions.ShouldNotHappenWithin
-	ShouldBeChronological      = assertions.ShouldBeChronological
-)

+ 0 - 140
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/collections.go

@@ -1,140 +0,0 @@
-package assertions
-
-import (
-	"fmt"
-	"reflect"
-
-	"github.com/jacobsa/oglematchers"
-)
-
-// ShouldContain receives exactly two parameters. The first is a slice and the
-// second is a proposed member. Membership is determined using ShouldEqual.
-func ShouldContain(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	if matchError := oglematchers.Contains(expected[0]).Matches(actual); matchError != nil {
-		typeName := reflect.TypeOf(actual)
-
-		if fmt.Sprintf("%v", matchError) == "which is not a slice or array" {
-			return fmt.Sprintf(shouldHaveBeenAValidCollection, typeName)
-		}
-		return fmt.Sprintf(shouldHaveContained, typeName, expected[0])
-	}
-	return success
-}
-
-// ShouldNotContain receives exactly two parameters. The first is a slice and the
-// second is a proposed member. Membership is determinied using ShouldEqual.
-func ShouldNotContain(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-	typeName := reflect.TypeOf(actual)
-
-	if matchError := oglematchers.Contains(expected[0]).Matches(actual); matchError != nil {
-		if fmt.Sprintf("%v", matchError) == "which is not a slice or array" {
-			return fmt.Sprintf(shouldHaveBeenAValidCollection, typeName)
-		}
-		return success
-	}
-	return fmt.Sprintf(shouldNotHaveContained, typeName, expected[0])
-}
-
-// ShouldBeIn receives at least 2 parameters. The first is a proposed member of the collection
-// that is passed in either as the second parameter, or of the collection that is comprised
-// of all the remaining parameters. This assertion ensures that the proposed member is in
-// the collection (using ShouldEqual).
-func ShouldBeIn(actual interface{}, expected ...interface{}) string {
-	if fail := atLeast(1, expected); fail != success {
-		return fail
-	}
-
-	if len(expected) == 1 {
-		return shouldBeIn(actual, expected[0])
-	}
-	return shouldBeIn(actual, expected)
-}
-func shouldBeIn(actual interface{}, expected interface{}) string {
-	if matchError := oglematchers.Contains(actual).Matches(expected); matchError != nil {
-		return fmt.Sprintf(shouldHaveBeenIn, actual, reflect.TypeOf(expected))
-	}
-	return success
-}
-
-// ShouldNotBeIn receives at least 2 parameters. The first is a proposed member of the collection
-// that is passed in either as the second parameter, or of the collection that is comprised
-// of all the remaining parameters. This assertion ensures that the proposed member is NOT in
-// the collection (using ShouldEqual).
-func ShouldNotBeIn(actual interface{}, expected ...interface{}) string {
-	if fail := atLeast(1, expected); fail != success {
-		return fail
-	}
-
-	if len(expected) == 1 {
-		return shouldNotBeIn(actual, expected[0])
-	}
-	return shouldNotBeIn(actual, expected)
-}
-func shouldNotBeIn(actual interface{}, expected interface{}) string {
-	if matchError := oglematchers.Contains(actual).Matches(expected); matchError == nil {
-		return fmt.Sprintf(shouldNotHaveBeenIn, actual, reflect.TypeOf(expected))
-	}
-	return success
-}
-
-// ShouldBeEmpty receives a single parameter (actual) and determines whether or not
-// calling len(actual) would return `0`. It obeys the rules specified by the len
-// function for determining length: http://golang.org/pkg/builtin/#len
-func ShouldBeEmpty(actual interface{}, expected ...interface{}) string {
-	if fail := need(0, expected); fail != success {
-		return fail
-	}
-
-	if actual == nil {
-		return success
-	}
-
-	value := reflect.ValueOf(actual)
-	switch value.Kind() {
-	case reflect.Slice:
-		if value.Len() == 0 {
-			return success
-		}
-	case reflect.Chan:
-		if value.Len() == 0 {
-			return success
-		}
-	case reflect.Map:
-		if value.Len() == 0 {
-			return success
-		}
-	case reflect.String:
-		if value.Len() == 0 {
-			return success
-		}
-	case reflect.Ptr:
-		elem := value.Elem()
-		kind := elem.Kind()
-		if (kind == reflect.Slice || kind == reflect.Array) && elem.Len() == 0 {
-			return success
-		}
-	}
-
-	return fmt.Sprintf(shouldHaveBeenEmpty, actual)
-}
-
-// ShouldNotBeEmpty receives a single parameter (actual) and determines whether or not
-// calling len(actual) would return a value greater than zero. It obeys the rules
-// specified by the `len` function for determining length: http://golang.org/pkg/builtin/#len
-func ShouldNotBeEmpty(actual interface{}, expected ...interface{}) string {
-	if fail := need(0, expected); fail != success {
-		return fail
-	}
-
-	if empty := ShouldBeEmpty(actual, expected...); empty != success {
-		return success
-	}
-	return fmt.Sprintf(shouldNotHaveBeenEmpty, actual)
-}

+ 0 - 103
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/collections_test.go

@@ -1,103 +0,0 @@
-package assertions
-
-import (
-	"fmt"
-	"testing"
-	"time"
-)
-
-func TestShouldContain(t *testing.T) {
-	fail(t, so([]int{}, ShouldContain), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so([]int{}, ShouldContain, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(Thing1{}, ShouldContain, 1), "You must provide a valid container (was assertions.Thing1)!")
-	fail(t, so(nil, ShouldContain, 1), "You must provide a valid container (was <nil>)!")
-	fail(t, so([]int{1}, ShouldContain, 2), "Expected the container ([]int) to contain: '2' (but it didn't)!")
-
-	pass(t, so([]int{1}, ShouldContain, 1))
-	pass(t, so([]int{1, 2, 3}, ShouldContain, 2))
-}
-
-func TestShouldNotContain(t *testing.T) {
-	fail(t, so([]int{}, ShouldNotContain), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so([]int{}, ShouldNotContain, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(Thing1{}, ShouldNotContain, 1), "You must provide a valid container (was assertions.Thing1)!")
-	fail(t, so(nil, ShouldNotContain, 1), "You must provide a valid container (was <nil>)!")
-
-	fail(t, so([]int{1}, ShouldNotContain, 1), "Expected the container ([]int) NOT to contain: '1' (but it did)!")
-	fail(t, so([]int{1, 2, 3}, ShouldNotContain, 2), "Expected the container ([]int) NOT to contain: '2' (but it did)!")
-
-	pass(t, so([]int{1}, ShouldNotContain, 2))
-}
-
-func TestShouldBeIn(t *testing.T) {
-	fail(t, so(4, ShouldBeIn), shouldHaveProvidedCollectionMembers)
-
-	container := []int{1, 2, 3, 4}
-	pass(t, so(4, ShouldBeIn, container))
-	pass(t, so(4, ShouldBeIn, 1, 2, 3, 4))
-
-	fail(t, so(4, ShouldBeIn, 1, 2, 3), "Expected '4' to be in the container ([]interface {}, but it wasn't)!")
-	fail(t, so(4, ShouldBeIn, []int{1, 2, 3}), "Expected '4' to be in the container ([]int, but it wasn't)!")
-}
-
-func TestShouldNotBeIn(t *testing.T) {
-	fail(t, so(4, ShouldNotBeIn), shouldHaveProvidedCollectionMembers)
-
-	container := []int{1, 2, 3, 4}
-	pass(t, so(42, ShouldNotBeIn, container))
-	pass(t, so(42, ShouldNotBeIn, 1, 2, 3, 4))
-
-	fail(t, so(2, ShouldNotBeIn, 1, 2, 3), "Expected '2' NOT to be in the container ([]interface {}, but it was)!")
-	fail(t, so(2, ShouldNotBeIn, []int{1, 2, 3}), "Expected '2' NOT to be in the container ([]int, but it was)!")
-}
-
-func TestShouldBeEmpty(t *testing.T) {
-	fail(t, so(1, ShouldBeEmpty, 2, 3), "This assertion requires exactly 0 comparison values (you provided 2).")
-
-	pass(t, so([]int{}, ShouldBeEmpty))           // empty slice
-	pass(t, so([]interface{}{}, ShouldBeEmpty))   // empty slice
-	pass(t, so(map[string]int{}, ShouldBeEmpty))  // empty map
-	pass(t, so("", ShouldBeEmpty))                // empty string
-	pass(t, so(&[]int{}, ShouldBeEmpty))          // pointer to empty slice
-	pass(t, so(&[0]int{}, ShouldBeEmpty))         // pointer to empty array
-	pass(t, so(nil, ShouldBeEmpty))               // nil
-	pass(t, so(make(chan string), ShouldBeEmpty)) // empty channel
-
-	fail(t, so([]int{1}, ShouldBeEmpty), "Expected [1] to be empty (but it wasn't)!")                      // non-empty slice
-	fail(t, so([]interface{}{1}, ShouldBeEmpty), "Expected [1] to be empty (but it wasn't)!")              // non-empty slice
-	fail(t, so(map[string]int{"hi": 0}, ShouldBeEmpty), "Expected map[hi:0] to be empty (but it wasn't)!") // non-empty map
-	fail(t, so("hi", ShouldBeEmpty), "Expected hi to be empty (but it wasn't)!")                           // non-empty string
-	fail(t, so(&[]int{1}, ShouldBeEmpty), "Expected &[1] to be empty (but it wasn't)!")                    // pointer to non-empty slice
-	fail(t, so(&[1]int{1}, ShouldBeEmpty), "Expected &[1] to be empty (but it wasn't)!")                   // pointer to non-empty array
-	c := make(chan int, 1)                                                                                 // non-empty channel
-	go func() { c <- 1 }()
-	time.Sleep(time.Millisecond)
-	fail(t, so(c, ShouldBeEmpty), fmt.Sprintf("Expected %+v to be empty (but it wasn't)!", c))
-}
-
-func TestShouldNotBeEmpty(t *testing.T) {
-	fail(t, so(1, ShouldNotBeEmpty, 2, 3), "This assertion requires exactly 0 comparison values (you provided 2).")
-
-	fail(t, so([]int{}, ShouldNotBeEmpty), "Expected [] to NOT be empty (but it was)!")             // empty slice
-	fail(t, so([]interface{}{}, ShouldNotBeEmpty), "Expected [] to NOT be empty (but it was)!")     // empty slice
-	fail(t, so(map[string]int{}, ShouldNotBeEmpty), "Expected map[] to NOT be empty (but it was)!") // empty map
-	fail(t, so("", ShouldNotBeEmpty), "Expected  to NOT be empty (but it was)!")                    // empty string
-	fail(t, so(&[]int{}, ShouldNotBeEmpty), "Expected &[] to NOT be empty (but it was)!")           // pointer to empty slice
-	fail(t, so(&[0]int{}, ShouldNotBeEmpty), "Expected &[] to NOT be empty (but it was)!")          // pointer to empty array
-	fail(t, so(nil, ShouldNotBeEmpty), "Expected <nil> to NOT be empty (but it was)!")              // nil
-	c := make(chan int, 0)                                                                          // non-empty channel
-	fail(t, so(c, ShouldNotBeEmpty), fmt.Sprintf("Expected %+v to NOT be empty (but it was)!", c))  // empty channel
-
-	pass(t, so([]int{1}, ShouldNotBeEmpty))                // non-empty slice
-	pass(t, so([]interface{}{1}, ShouldNotBeEmpty))        // non-empty slice
-	pass(t, so(map[string]int{"hi": 0}, ShouldNotBeEmpty)) // non-empty map
-	pass(t, so("hi", ShouldNotBeEmpty))                    // non-empty string
-	pass(t, so(&[]int{1}, ShouldNotBeEmpty))               // pointer to non-empty slice
-	pass(t, so(&[1]int{1}, ShouldNotBeEmpty))              // pointer to non-empty array
-	c = make(chan int, 1)
-	go func() { c <- 1 }()
-	time.Sleep(time.Millisecond)
-	pass(t, so(c, ShouldNotBeEmpty))
-}

+ 0 - 3
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/doc.go

@@ -1,3 +0,0 @@
-// Package assertions contains the implementations for all assertions which
-// are referenced in the convey package for use with the So(...) method.
-package assertions

+ 0 - 281
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/equality.go

@@ -1,281 +0,0 @@
-package assertions
-
-import (
-	"errors"
-	"fmt"
-	"math"
-	"reflect"
-	"strings"
-
-	"github.com/jacobsa/oglematchers"
-)
-
-// default acceptable delta for ShouldAlmostEqual
-const defaultDelta = 0.0000000001
-
-// ShouldEqual receives exactly two parameters and does an equality check.
-func ShouldEqual(actual interface{}, expected ...interface{}) string {
-	if message := need(1, expected); message != success {
-		return message
-	}
-	return shouldEqual(actual, expected[0])
-}
-func shouldEqual(actual, expected interface{}) (message string) {
-	defer func() {
-		if r := recover(); r != nil {
-			message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual))
-			return
-		}
-	}()
-
-	if matchError := oglematchers.Equals(expected).Matches(actual); matchError != nil {
-		message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual))
-		return
-	}
-
-	return success
-}
-
-// ShouldNotEqual receives exactly two parameters and does an inequality check.
-func ShouldNotEqual(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	} else if ShouldEqual(actual, expected[0]) == success {
-		return fmt.Sprintf(shouldNotHaveBeenEqual, actual, expected[0])
-	}
-	return success
-}
-
-// ShouldAlmostEqual makes sure that two parameters are close enough to being equal.
-// The acceptable delta may be specified with a third argument,
-// or a very small default delta will be used.
-func ShouldAlmostEqual(actual interface{}, expected ...interface{}) string {
-	actualFloat, expectedFloat, deltaFloat, err := cleanAlmostEqualInput(actual, expected...)
-
-	if err != "" {
-		return err
-	}
-
-	if math.Abs(actualFloat-expectedFloat) <= deltaFloat {
-		return success
-	} else {
-		return fmt.Sprintf(shouldHaveBeenAlmostEqual, actualFloat, expectedFloat)
-	}
-}
-
-// ShouldNotAlmostEqual is the inverse of ShouldAlmostEqual
-func ShouldNotAlmostEqual(actual interface{}, expected ...interface{}) string {
-	actualFloat, expectedFloat, deltaFloat, err := cleanAlmostEqualInput(actual, expected...)
-
-	if err != "" {
-		return err
-	}
-
-	if math.Abs(actualFloat-expectedFloat) > deltaFloat {
-		return success
-	} else {
-		return fmt.Sprintf(shouldHaveNotBeenAlmostEqual, actualFloat, expectedFloat)
-	}
-}
-
-func cleanAlmostEqualInput(actual interface{}, expected ...interface{}) (float64, float64, float64, string) {
-	deltaFloat := 0.0000000001
-
-	if len(expected) == 0 {
-		return 0.0, 0.0, 0.0, "This assertion requires exactly one comparison value and an optional delta (you provided neither)"
-	} else if len(expected) == 2 {
-		delta, err := getFloat(expected[1])
-
-		if err != nil {
-			return 0.0, 0.0, 0.0, "delta must be a numerical type"
-		}
-
-		deltaFloat = delta
-	} else if len(expected) > 2 {
-		return 0.0, 0.0, 0.0, "This assertion requires exactly one comparison value and an optional delta (you provided more values)"
-	}
-
-	actualFloat, err := getFloat(actual)
-
-	if err != nil {
-		return 0.0, 0.0, 0.0, err.Error()
-	}
-
-	expectedFloat, err := getFloat(expected[0])
-
-	if err != nil {
-		return 0.0, 0.0, 0.0, err.Error()
-	}
-
-	return actualFloat, expectedFloat, deltaFloat, ""
-}
-
-// returns the float value of any real number, or error if it is not a numerical type
-func getFloat(num interface{}) (float64, error) {
-	numValue := reflect.ValueOf(num)
-	numKind := numValue.Kind()
-
-	if numKind == reflect.Int ||
-		numKind == reflect.Int8 ||
-		numKind == reflect.Int16 ||
-		numKind == reflect.Int32 ||
-		numKind == reflect.Int64 {
-		return float64(numValue.Int()), nil
-	} else if numKind == reflect.Uint ||
-		numKind == reflect.Uint8 ||
-		numKind == reflect.Uint16 ||
-		numKind == reflect.Uint32 ||
-		numKind == reflect.Uint64 {
-		return float64(numValue.Uint()), nil
-	} else if numKind == reflect.Float32 ||
-		numKind == reflect.Float64 {
-		return numValue.Float(), nil
-	} else {
-		return 0.0, errors.New("must be a numerical type, but was " + numKind.String())
-	}
-}
-
-// ShouldResemble receives exactly two parameters and does a deep equal check (see reflect.DeepEqual)
-func ShouldResemble(actual interface{}, expected ...interface{}) string {
-	if message := need(1, expected); message != success {
-		return message
-	}
-
-	if matchError := oglematchers.DeepEquals(expected[0]).Matches(actual); matchError != nil {
-		message := fmt.Sprintf(
-			shouldHaveResembled,
-			expected[0], expected[0],
-			actual, actual,
-		)
-		return serializer.serialize(
-			expected[0], actual, message)
-	}
-
-	return success
-}
-
-// ShouldNotResemble receives exactly two parameters and does an inverse deep equal check (see reflect.DeepEqual)
-func ShouldNotResemble(actual interface{}, expected ...interface{}) string {
-	if message := need(1, expected); message != success {
-		return message
-	} else if ShouldResemble(actual, expected[0]) == success {
-		return fmt.Sprintf(
-			shouldNotHaveResembled,
-			actual, actual,
-			expected[0], expected[0],
-		)
-	}
-	return success
-}
-
-// ShouldPointTo receives exactly two parameters and checks to see that they point to the same address.
-func ShouldPointTo(actual interface{}, expected ...interface{}) string {
-	if message := need(1, expected); message != success {
-		return message
-	}
-	return shouldPointTo(actual, expected[0])
-
-}
-func shouldPointTo(actual, expected interface{}) string {
-	actualValue := reflect.ValueOf(actual)
-	expectedValue := reflect.ValueOf(expected)
-
-	if ShouldNotBeNil(actual) != success {
-		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "nil")
-	} else if ShouldNotBeNil(expected) != success {
-		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "nil")
-	} else if actualValue.Kind() != reflect.Ptr {
-		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "not")
-	} else if expectedValue.Kind() != reflect.Ptr {
-		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "not")
-	} else if ShouldEqual(actualValue.Pointer(), expectedValue.Pointer()) != success {
-		actualAddress := reflect.ValueOf(actual).Pointer()
-		expectedAddress := reflect.ValueOf(expected).Pointer()
-		return serializer.serialize(expectedAddress, actualAddress, fmt.Sprintf(shouldHavePointedTo,
-			actual, actualAddress,
-			expected, expectedAddress))
-	}
-	return success
-}
-
-// ShouldNotPointTo receives exactly two parameters and checks to see that they point to different addresess.
-func ShouldNotPointTo(actual interface{}, expected ...interface{}) string {
-	if message := need(1, expected); message != success {
-		return message
-	}
-	compare := ShouldPointTo(actual, expected[0])
-	if strings.HasPrefix(compare, shouldBePointers) {
-		return compare
-	} else if compare == success {
-		return fmt.Sprintf(shouldNotHavePointedTo, actual, expected[0], reflect.ValueOf(actual).Pointer())
-	}
-	return success
-}
-
-// ShouldBeNil receives a single parameter and ensures that it is nil.
-func ShouldBeNil(actual interface{}, expected ...interface{}) string {
-	if fail := need(0, expected); fail != success {
-		return fail
-	} else if actual == nil {
-		return success
-	} else if interfaceHasNilValue(actual) {
-		return success
-	}
-	return fmt.Sprintf(shouldHaveBeenNil, actual)
-}
-func interfaceHasNilValue(actual interface{}) bool {
-	value := reflect.ValueOf(actual)
-	kind := value.Kind()
-	nilable := kind == reflect.Slice ||
-		kind == reflect.Chan ||
-		kind == reflect.Func ||
-		kind == reflect.Ptr ||
-		kind == reflect.Map
-
-	// Careful: reflect.Value.IsNil() will panic unless it's an interface, chan, map, func, slice, or ptr
-	// Reference: http://golang.org/pkg/reflect/#Value.IsNil
-	return nilable && value.IsNil()
-}
-
-// ShouldNotBeNil receives a single parameter and ensures that it is not nil.
-func ShouldNotBeNil(actual interface{}, expected ...interface{}) string {
-	if fail := need(0, expected); fail != success {
-		return fail
-	} else if ShouldBeNil(actual) == success {
-		return fmt.Sprintf(shouldNotHaveBeenNil, actual)
-	}
-	return success
-}
-
-// ShouldBeTrue receives a single parameter and ensures that it is true.
-func ShouldBeTrue(actual interface{}, expected ...interface{}) string {
-	if fail := need(0, expected); fail != success {
-		return fail
-	} else if actual != true {
-		return fmt.Sprintf(shouldHaveBeenTrue, actual)
-	}
-	return success
-}
-
-// ShouldBeFalse receives a single parameter and ensures that it is false.
-func ShouldBeFalse(actual interface{}, expected ...interface{}) string {
-	if fail := need(0, expected); fail != success {
-		return fail
-	} else if actual != false {
-		return fmt.Sprintf(shouldHaveBeenFalse, actual)
-	}
-	return success
-}
-
-// ShouldBeZeroValue receives a single parameter and ensures that it is
-// the Go equivalent of the default value, or "zero" value.
-func ShouldBeZeroValue(actual interface{}, expected ...interface{}) string {
-	if fail := need(0, expected); fail != success {
-		return fail
-	}
-	zeroVal := reflect.Zero(reflect.TypeOf(actual)).Interface()
-	if !reflect.DeepEqual(zeroVal, actual) {
-		return serializer.serialize(zeroVal, actual, fmt.Sprintf(shouldHaveBeenZeroValue, actual))
-	}
-	return success
-}

+ 0 - 256
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/equality_test.go

@@ -1,256 +0,0 @@
-package assertions
-
-import (
-	"fmt"
-	"reflect"
-	"testing"
-)
-
-func TestShouldEqual(t *testing.T) {
-	serializer = newFakeSerializer()
-
-	fail(t, so(1, ShouldEqual), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(1, ShouldEqual, 1, 2), "This assertion requires exactly 1 comparison values (you provided 2).")
-	fail(t, so(1, ShouldEqual, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	pass(t, so(1, ShouldEqual, 1))
-	fail(t, so(1, ShouldEqual, 2), "2|1|Expected: '2' Actual: '1' (Should be equal)")
-
-	pass(t, so(true, ShouldEqual, true))
-	fail(t, so(true, ShouldEqual, false), "false|true|Expected: 'false' Actual: 'true' (Should be equal)")
-
-	pass(t, so("hi", ShouldEqual, "hi"))
-	fail(t, so("hi", ShouldEqual, "bye"), "bye|hi|Expected: 'bye' Actual: 'hi' (Should be equal)")
-
-	pass(t, so(42, ShouldEqual, uint(42)))
-
-	fail(t, so(Thing1{"hi"}, ShouldEqual, Thing1{}), "{}|{hi}|Expected: '{}' Actual: '{hi}' (Should be equal)")
-	fail(t, so(Thing1{"hi"}, ShouldEqual, Thing1{"hi"}), "{hi}|{hi}|Expected: '{hi}' Actual: '{hi}' (Should be equal)")
-	fail(t, so(&Thing1{"hi"}, ShouldEqual, &Thing1{"hi"}), "&{hi}|&{hi}|Expected: '&{hi}' Actual: '&{hi}' (Should be equal)")
-
-	fail(t, so(Thing1{}, ShouldEqual, Thing2{}), "{}|{}|Expected: '{}' Actual: '{}' (Should be equal)")
-}
-
-func TestShouldNotEqual(t *testing.T) {
-	fail(t, so(1, ShouldNotEqual), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(1, ShouldNotEqual, 1, 2), "This assertion requires exactly 1 comparison values (you provided 2).")
-	fail(t, so(1, ShouldNotEqual, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	pass(t, so(1, ShouldNotEqual, 2))
-	fail(t, so(1, ShouldNotEqual, 1), "Expected '1' to NOT equal '1' (but it did)!")
-
-	pass(t, so(true, ShouldNotEqual, false))
-	fail(t, so(true, ShouldNotEqual, true), "Expected 'true' to NOT equal 'true' (but it did)!")
-
-	pass(t, so("hi", ShouldNotEqual, "bye"))
-	fail(t, so("hi", ShouldNotEqual, "hi"), "Expected 'hi' to NOT equal 'hi' (but it did)!")
-
-	pass(t, so(&Thing1{"hi"}, ShouldNotEqual, &Thing1{"hi"}))
-	pass(t, so(Thing1{"hi"}, ShouldNotEqual, Thing1{"hi"}))
-	pass(t, so(Thing1{}, ShouldNotEqual, Thing1{}))
-	pass(t, so(Thing1{}, ShouldNotEqual, Thing2{}))
-}
-
-func TestShouldAlmostEqual(t *testing.T) {
-	fail(t, so(1, ShouldAlmostEqual), "This assertion requires exactly one comparison value and an optional delta (you provided neither)")
-	fail(t, so(1, ShouldAlmostEqual, 1, 2, 3), "This assertion requires exactly one comparison value and an optional delta (you provided more values)")
-
-	// with the default delta
-	pass(t, so(1, ShouldAlmostEqual, .99999999999999))
-	pass(t, so(1.3612499999999996, ShouldAlmostEqual, 1.36125))
-	pass(t, so(0.7285312499999999, ShouldAlmostEqual, 0.72853125))
-	fail(t, so(1, ShouldAlmostEqual, .99), "Expected '1' to almost equal '0.99' (but it didn't)!")
-
-	// with a different delta
-	pass(t, so(100.0, ShouldAlmostEqual, 110.0, 10.0))
-	fail(t, so(100.0, ShouldAlmostEqual, 111.0, 10.5), "Expected '100' to almost equal '111' (but it didn't)!")
-
-	// ints should work
-	pass(t, so(100, ShouldAlmostEqual, 100.0))
-	fail(t, so(100, ShouldAlmostEqual, 99.0), "Expected '100' to almost equal '99' (but it didn't)!")
-
-	// float32 should work
-	pass(t, so(float64(100.0), ShouldAlmostEqual, float32(100.0)))
-	fail(t, so(float32(100.0), ShouldAlmostEqual, 99.0, float32(0.1)), "Expected '100' to almost equal '99' (but it didn't)!")
-}
-
-func TestShouldNotAlmostEqual(t *testing.T) {
-	fail(t, so(1, ShouldNotAlmostEqual), "This assertion requires exactly one comparison value and an optional delta (you provided neither)")
-	fail(t, so(1, ShouldNotAlmostEqual, 1, 2, 3), "This assertion requires exactly one comparison value and an optional delta (you provided more values)")
-
-	// with the default delta
-	fail(t, so(1, ShouldNotAlmostEqual, .99999999999999), "Expected '1' to NOT almost equal '0.99999999999999' (but it did)!")
-	fail(t, so(1.3612499999999996, ShouldNotAlmostEqual, 1.36125), "Expected '1.3612499999999996' to NOT almost equal '1.36125' (but it did)!")
-	pass(t, so(1, ShouldNotAlmostEqual, .99))
-
-	// with a different delta
-	fail(t, so(100.0, ShouldNotAlmostEqual, 110.0, 10.0), "Expected '100' to NOT almost equal '110' (but it did)!")
-	pass(t, so(100.0, ShouldNotAlmostEqual, 111.0, 10.5))
-
-	// ints should work
-	fail(t, so(100, ShouldNotAlmostEqual, 100.0), "Expected '100' to NOT almost equal '100' (but it did)!")
-	pass(t, so(100, ShouldNotAlmostEqual, 99.0))
-
-	// float32 should work
-	fail(t, so(float64(100.0), ShouldNotAlmostEqual, float32(100.0)), "Expected '100' to NOT almost equal '100' (but it did)!")
-	pass(t, so(float32(100.0), ShouldNotAlmostEqual, 99.0, float32(0.1)))
-}
-
-func TestShouldResemble(t *testing.T) {
-	serializer = newFakeSerializer()
-
-	fail(t, so(Thing1{"hi"}, ShouldResemble), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"hi"}, Thing1{"hi"}), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	pass(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"hi"}))
-	fail(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"bye"}), "{bye}|{hi}|Expected: 'assertions.Thing1({a:bye})' Actual: 'assertions.Thing1({a:hi})' (Should resemble)!")
-}
-
-func TestShouldNotResemble(t *testing.T) {
-	fail(t, so(Thing1{"hi"}, ShouldNotResemble), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"hi"}, Thing1{"hi"}), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	pass(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"bye"}))
-	fail(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"hi"}),
-		"Expected 'assertions.Thing1({a:hi})' to NOT resemble 'assertions.Thing1({a:hi})' (but it did)!")
-
-	pass(t, so(map[string]string{"hi": "bye"}, ShouldResemble, map[string]string{"hi": "bye"}))
-	fail(t, so(StringStringMapAlias{"hi": "bye"}, ShouldResemble, map[string]string{"hi": "bye"}),
-		"map[hi:bye]|map[hi:bye]|Expected: 'map[string]string(map[hi:bye])' Actual: 'assertions.StringStringMapAlias(map[hi:bye])' (Should resemble)!")
-	pass(t, so(IntAlias(42), ShouldNotResemble, 42))
-	fail(t, so(IntAlias(42), ShouldResemble, 42), "42|42|Expected: 'int(42)' Actual: 'assertions.IntAlias(42)' (Should resemble)!")
-	fail(t, so(StringAlias("hi"), ShouldResemble, "hi"), "hi|hi|Expected: 'string(hi)' Actual: 'assertions.StringAlias(hi)' (Should resemble)!")
-
-	pass(t, so(StringSliceAlias{"hi", "bye"}, ShouldNotResemble, []string{"hi", "bye"}))
-	fail(t, so(StringSliceAlias{"hi", "bye"}, ShouldResemble, []string{"hi", "bye"}),
-		"[hi bye]|[hi bye]|Expected: '[]string([hi bye])' Actual: 'assertions.StringSliceAlias([hi bye])' (Should resemble)!")
-}
-
-func TestShouldPointTo(t *testing.T) {
-	serializer = newFakeSerializer()
-
-	t1 := &Thing1{}
-	t2 := t1
-	t3 := &Thing1{}
-
-	pointer1 := reflect.ValueOf(t1).Pointer()
-	pointer3 := reflect.ValueOf(t3).Pointer()
-
-	fail(t, so(t1, ShouldPointTo), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(t1, ShouldPointTo, t2, t3), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	pass(t, so(t1, ShouldPointTo, t2))
-	fail(t, so(t1, ShouldPointTo, t3), fmt.Sprintf(
-		"%v|%v|Expected '&{a:}' (address: '%v') and '&{a:}' (address: '%v') to be the same address (but their weren't)!",
-		pointer3, pointer1, pointer1, pointer3))
-
-	t4 := Thing1{}
-	t5 := t4
-
-	fail(t, so(t4, ShouldPointTo, t5), "Both arguments should be pointers (the first was not)!")
-	fail(t, so(&t4, ShouldPointTo, t5), "Both arguments should be pointers (the second was not)!")
-	fail(t, so(nil, ShouldPointTo, nil), "Both arguments should be pointers (the first was nil)!")
-	fail(t, so(&t4, ShouldPointTo, nil), "Both arguments should be pointers (the second was nil)!")
-}
-
-func TestShouldNotPointTo(t *testing.T) {
-	t1 := &Thing1{}
-	t2 := t1
-	t3 := &Thing1{}
-
-	pointer1 := reflect.ValueOf(t1).Pointer()
-
-	fail(t, so(t1, ShouldNotPointTo), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(t1, ShouldNotPointTo, t2, t3), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	pass(t, so(t1, ShouldNotPointTo, t3))
-	fail(t, so(t1, ShouldNotPointTo, t2), fmt.Sprintf("Expected '&{a:}' and '&{a:}' to be different references (but they matched: '%v')!", pointer1))
-
-	t4 := Thing1{}
-	t5 := t4
-
-	fail(t, so(t4, ShouldNotPointTo, t5), "Both arguments should be pointers (the first was not)!")
-	fail(t, so(&t4, ShouldNotPointTo, t5), "Both arguments should be pointers (the second was not)!")
-	fail(t, so(nil, ShouldNotPointTo, nil), "Both arguments should be pointers (the first was nil)!")
-	fail(t, so(&t4, ShouldNotPointTo, nil), "Both arguments should be pointers (the second was nil)!")
-}
-
-func TestShouldBeNil(t *testing.T) {
-	fail(t, so(nil, ShouldBeNil, nil, nil, nil), "This assertion requires exactly 0 comparison values (you provided 3).")
-	fail(t, so(nil, ShouldBeNil, nil), "This assertion requires exactly 0 comparison values (you provided 1).")
-
-	pass(t, so(nil, ShouldBeNil))
-	fail(t, so(1, ShouldBeNil), "Expected: nil Actual: '1'")
-
-	var thing Thinger
-	pass(t, so(thing, ShouldBeNil))
-	thing = &Thing{}
-	fail(t, so(thing, ShouldBeNil), "Expected: nil Actual: '&{}'")
-
-	var thingOne *Thing1
-	pass(t, so(thingOne, ShouldBeNil))
-
-	var nilSlice []int = nil
-	pass(t, so(nilSlice, ShouldBeNil))
-
-	var nilMap map[string]string = nil
-	pass(t, so(nilMap, ShouldBeNil))
-
-	var nilChannel chan int = nil
-	pass(t, so(nilChannel, ShouldBeNil))
-
-	var nilFunc func() = nil
-	pass(t, so(nilFunc, ShouldBeNil))
-
-	var nilInterface interface{} = nil
-	pass(t, so(nilInterface, ShouldBeNil))
-}
-
-func TestShouldNotBeNil(t *testing.T) {
-	fail(t, so(nil, ShouldNotBeNil, nil, nil, nil), "This assertion requires exactly 0 comparison values (you provided 3).")
-	fail(t, so(nil, ShouldNotBeNil, nil), "This assertion requires exactly 0 comparison values (you provided 1).")
-
-	fail(t, so(nil, ShouldNotBeNil), "Expected '<nil>' to NOT be nil (but it was)!")
-	pass(t, so(1, ShouldNotBeNil))
-
-	var thing Thinger
-	fail(t, so(thing, ShouldNotBeNil), "Expected '<nil>' to NOT be nil (but it was)!")
-	thing = &Thing{}
-	pass(t, so(thing, ShouldNotBeNil))
-}
-
-func TestShouldBeTrue(t *testing.T) {
-	fail(t, so(true, ShouldBeTrue, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).")
-	fail(t, so(true, ShouldBeTrue, 1), "This assertion requires exactly 0 comparison values (you provided 1).")
-
-	fail(t, so(false, ShouldBeTrue), "Expected: true Actual: false")
-	fail(t, so(1, ShouldBeTrue), "Expected: true Actual: 1")
-	pass(t, so(true, ShouldBeTrue))
-}
-
-func TestShouldBeFalse(t *testing.T) {
-	fail(t, so(false, ShouldBeFalse, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).")
-	fail(t, so(false, ShouldBeFalse, 1), "This assertion requires exactly 0 comparison values (you provided 1).")
-
-	fail(t, so(true, ShouldBeFalse), "Expected: false Actual: true")
-	fail(t, so(1, ShouldBeFalse), "Expected: false Actual: 1")
-	pass(t, so(false, ShouldBeFalse))
-}
-
-func TestShouldBeZeroValue(t *testing.T) {
-	serializer = newFakeSerializer()
-
-	fail(t, so(0, ShouldBeZeroValue, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).")
-	fail(t, so(false, ShouldBeZeroValue, true), "This assertion requires exactly 0 comparison values (you provided 1).")
-
-	fail(t, so(1, ShouldBeZeroValue), "0|1|'1' should have been the zero value")                                       //"Expected: (zero value) Actual: 1")
-	fail(t, so(true, ShouldBeZeroValue), "false|true|'true' should have been the zero value")                          //"Expected: (zero value) Actual: true")
-	fail(t, so("123", ShouldBeZeroValue), "|123|'123' should have been the zero value")                                //"Expected: (zero value) Actual: 123")
-	fail(t, so(" ", ShouldBeZeroValue), "| |' ' should have been the zero value")                                      //"Expected: (zero value) Actual:  ")
-	fail(t, so([]string{"Nonempty"}, ShouldBeZeroValue), "[]|[Nonempty]|'[Nonempty]' should have been the zero value") //"Expected: (zero value) Actual: [Nonempty]")
-	fail(t, so(struct{ a string }{a: "asdf"}, ShouldBeZeroValue), "{}|{asdf}|'{a:asdf}' should have been the zero value")
-	pass(t, so(0, ShouldBeZeroValue))
-	pass(t, so(false, ShouldBeZeroValue))
-	pass(t, so("", ShouldBeZeroValue))
-	pass(t, so(struct{}{}, ShouldBeZeroValue))
-}

+ 0 - 22
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/filter.go

@@ -1,22 +0,0 @@
-package assertions
-
-import "fmt"
-
-const (
-	success         = ""
-	needExactValues = "This assertion requires exactly %d comparison values (you provided %d)."
-)
-
-func need(needed int, expected []interface{}) string {
-	if len(expected) != needed {
-		return fmt.Sprintf(needExactValues, needed, len(expected))
-	}
-	return success
-}
-
-func atLeast(minimum int, expected []interface{}) string {
-	if len(expected) < 1 {
-		return shouldHaveProvidedCollectionMembers
-	}
-	return success
-}

+ 0 - 7
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/init.go

@@ -1,7 +0,0 @@
-package assertions
-
-var serializer Serializer
-
-func init() {
-	serializer = newSerializer()
-}

+ 0 - 86
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/messages.go

@@ -1,86 +0,0 @@
-package assertions
-
-const ( // equality
-	shouldHaveBeenEqual          = "Expected: '%v'\nActual:   '%v'\n(Should be equal)"
-	shouldNotHaveBeenEqual       = "Expected     '%v'\nto NOT equal '%v'\n(but it did)!"
-	shouldHaveBeenAlmostEqual    = "Expected '%v' to almost equal '%v' (but it didn't)!"
-	shouldHaveNotBeenAlmostEqual = "Expected '%v' to NOT almost equal '%v' (but it did)!"
-	shouldHaveResembled          = "Expected: '%T(%+v)'\nActual:   '%T(%+v)'\n(Should resemble)!"
-	shouldNotHaveResembled       = "Expected        '%T(%+v)'\nto NOT resemble '%T(%+v)'\n(but it did)!"
-	shouldBePointers             = "Both arguments should be pointers "
-	shouldHaveBeenNonNilPointer  = shouldBePointers + "(the %s was %s)!"
-	shouldHavePointedTo          = "Expected '%+v' (address: '%v') and '%+v' (address: '%v') to be the same address (but their weren't)!"
-	shouldNotHavePointedTo       = "Expected '%+v' and '%+v' to be different references (but they matched: '%v')!"
-	shouldHaveBeenNil            = "Expected: nil\nActual:   '%v'"
-	shouldNotHaveBeenNil         = "Expected '%+v' to NOT be nil (but it was)!"
-	shouldHaveBeenTrue           = "Expected: true\nActual:   %v"
-	shouldHaveBeenFalse          = "Expected: false\nActual:   %v"
-	shouldHaveBeenZeroValue      = "'%+v' should have been the zero value" //"Expected: (zero value)\nActual:   %v"
-)
-
-const ( // quantity comparisons
-	shouldHaveBeenGreater            = "Expected '%v' to be greater than '%v' (but it wasn't)!"
-	shouldHaveBeenGreaterOrEqual     = "Expected '%v' to be greater than or equal to '%v' (but it wasn't)!"
-	shouldHaveBeenLess               = "Expected '%v' to be less than '%v' (but it wasn't)!"
-	shouldHaveBeenLessOrEqual        = "Expected '%v' to be less than or equal to '%v' (but it wasn't)!"
-	shouldHaveBeenBetween            = "Expected '%v' to be between '%v' and '%v' (but it wasn't)!"
-	shouldNotHaveBeenBetween         = "Expected '%v' NOT to be between '%v' and '%v' (but it was)!"
-	shouldHaveDifferentUpperAndLower = "The lower and upper bounds must be different values (they were both '%v')."
-	shouldHaveBeenBetweenOrEqual     = "Expected '%v' to be between '%v' and '%v' or equal to one of them (but it wasn't)!"
-	shouldNotHaveBeenBetweenOrEqual  = "Expected '%v' NOT to be between '%v' and '%v' or equal to one of them (but it was)!"
-)
-
-const ( // collections
-	shouldHaveContained                 = "Expected the container (%v) to contain: '%v' (but it didn't)!"
-	shouldNotHaveContained              = "Expected the container (%v) NOT to contain: '%v' (but it did)!"
-	shouldHaveBeenIn                    = "Expected '%v' to be in the container (%v, but it wasn't)!"
-	shouldNotHaveBeenIn                 = "Expected '%v' NOT to be in the container (%v, but it was)!"
-	shouldHaveBeenAValidCollection      = "You must provide a valid container (was %v)!"
-	shouldHaveProvidedCollectionMembers = "This assertion requires at least 1 comparison value (you provided 0)."
-	shouldHaveBeenEmpty                 = "Expected %+v to be empty (but it wasn't)!"
-	shouldNotHaveBeenEmpty              = "Expected %+v to NOT be empty (but it was)!"
-)
-
-const ( // strings
-	shouldHaveStartedWith           = "Expected      '%v'\nto start with '%v'\n(but it didn't)!"
-	shouldNotHaveStartedWith        = "Expected          '%v'\nNOT to start with '%v'\n(but it did)!"
-	shouldHaveEndedWith             = "Expected    '%v'\nto end with '%v'\n(but it didn't)!"
-	shouldNotHaveEndedWith          = "Expected        '%v'\nNOT to end with '%v'\n(but it did)!"
-	shouldBothBeStrings             = "Both arguments to this assertion must be strings (you provided %v and %v)."
-	shouldBeString                  = "The argument to this assertion must be a string (you provided %v)."
-	shouldHaveContainedSubstring    = "Expected '%s' to contain substring '%s' (but it didn't)!"
-	shouldNotHaveContainedSubstring = "Expected '%s' NOT to contain substring '%s' (but it didn't)!"
-	shouldHaveBeenBlank             = "Expected '%s' to be blank (but it wasn't)!"
-	shouldNotHaveBeenBlank          = "Expected value to NOT be blank (but it was)!"
-)
-
-const ( // panics
-	shouldUseVoidNiladicFunction = "You must provide a void, niladic function as the first argument!"
-	shouldHavePanickedWith       = "Expected func() to panic with '%v' (but it panicked with '%v')!"
-	shouldHavePanicked           = "Expected func() to panic (but it didn't)!"
-	shouldNotHavePanicked        = "Expected func() NOT to panic (error: '%+v')!"
-	shouldNotHavePanickedWith    = "Expected func() NOT to panic with '%v' (but it did)!"
-)
-
-const ( // type checking
-	shouldHaveBeenA    = "Expected '%v' to be: '%v' (but was: '%v')!"
-	shouldNotHaveBeenA = "Expected '%v' to NOT be: '%v' (but it was)!"
-
-	shouldHaveImplemented             = "Expected: '%v interface support'\nActual:   '%v' does not implement the interface!"
-	shouldNotHaveImplemented          = "Expected         '%v'\nto NOT implement '%v'\n(but it did)!"
-	shouldCompareWithInterfacePointer = "The expected value must be a pointer to an interface type (eg. *fmt.Stringer)"
-	shouldNotBeNilActual              = "The actual value was 'nil' and should be a value or a pointer to a value!"
-)
-
-const ( // time comparisons
-	shouldUseTimes                   = "You must provide time instances as arguments to this assertion."
-	shouldUseTimeSlice               = "You must provide a slice of time instances as the first argument to this assertion."
-	shouldUseDurationAndTime         = "You must provide a duration and a time as arguments to this assertion."
-	shouldHaveHappenedBefore         = "Expected '%v' to happen before '%v' (it happened '%v' after)!"
-	shouldHaveHappenedAfter          = "Expected '%v' to happen after '%v' (it happened '%v' before)!"
-	shouldHaveHappenedBetween        = "Expected '%v' to happen between '%v' and '%v' (it happened '%v' outside threshold)!"
-	shouldNotHaveHappenedOnOrBetween = "Expected '%v' to NOT happen on or between '%v' and '%v' (but it did)!"
-
-	// format params: incorrect-index, previous-index, previous-time, incorrect-index, incorrect-time
-	shouldHaveBeenChronological = "The 'Time' at index [%d] should have happened after the previous one (but it didn't!):\n  [%d]: %s\n  [%d]: %s (see, it happened before!)"
-)

+ 0 - 115
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/panic.go

@@ -1,115 +0,0 @@
-package assertions
-
-import "fmt"
-
-// ShouldPanic receives a void, niladic function and expects to recover a panic.
-func ShouldPanic(actual interface{}, expected ...interface{}) (message string) {
-	if fail := need(0, expected); fail != success {
-		return fail
-	}
-
-	action, _ := actual.(func())
-
-	if action == nil {
-		message = shouldUseVoidNiladicFunction
-		return
-	}
-
-	defer func() {
-		recovered := recover()
-		if recovered == nil {
-			message = shouldHavePanicked
-		} else {
-			message = success
-		}
-	}()
-	action()
-
-	return
-}
-
-// ShouldNotPanic receives a void, niladic function and expects to execute the function without any panic.
-func ShouldNotPanic(actual interface{}, expected ...interface{}) (message string) {
-	if fail := need(0, expected); fail != success {
-		return fail
-	}
-
-	action, _ := actual.(func())
-
-	if action == nil {
-		message = shouldUseVoidNiladicFunction
-		return
-	}
-
-	defer func() {
-		recovered := recover()
-		if recovered != nil {
-			message = fmt.Sprintf(shouldNotHavePanicked, recovered)
-		} else {
-			message = success
-		}
-	}()
-	action()
-
-	return
-}
-
-// ShouldPanicWith receives a void, niladic function and expects to recover a panic with the second argument as the content.
-func ShouldPanicWith(actual interface{}, expected ...interface{}) (message string) {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	action, _ := actual.(func())
-
-	if action == nil {
-		message = shouldUseVoidNiladicFunction
-		return
-	}
-
-	defer func() {
-		recovered := recover()
-		if recovered == nil {
-			message = shouldHavePanicked
-		} else {
-			if equal := ShouldEqual(recovered, expected[0]); equal != success {
-				message = serializer.serialize(expected[0], recovered, fmt.Sprintf(shouldHavePanickedWith, expected[0], recovered))
-			} else {
-				message = success
-			}
-		}
-	}()
-	action()
-
-	return
-}
-
-// ShouldNotPanicWith receives a void, niladic function and expects to recover a panic whose content differs from the second argument.
-func ShouldNotPanicWith(actual interface{}, expected ...interface{}) (message string) {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	action, _ := actual.(func())
-
-	if action == nil {
-		message = shouldUseVoidNiladicFunction
-		return
-	}
-
-	defer func() {
-		recovered := recover()
-		if recovered == nil {
-			message = success
-		} else {
-			if equal := ShouldEqual(recovered, expected[0]); equal == success {
-				message = fmt.Sprintf(shouldNotHavePanickedWith, expected[0])
-			} else {
-				message = success
-			}
-		}
-	}()
-	action()
-
-	return
-}

+ 0 - 53
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/panic_test.go

@@ -1,53 +0,0 @@
-package assertions
-
-import (
-	"fmt"
-	"testing"
-)
-
-func TestShouldPanic(t *testing.T) {
-	fail(t, so(func() {}, ShouldPanic, 1), "This assertion requires exactly 0 comparison values (you provided 1).")
-	fail(t, so(func() {}, ShouldPanic, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).")
-
-	fail(t, so(1, ShouldPanic), shouldUseVoidNiladicFunction)
-	fail(t, so(func(i int) {}, ShouldPanic), shouldUseVoidNiladicFunction)
-	fail(t, so(func() int { panic("hi") }, ShouldPanic), shouldUseVoidNiladicFunction)
-
-	fail(t, so(func() {}, ShouldPanic), shouldHavePanicked)
-	pass(t, so(func() { panic("hi") }, ShouldPanic))
-}
-
-func TestShouldNotPanic(t *testing.T) {
-	fail(t, so(func() {}, ShouldNotPanic, 1), "This assertion requires exactly 0 comparison values (you provided 1).")
-	fail(t, so(func() {}, ShouldNotPanic, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).")
-
-	fail(t, so(1, ShouldNotPanic), shouldUseVoidNiladicFunction)
-	fail(t, so(func(i int) {}, ShouldNotPanic), shouldUseVoidNiladicFunction)
-
-	fail(t, so(func() { panic("hi") }, ShouldNotPanic), fmt.Sprintf(shouldNotHavePanicked, "hi"))
-	pass(t, so(func() {}, ShouldNotPanic))
-}
-
-func TestShouldPanicWith(t *testing.T) {
-	fail(t, so(func() {}, ShouldPanicWith), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(func() {}, ShouldPanicWith, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(1, ShouldPanicWith, 1), shouldUseVoidNiladicFunction)
-	fail(t, so(func(i int) {}, ShouldPanicWith, "hi"), shouldUseVoidNiladicFunction)
-	fail(t, so(func() {}, ShouldPanicWith, "bye"), shouldHavePanicked)
-	fail(t, so(func() { panic("hi") }, ShouldPanicWith, "bye"), "bye|hi|Expected func() to panic with 'bye' (but it panicked with 'hi')!")
-
-	pass(t, so(func() { panic("hi") }, ShouldPanicWith, "hi"))
-}
-
-func TestShouldNotPanicWith(t *testing.T) {
-	fail(t, so(func() {}, ShouldNotPanicWith), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(func() {}, ShouldNotPanicWith, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(1, ShouldNotPanicWith, 1), shouldUseVoidNiladicFunction)
-	fail(t, so(func(i int) {}, ShouldNotPanicWith, "hi"), shouldUseVoidNiladicFunction)
-	fail(t, so(func() { panic("hi") }, ShouldNotPanicWith, "hi"), "Expected func() NOT to panic with 'hi' (but it did)!")
-
-	pass(t, so(func() {}, ShouldNotPanicWith, "bye"))
-	pass(t, so(func() { panic("hi") }, ShouldNotPanicWith, "bye"))
-}

+ 0 - 141
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/quantity.go

@@ -1,141 +0,0 @@
-package assertions
-
-import (
-	"fmt"
-
-	"github.com/jacobsa/oglematchers"
-)
-
-// ShouldBeGreaterThan receives exactly two parameters and ensures that the first is greater than the second.
-func ShouldBeGreaterThan(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	if matchError := oglematchers.GreaterThan(expected[0]).Matches(actual); matchError != nil {
-		return fmt.Sprintf(shouldHaveBeenGreater, actual, expected[0])
-	}
-	return success
-}
-
-// ShouldBeGreaterThanOrEqualTo receives exactly two parameters and ensures that the first is greater than or equal to the second.
-func ShouldBeGreaterThanOrEqualTo(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	} else if matchError := oglematchers.GreaterOrEqual(expected[0]).Matches(actual); matchError != nil {
-		return fmt.Sprintf(shouldHaveBeenGreaterOrEqual, actual, expected[0])
-	}
-	return success
-}
-
-// ShouldBeLessThan receives exactly two parameters and ensures that the first is less than the second.
-func ShouldBeLessThan(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	} else if matchError := oglematchers.LessThan(expected[0]).Matches(actual); matchError != nil {
-		return fmt.Sprintf(shouldHaveBeenLess, actual, expected[0])
-	}
-	return success
-}
-
-// ShouldBeLessThan receives exactly two parameters and ensures that the first is less than or equal to the second.
-func ShouldBeLessThanOrEqualTo(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	} else if matchError := oglematchers.LessOrEqual(expected[0]).Matches(actual); matchError != nil {
-		return fmt.Sprintf(shouldHaveBeenLess, actual, expected[0])
-	}
-	return success
-}
-
-// ShouldBeBetween receives exactly three parameters: an actual value, a lower bound, and an upper bound.
-// It ensures that the actual value is between both bounds (but not equal to either of them).
-func ShouldBeBetween(actual interface{}, expected ...interface{}) string {
-	if fail := need(2, expected); fail != success {
-		return fail
-	}
-	lower, upper, fail := deriveBounds(expected)
-
-	if fail != success {
-		return fail
-	} else if !isBetween(actual, lower, upper) {
-		return fmt.Sprintf(shouldHaveBeenBetween, actual, lower, upper)
-	}
-	return success
-}
-
-// ShouldNotBeBetween receives exactly three parameters: an actual value, a lower bound, and an upper bound.
-// It ensures that the actual value is NOT between both bounds.
-func ShouldNotBeBetween(actual interface{}, expected ...interface{}) string {
-	if fail := need(2, expected); fail != success {
-		return fail
-	}
-	lower, upper, fail := deriveBounds(expected)
-
-	if fail != success {
-		return fail
-	} else if isBetween(actual, lower, upper) {
-		return fmt.Sprintf(shouldNotHaveBeenBetween, actual, lower, upper)
-	}
-	return success
-}
-func deriveBounds(values []interface{}) (lower interface{}, upper interface{}, fail string) {
-	lower = values[0]
-	upper = values[1]
-
-	if ShouldNotEqual(lower, upper) != success {
-		return nil, nil, fmt.Sprintf(shouldHaveDifferentUpperAndLower, lower)
-	} else if ShouldBeLessThan(lower, upper) != success {
-		lower, upper = upper, lower
-	}
-	return lower, upper, success
-}
-func isBetween(value, lower, upper interface{}) bool {
-	if ShouldBeGreaterThan(value, lower) != success {
-		return false
-	} else if ShouldBeLessThan(value, upper) != success {
-		return false
-	}
-	return true
-}
-
-// ShouldBeBetweenOrEqual receives exactly three parameters: an actual value, a lower bound, and an upper bound.
-// It ensures that the actual value is between both bounds or equal to one of them.
-func ShouldBeBetweenOrEqual(actual interface{}, expected ...interface{}) string {
-	if fail := need(2, expected); fail != success {
-		return fail
-	}
-	lower, upper, fail := deriveBounds(expected)
-
-	if fail != success {
-		return fail
-	} else if !isBetweenOrEqual(actual, lower, upper) {
-		return fmt.Sprintf(shouldHaveBeenBetweenOrEqual, actual, lower, upper)
-	}
-	return success
-}
-
-// ShouldNotBeBetweenOrEqual receives exactly three parameters: an actual value, a lower bound, and an upper bound.
-// It ensures that the actual value is nopt between the bounds nor equal to either of them.
-func ShouldNotBeBetweenOrEqual(actual interface{}, expected ...interface{}) string {
-	if fail := need(2, expected); fail != success {
-		return fail
-	}
-	lower, upper, fail := deriveBounds(expected)
-
-	if fail != success {
-		return fail
-	} else if isBetweenOrEqual(actual, lower, upper) {
-		return fmt.Sprintf(shouldNotHaveBeenBetweenOrEqual, actual, lower, upper)
-	}
-	return success
-}
-
-func isBetweenOrEqual(value, lower, upper interface{}) bool {
-	if ShouldBeGreaterThanOrEqualTo(value, lower) != success {
-		return false
-	} else if ShouldBeLessThanOrEqualTo(value, upper) != success {
-		return false
-	}
-	return true
-}

+ 0 - 145
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/quantity_test.go

@@ -1,145 +0,0 @@
-package assertions
-
-import "testing"
-
-func TestShouldBeGreaterThan(t *testing.T) {
-	fail(t, so(1, ShouldBeGreaterThan), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(1, ShouldBeGreaterThan, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	pass(t, so(1, ShouldBeGreaterThan, 0))
-	pass(t, so(1.1, ShouldBeGreaterThan, 1))
-	pass(t, so(1, ShouldBeGreaterThan, uint(0)))
-	pass(t, so("b", ShouldBeGreaterThan, "a"))
-
-	fail(t, so(0, ShouldBeGreaterThan, 1), "Expected '0' to be greater than '1' (but it wasn't)!")
-	fail(t, so(1, ShouldBeGreaterThan, 1.1), "Expected '1' to be greater than '1.1' (but it wasn't)!")
-	fail(t, so(uint(0), ShouldBeGreaterThan, 1.1), "Expected '0' to be greater than '1.1' (but it wasn't)!")
-	fail(t, so("a", ShouldBeGreaterThan, "b"), "Expected 'a' to be greater than 'b' (but it wasn't)!")
-}
-
-func TestShouldBeGreaterThanOrEqual(t *testing.T) {
-	fail(t, so(1, ShouldBeGreaterThanOrEqualTo), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(1, ShouldBeGreaterThanOrEqualTo, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	pass(t, so(1, ShouldBeGreaterThanOrEqualTo, 1))
-	pass(t, so(1.1, ShouldBeGreaterThanOrEqualTo, 1.1))
-	pass(t, so(1, ShouldBeGreaterThanOrEqualTo, uint(1)))
-	pass(t, so("b", ShouldBeGreaterThanOrEqualTo, "b"))
-
-	pass(t, so(1, ShouldBeGreaterThanOrEqualTo, 0))
-	pass(t, so(1.1, ShouldBeGreaterThanOrEqualTo, 1))
-	pass(t, so(1, ShouldBeGreaterThanOrEqualTo, uint(0)))
-	pass(t, so("b", ShouldBeGreaterThanOrEqualTo, "a"))
-
-	fail(t, so(0, ShouldBeGreaterThanOrEqualTo, 1), "Expected '0' to be greater than or equal to '1' (but it wasn't)!")
-	fail(t, so(1, ShouldBeGreaterThanOrEqualTo, 1.1), "Expected '1' to be greater than or equal to '1.1' (but it wasn't)!")
-	fail(t, so(uint(0), ShouldBeGreaterThanOrEqualTo, 1.1), "Expected '0' to be greater than or equal to '1.1' (but it wasn't)!")
-	fail(t, so("a", ShouldBeGreaterThanOrEqualTo, "b"), "Expected 'a' to be greater than or equal to 'b' (but it wasn't)!")
-}
-
-func TestShouldBeLessThan(t *testing.T) {
-	fail(t, so(1, ShouldBeLessThan), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(1, ShouldBeLessThan, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	pass(t, so(0, ShouldBeLessThan, 1))
-	pass(t, so(1, ShouldBeLessThan, 1.1))
-	pass(t, so(uint(0), ShouldBeLessThan, 1))
-	pass(t, so("a", ShouldBeLessThan, "b"))
-
-	fail(t, so(1, ShouldBeLessThan, 0), "Expected '1' to be less than '0' (but it wasn't)!")
-	fail(t, so(1.1, ShouldBeLessThan, 1), "Expected '1.1' to be less than '1' (but it wasn't)!")
-	fail(t, so(1.1, ShouldBeLessThan, uint(0)), "Expected '1.1' to be less than '0' (but it wasn't)!")
-	fail(t, so("b", ShouldBeLessThan, "a"), "Expected 'b' to be less than 'a' (but it wasn't)!")
-}
-
-func TestShouldBeLessThanOrEqualTo(t *testing.T) {
-	fail(t, so(1, ShouldBeLessThanOrEqualTo), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(1, ShouldBeLessThanOrEqualTo, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	pass(t, so(1, ShouldBeLessThanOrEqualTo, 1))
-	pass(t, so(1.1, ShouldBeLessThanOrEqualTo, 1.1))
-	pass(t, so(uint(1), ShouldBeLessThanOrEqualTo, 1))
-	pass(t, so("b", ShouldBeLessThanOrEqualTo, "b"))
-
-	pass(t, so(0, ShouldBeLessThanOrEqualTo, 1))
-	pass(t, so(1, ShouldBeLessThanOrEqualTo, 1.1))
-	pass(t, so(uint(0), ShouldBeLessThanOrEqualTo, 1))
-	pass(t, so("a", ShouldBeLessThanOrEqualTo, "b"))
-
-	fail(t, so(1, ShouldBeLessThanOrEqualTo, 0), "Expected '1' to be less than '0' (but it wasn't)!")
-	fail(t, so(1.1, ShouldBeLessThanOrEqualTo, 1), "Expected '1.1' to be less than '1' (but it wasn't)!")
-	fail(t, so(1.1, ShouldBeLessThanOrEqualTo, uint(0)), "Expected '1.1' to be less than '0' (but it wasn't)!")
-	fail(t, so("b", ShouldBeLessThanOrEqualTo, "a"), "Expected 'b' to be less than 'a' (but it wasn't)!")
-}
-
-func TestShouldBeBetween(t *testing.T) {
-	fail(t, so(1, ShouldBeBetween), "This assertion requires exactly 2 comparison values (you provided 0).")
-	fail(t, so(1, ShouldBeBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).")
-
-	fail(t, so(4, ShouldBeBetween, 1, 1), "The lower and upper bounds must be different values (they were both '1').")
-
-	fail(t, so(7, ShouldBeBetween, 8, 12), "Expected '7' to be between '8' and '12' (but it wasn't)!")
-	fail(t, so(8, ShouldBeBetween, 8, 12), "Expected '8' to be between '8' and '12' (but it wasn't)!")
-	pass(t, so(9, ShouldBeBetween, 8, 12))
-	pass(t, so(10, ShouldBeBetween, 8, 12))
-	pass(t, so(11, ShouldBeBetween, 8, 12))
-	fail(t, so(12, ShouldBeBetween, 8, 12), "Expected '12' to be between '8' and '12' (but it wasn't)!")
-	fail(t, so(13, ShouldBeBetween, 8, 12), "Expected '13' to be between '8' and '12' (but it wasn't)!")
-
-	pass(t, so(1, ShouldBeBetween, 2, 0))
-	fail(t, so(-1, ShouldBeBetween, 2, 0), "Expected '-1' to be between '0' and '2' (but it wasn't)!")
-}
-
-func TestShouldNotBeBetween(t *testing.T) {
-	fail(t, so(1, ShouldNotBeBetween), "This assertion requires exactly 2 comparison values (you provided 0).")
-	fail(t, so(1, ShouldNotBeBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).")
-
-	fail(t, so(4, ShouldNotBeBetween, 1, 1), "The lower and upper bounds must be different values (they were both '1').")
-
-	pass(t, so(7, ShouldNotBeBetween, 8, 12))
-	pass(t, so(8, ShouldNotBeBetween, 8, 12))
-	fail(t, so(9, ShouldNotBeBetween, 8, 12), "Expected '9' NOT to be between '8' and '12' (but it was)!")
-	fail(t, so(10, ShouldNotBeBetween, 8, 12), "Expected '10' NOT to be between '8' and '12' (but it was)!")
-	fail(t, so(11, ShouldNotBeBetween, 8, 12), "Expected '11' NOT to be between '8' and '12' (but it was)!")
-	pass(t, so(12, ShouldNotBeBetween, 8, 12))
-	pass(t, so(13, ShouldNotBeBetween, 8, 12))
-
-	pass(t, so(-1, ShouldNotBeBetween, 2, 0))
-	fail(t, so(1, ShouldNotBeBetween, 2, 0), "Expected '1' NOT to be between '0' and '2' (but it was)!")
-}
-
-func TestShouldBeBetweenOrEqual(t *testing.T) {
-	fail(t, so(1, ShouldBeBetweenOrEqual), "This assertion requires exactly 2 comparison values (you provided 0).")
-	fail(t, so(1, ShouldBeBetweenOrEqual, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).")
-
-	fail(t, so(4, ShouldBeBetweenOrEqual, 1, 1), "The lower and upper bounds must be different values (they were both '1').")
-
-	fail(t, so(7, ShouldBeBetweenOrEqual, 8, 12), "Expected '7' to be between '8' and '12' or equal to one of them (but it wasn't)!")
-	pass(t, so(8, ShouldBeBetweenOrEqual, 8, 12))
-	pass(t, so(9, ShouldBeBetweenOrEqual, 8, 12))
-	pass(t, so(10, ShouldBeBetweenOrEqual, 8, 12))
-	pass(t, so(11, ShouldBeBetweenOrEqual, 8, 12))
-	pass(t, so(12, ShouldBeBetweenOrEqual, 8, 12))
-	fail(t, so(13, ShouldBeBetweenOrEqual, 8, 12), "Expected '13' to be between '8' and '12' or equal to one of them (but it wasn't)!")
-
-	pass(t, so(1, ShouldBeBetweenOrEqual, 2, 0))
-	fail(t, so(-1, ShouldBeBetweenOrEqual, 2, 0), "Expected '-1' to be between '0' and '2' or equal to one of them (but it wasn't)!")
-}
-
-func TestShouldNotBeBetweenOrEqual(t *testing.T) {
-	fail(t, so(1, ShouldNotBeBetweenOrEqual), "This assertion requires exactly 2 comparison values (you provided 0).")
-	fail(t, so(1, ShouldNotBeBetweenOrEqual, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).")
-
-	fail(t, so(4, ShouldNotBeBetweenOrEqual, 1, 1), "The lower and upper bounds must be different values (they were both '1').")
-
-	pass(t, so(7, ShouldNotBeBetweenOrEqual, 8, 12))
-	fail(t, so(8, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '8' NOT to be between '8' and '12' or equal to one of them (but it was)!")
-	fail(t, so(9, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '9' NOT to be between '8' and '12' or equal to one of them (but it was)!")
-	fail(t, so(10, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '10' NOT to be between '8' and '12' or equal to one of them (but it was)!")
-	fail(t, so(11, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '11' NOT to be between '8' and '12' or equal to one of them (but it was)!")
-	fail(t, so(12, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '12' NOT to be between '8' and '12' or equal to one of them (but it was)!")
-	pass(t, so(13, ShouldNotBeBetweenOrEqual, 8, 12))
-
-	pass(t, so(-1, ShouldNotBeBetweenOrEqual, 2, 0))
-	fail(t, so(1, ShouldNotBeBetweenOrEqual, 2, 0), "Expected '1' NOT to be between '0' and '2' or equal to one of them (but it was)!")
-}

+ 0 - 31
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/serializer.go

@@ -1,31 +0,0 @@
-package assertions
-
-import (
-	"encoding/json"
-	"fmt"
-
-	"github.com/smartystreets/goconvey/convey/reporting"
-)
-
-type Serializer interface {
-	serialize(expected, actual interface{}, message string) string
-}
-
-type failureSerializer struct{}
-
-func (self *failureSerializer) serialize(expected, actual interface{}, message string) string {
-	view := reporting.FailureView{
-		Message:  message,
-		Expected: fmt.Sprintf("%+v", expected),
-		Actual:   fmt.Sprintf("%+v", actual),
-	}
-	serialized, err := json.Marshal(view)
-	if err != nil {
-		return message
-	}
-	return string(serialized)
-}
-
-func newSerializer() *failureSerializer {
-	return &failureSerializer{}
-}

+ 0 - 28
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/serializer_test.go

@@ -1,28 +0,0 @@
-package assertions
-
-import (
-	"encoding/json"
-	"fmt"
-	"testing"
-
-	"github.com/smartystreets/goconvey/convey/reporting"
-)
-
-func TestSerializerCreatesSerializedVersionOfAssertionResult(t *testing.T) {
-	thing1 := Thing1{"Hi"}
-	thing2 := Thing2{"Bye"}
-	message := "Super-hip failure message."
-	serializer := newSerializer()
-
-	actualResult := serializer.serialize(thing1, thing2, message)
-
-	expectedResult, _ := json.Marshal(reporting.FailureView{
-		Message:  message,
-		Expected: fmt.Sprintf("%+v", thing1),
-		Actual:   fmt.Sprintf("%+v", thing2),
-	})
-
-	if actualResult != string(expectedResult) {
-		t.Errorf("\nExpected: %s\nActual:   %s", string(expectedResult), actualResult)
-	}
-}

+ 0 - 183
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/strings.go

@@ -1,183 +0,0 @@
-package assertions
-
-import (
-	"fmt"
-	"reflect"
-	"strings"
-)
-
-// ShouldStartWith receives exactly 2 string parameters and ensures that the first starts with the second.
-func ShouldStartWith(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	value, valueIsString := actual.(string)
-	prefix, prefixIsString := expected[0].(string)
-
-	if !valueIsString || !prefixIsString {
-		return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0]))
-	}
-
-	return shouldStartWith(value, prefix)
-}
-func shouldStartWith(value, prefix string) string {
-	if !strings.HasPrefix(value, prefix) {
-		shortval := value
-		if len(shortval) > len(prefix) {
-			shortval = shortval[:len(prefix)] + "..."
-		}
-		return serializer.serialize(prefix, shortval, fmt.Sprintf(shouldHaveStartedWith, value, prefix))
-	}
-	return success
-}
-
-// ShouldNotStartWith receives exactly 2 string parameters and ensures that the first does not start with the second.
-func ShouldNotStartWith(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	value, valueIsString := actual.(string)
-	prefix, prefixIsString := expected[0].(string)
-
-	if !valueIsString || !prefixIsString {
-		return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0]))
-	}
-
-	return shouldNotStartWith(value, prefix)
-}
-func shouldNotStartWith(value, prefix string) string {
-	if strings.HasPrefix(value, prefix) {
-		if value == "" {
-			value = "<empty>"
-		}
-		if prefix == "" {
-			prefix = "<empty>"
-		}
-		return fmt.Sprintf(shouldNotHaveStartedWith, value, prefix)
-	}
-	return success
-}
-
-// ShouldEndWith receives exactly 2 string parameters and ensures that the first ends with the second.
-func ShouldEndWith(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	value, valueIsString := actual.(string)
-	suffix, suffixIsString := expected[0].(string)
-
-	if !valueIsString || !suffixIsString {
-		return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0]))
-	}
-
-	return shouldEndWith(value, suffix)
-}
-func shouldEndWith(value, suffix string) string {
-	if !strings.HasSuffix(value, suffix) {
-		shortval := value
-		if len(shortval) > len(suffix) {
-			shortval = "..." + shortval[len(shortval)-len(suffix):]
-		}
-		return serializer.serialize(suffix, shortval, fmt.Sprintf(shouldHaveEndedWith, value, suffix))
-	}
-	return success
-}
-
-// ShouldEndWith receives exactly 2 string parameters and ensures that the first does not end with the second.
-func ShouldNotEndWith(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	value, valueIsString := actual.(string)
-	suffix, suffixIsString := expected[0].(string)
-
-	if !valueIsString || !suffixIsString {
-		return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0]))
-	}
-
-	return shouldNotEndWith(value, suffix)
-}
-func shouldNotEndWith(value, suffix string) string {
-	if strings.HasSuffix(value, suffix) {
-		if value == "" {
-			value = "<empty>"
-		}
-		if suffix == "" {
-			suffix = "<empty>"
-		}
-		return fmt.Sprintf(shouldNotHaveEndedWith, value, suffix)
-	}
-	return success
-}
-
-// ShouldContainSubstring receives exactly 2 string parameters and ensures that the first contains the second as a substring.
-func ShouldContainSubstring(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	long, longOk := actual.(string)
-	short, shortOk := expected[0].(string)
-
-	if !longOk || !shortOk {
-		return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0]))
-	}
-
-	if !strings.Contains(long, short) {
-		return serializer.serialize(expected[0], actual, fmt.Sprintf(shouldHaveContainedSubstring, long, short))
-	}
-	return success
-}
-
-// ShouldNotContainSubstring receives exactly 2 string parameters and ensures that the first does NOT contain the second as a substring.
-func ShouldNotContainSubstring(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	long, longOk := actual.(string)
-	short, shortOk := expected[0].(string)
-
-	if !longOk || !shortOk {
-		return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0]))
-	}
-
-	if strings.Contains(long, short) {
-		return fmt.Sprintf(shouldNotHaveContainedSubstring, long, short)
-	}
-	return success
-}
-
-// ShouldBeBlank receives exactly 1 string parameter and ensures that it is equal to "".
-func ShouldBeBlank(actual interface{}, expected ...interface{}) string {
-	if fail := need(0, expected); fail != success {
-		return fail
-	}
-	value, ok := actual.(string)
-	if !ok {
-		return fmt.Sprintf(shouldBeString, reflect.TypeOf(actual))
-	}
-	if value != "" {
-		return serializer.serialize("", value, fmt.Sprintf(shouldHaveBeenBlank, value))
-	}
-	return success
-}
-
-// ShouldNotBeBlank receives exactly 1 string parameter and ensures that it is equal to "".
-func ShouldNotBeBlank(actual interface{}, expected ...interface{}) string {
-	if fail := need(0, expected); fail != success {
-		return fail
-	}
-	value, ok := actual.(string)
-	if !ok {
-		return fmt.Sprintf(shouldBeString, reflect.TypeOf(actual))
-	}
-	if value == "" {
-		return shouldNotHaveBeenBlank
-	}
-	return success
-}

+ 0 - 102
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/strings_test.go

@@ -1,102 +0,0 @@
-package assertions
-
-import "testing"
-
-func TestShouldStartWith(t *testing.T) {
-	serializer = newFakeSerializer()
-
-	fail(t, so("", ShouldStartWith), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so("", ShouldStartWith, "asdf", "asdf"), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	pass(t, so("", ShouldStartWith, ""))
-	fail(t, so("", ShouldStartWith, "x"), "x||Expected '' to start with 'x' (but it didn't)!")
-	pass(t, so("abc", ShouldStartWith, "abc"))
-	fail(t, so("abc", ShouldStartWith, "abcd"), "abcd|abc|Expected 'abc' to start with 'abcd' (but it didn't)!")
-
-	pass(t, so("superman", ShouldStartWith, "super"))
-	fail(t, so("superman", ShouldStartWith, "bat"), "bat|sup...|Expected 'superman' to start with 'bat' (but it didn't)!")
-	fail(t, so("superman", ShouldStartWith, "man"), "man|sup...|Expected 'superman' to start with 'man' (but it didn't)!")
-
-	fail(t, so(1, ShouldStartWith, 2), "Both arguments to this assertion must be strings (you provided int and int).")
-}
-
-func TestShouldNotStartWith(t *testing.T) {
-	fail(t, so("", ShouldNotStartWith), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so("", ShouldNotStartWith, "asdf", "asdf"), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	fail(t, so("", ShouldNotStartWith, ""), "Expected '<empty>' NOT to start with '<empty>' (but it did)!")
-	fail(t, so("superman", ShouldNotStartWith, "super"), "Expected 'superman' NOT to start with 'super' (but it did)!")
-	pass(t, so("superman", ShouldNotStartWith, "bat"))
-	pass(t, so("superman", ShouldNotStartWith, "man"))
-
-	fail(t, so(1, ShouldNotStartWith, 2), "Both arguments to this assertion must be strings (you provided int and int).")
-}
-
-func TestShouldEndWith(t *testing.T) {
-	serializer = newFakeSerializer()
-
-	fail(t, so("", ShouldEndWith), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so("", ShouldEndWith, "", ""), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	pass(t, so("", ShouldEndWith, ""))
-	fail(t, so("", ShouldEndWith, "z"), "z||Expected '' to end with 'z' (but it didn't)!")
-	pass(t, so("xyz", ShouldEndWith, "xyz"))
-	fail(t, so("xyz", ShouldEndWith, "wxyz"), "wxyz|xyz|Expected 'xyz' to end with 'wxyz' (but it didn't)!")
-
-	pass(t, so("superman", ShouldEndWith, "man"))
-	fail(t, so("superman", ShouldEndWith, "super"), "super|...erman|Expected 'superman' to end with 'super' (but it didn't)!")
-	fail(t, so("superman", ShouldEndWith, "blah"), "blah|...rman|Expected 'superman' to end with 'blah' (but it didn't)!")
-
-	fail(t, so(1, ShouldEndWith, 2), "Both arguments to this assertion must be strings (you provided int and int).")
-}
-
-func TestShouldNotEndWith(t *testing.T) {
-	fail(t, so("", ShouldNotEndWith), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so("", ShouldNotEndWith, "", ""), "This assertion requires exactly 1 comparison values (you provided 2).")
-
-	fail(t, so("", ShouldNotEndWith, ""), "Expected '<empty>' NOT to end with '<empty>' (but it did)!")
-	fail(t, so("superman", ShouldNotEndWith, "man"), "Expected 'superman' NOT to end with 'man' (but it did)!")
-	pass(t, so("superman", ShouldNotEndWith, "super"))
-
-	fail(t, so(1, ShouldNotEndWith, 2), "Both arguments to this assertion must be strings (you provided int and int).")
-}
-
-func TestShouldContainSubstring(t *testing.T) {
-	serializer = newFakeSerializer()
-
-	fail(t, so("asdf", ShouldContainSubstring), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so("asdf", ShouldContainSubstring, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(123, ShouldContainSubstring, 23), "Both arguments to this assertion must be strings (you provided int and int).")
-
-	pass(t, so("asdf", ShouldContainSubstring, "sd"))
-	fail(t, so("qwer", ShouldContainSubstring, "sd"), "sd|qwer|Expected 'qwer' to contain substring 'sd' (but it didn't)!")
-}
-
-func TestShouldNotContainSubstring(t *testing.T) {
-	fail(t, so("asdf", ShouldNotContainSubstring), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so("asdf", ShouldNotContainSubstring, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(123, ShouldNotContainSubstring, 23), "Both arguments to this assertion must be strings (you provided int and int).")
-
-	pass(t, so("qwer", ShouldNotContainSubstring, "sd"))
-	fail(t, so("asdf", ShouldNotContainSubstring, "sd"), "Expected 'asdf' NOT to contain substring 'sd' (but it didn't)!")
-}
-
-func TestShouldBeBlank(t *testing.T) {
-	serializer = newFakeSerializer()
-
-	fail(t, so("", ShouldBeBlank, "adsf"), "This assertion requires exactly 0 comparison values (you provided 1).")
-	fail(t, so(1, ShouldBeBlank), "The argument to this assertion must be a string (you provided int).")
-
-	fail(t, so("asdf", ShouldBeBlank), "|asdf|Expected 'asdf' to be blank (but it wasn't)!")
-	pass(t, so("", ShouldBeBlank))
-}
-
-func TestShouldNotBeBlank(t *testing.T) {
-	fail(t, so("", ShouldNotBeBlank, "adsf"), "This assertion requires exactly 0 comparison values (you provided 1).")
-	fail(t, so(1, ShouldNotBeBlank), "The argument to this assertion must be a string (you provided int).")
-
-	fail(t, so("", ShouldNotBeBlank), "Expected value to NOT be blank (but it was)!")
-	pass(t, so("asdf", ShouldNotBeBlank))
-}

+ 0 - 202
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/time.go

@@ -1,202 +0,0 @@
-package assertions
-
-import (
-	"fmt"
-	"time"
-)
-
-// ShouldHappenBefore receives exactly 2 time.Time arguments and asserts that the first happens before the second.
-func ShouldHappenBefore(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-	actualTime, firstOk := actual.(time.Time)
-	expectedTime, secondOk := expected[0].(time.Time)
-
-	if !firstOk || !secondOk {
-		return shouldUseTimes
-	}
-
-	if !actualTime.Before(expectedTime) {
-		return fmt.Sprintf(shouldHaveHappenedBefore, actualTime, expectedTime, actualTime.Sub(expectedTime))
-	}
-
-	return success
-}
-
-// ShouldHappenOnOrBefore receives exactly 2 time.Time arguments and asserts that the first happens on or before the second.
-func ShouldHappenOnOrBefore(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-	actualTime, firstOk := actual.(time.Time)
-	expectedTime, secondOk := expected[0].(time.Time)
-
-	if !firstOk || !secondOk {
-		return shouldUseTimes
-	}
-
-	if actualTime.Equal(expectedTime) {
-		return success
-	}
-	return ShouldHappenBefore(actualTime, expectedTime)
-}
-
-// ShouldHappenAfter receives exactly 2 time.Time arguments and asserts that the first happens after the second.
-func ShouldHappenAfter(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-	actualTime, firstOk := actual.(time.Time)
-	expectedTime, secondOk := expected[0].(time.Time)
-
-	if !firstOk || !secondOk {
-		return shouldUseTimes
-	}
-	if !actualTime.After(expectedTime) {
-		return fmt.Sprintf(shouldHaveHappenedAfter, actualTime, expectedTime, expectedTime.Sub(actualTime))
-	}
-	return success
-}
-
-// ShouldHappenOnOrAfter receives exactly 2 time.Time arguments and asserts that the first happens on or after the second.
-func ShouldHappenOnOrAfter(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-	actualTime, firstOk := actual.(time.Time)
-	expectedTime, secondOk := expected[0].(time.Time)
-
-	if !firstOk || !secondOk {
-		return shouldUseTimes
-	}
-	if actualTime.Equal(expectedTime) {
-		return success
-	}
-	return ShouldHappenAfter(actualTime, expectedTime)
-}
-
-// ShouldHappenBetween receives exactly 3 time.Time arguments and asserts that the first happens between (not on) the second and third.
-func ShouldHappenBetween(actual interface{}, expected ...interface{}) string {
-	if fail := need(2, expected); fail != success {
-		return fail
-	}
-	actualTime, firstOk := actual.(time.Time)
-	min, secondOk := expected[0].(time.Time)
-	max, thirdOk := expected[1].(time.Time)
-
-	if !firstOk || !secondOk || !thirdOk {
-		return shouldUseTimes
-	}
-
-	if !actualTime.After(min) {
-		return fmt.Sprintf(shouldHaveHappenedBetween, actualTime, min, max, min.Sub(actualTime))
-	}
-	if !actualTime.Before(max) {
-		return fmt.Sprintf(shouldHaveHappenedBetween, actualTime, min, max, actualTime.Sub(max))
-	}
-	return success
-}
-
-// ShouldHappenOnOrBetween receives exactly 3 time.Time arguments and asserts that the first happens between or on the second and third.
-func ShouldHappenOnOrBetween(actual interface{}, expected ...interface{}) string {
-	if fail := need(2, expected); fail != success {
-		return fail
-	}
-	actualTime, firstOk := actual.(time.Time)
-	min, secondOk := expected[0].(time.Time)
-	max, thirdOk := expected[1].(time.Time)
-
-	if !firstOk || !secondOk || !thirdOk {
-		return shouldUseTimes
-	}
-	if actualTime.Equal(min) || actualTime.Equal(max) {
-		return success
-	}
-	return ShouldHappenBetween(actualTime, min, max)
-}
-
-// ShouldNotHappenOnOrBetween receives exactly 3 time.Time arguments and asserts that the first
-// does NOT happen between or on the second or third.
-func ShouldNotHappenOnOrBetween(actual interface{}, expected ...interface{}) string {
-	if fail := need(2, expected); fail != success {
-		return fail
-	}
-	actualTime, firstOk := actual.(time.Time)
-	min, secondOk := expected[0].(time.Time)
-	max, thirdOk := expected[1].(time.Time)
-
-	if !firstOk || !secondOk || !thirdOk {
-		return shouldUseTimes
-	}
-	if actualTime.Equal(min) || actualTime.Equal(max) {
-		return fmt.Sprintf(shouldNotHaveHappenedOnOrBetween, actualTime, min, max)
-	}
-	if actualTime.After(min) && actualTime.Before(max) {
-		return fmt.Sprintf(shouldNotHaveHappenedOnOrBetween, actualTime, min, max)
-	}
-	return success
-}
-
-// ShouldHappenWithin receives a time.Time, a time.Duration, and a time.Time (3 arguments)
-// and asserts that the first time.Time happens within or on the duration specified relative to
-// the other time.Time.
-func ShouldHappenWithin(actual interface{}, expected ...interface{}) string {
-	if fail := need(2, expected); fail != success {
-		return fail
-	}
-	actualTime, firstOk := actual.(time.Time)
-	tolerance, secondOk := expected[0].(time.Duration)
-	threshold, thirdOk := expected[1].(time.Time)
-
-	if !firstOk || !secondOk || !thirdOk {
-		return shouldUseDurationAndTime
-	}
-
-	min := threshold.Add(-tolerance)
-	max := threshold.Add(tolerance)
-	return ShouldHappenOnOrBetween(actualTime, min, max)
-}
-
-// ShouldNotHappenWithin receives a time.Time, a time.Duration, and a time.Time (3 arguments)
-// and asserts that the first time.Time does NOT happen within or on the duration specified relative to
-// the other time.Time.
-func ShouldNotHappenWithin(actual interface{}, expected ...interface{}) string {
-	if fail := need(2, expected); fail != success {
-		return fail
-	}
-	actualTime, firstOk := actual.(time.Time)
-	tolerance, secondOk := expected[0].(time.Duration)
-	threshold, thirdOk := expected[1].(time.Time)
-
-	if !firstOk || !secondOk || !thirdOk {
-		return shouldUseDurationAndTime
-	}
-
-	min := threshold.Add(-tolerance)
-	max := threshold.Add(tolerance)
-	return ShouldNotHappenOnOrBetween(actualTime, min, max)
-}
-
-// ShouldBeChronological receives a []time.Time slice and asserts that the are
-// in chronological order starting with the first time.Time as the earliest.
-func ShouldBeChronological(actual interface{}, expected ...interface{}) string {
-	if fail := need(0, expected); fail != success {
-		return fail
-	}
-
-	times, ok := actual.([]time.Time)
-	if !ok {
-		return shouldUseTimeSlice
-	}
-
-	var previous time.Time
-	for i, current := range times {
-		if i > 0 && current.Before(previous) {
-			return fmt.Sprintf(shouldHaveBeenChronological,
-				i, i-1, previous.String(), i, current.String())
-		}
-		previous = current
-	}
-	return ""
-}

+ 0 - 159
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/time_test.go

@@ -1,159 +0,0 @@
-package assertions
-
-import (
-	"fmt"
-	"testing"
-	"time"
-)
-
-func TestShouldHappenBefore(t *testing.T) {
-	fail(t, so(0, ShouldHappenBefore), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(0, ShouldHappenBefore, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(0, ShouldHappenBefore, 1), shouldUseTimes)
-	fail(t, so(0, ShouldHappenBefore, time.Now()), shouldUseTimes)
-	fail(t, so(time.Now(), ShouldHappenBefore, 0), shouldUseTimes)
-
-	fail(t, so(january3, ShouldHappenBefore, january1), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '48h0m0s' after)!", pretty(january3), pretty(january1)))
-	fail(t, so(january3, ShouldHappenBefore, january3), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '0' after)!", pretty(january3), pretty(january3)))
-	pass(t, so(january1, ShouldHappenBefore, january3))
-}
-
-func TestShouldHappenOnOrBefore(t *testing.T) {
-	fail(t, so(0, ShouldHappenOnOrBefore), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(0, ShouldHappenOnOrBefore, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(0, ShouldHappenOnOrBefore, 1), shouldUseTimes)
-	fail(t, so(0, ShouldHappenOnOrBefore, time.Now()), shouldUseTimes)
-	fail(t, so(time.Now(), ShouldHappenOnOrBefore, 0), shouldUseTimes)
-
-	fail(t, so(january3, ShouldHappenOnOrBefore, january1), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '48h0m0s' after)!", pretty(january3), pretty(january1)))
-	pass(t, so(january3, ShouldHappenOnOrBefore, january3))
-	pass(t, so(january1, ShouldHappenOnOrBefore, january3))
-}
-
-func TestShouldHappenAfter(t *testing.T) {
-	fail(t, so(0, ShouldHappenAfter), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(0, ShouldHappenAfter, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(0, ShouldHappenAfter, 1), shouldUseTimes)
-	fail(t, so(0, ShouldHappenAfter, time.Now()), shouldUseTimes)
-	fail(t, so(time.Now(), ShouldHappenAfter, 0), shouldUseTimes)
-
-	fail(t, so(january1, ShouldHappenAfter, january2), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '24h0m0s' before)!", pretty(january1), pretty(january2)))
-	fail(t, so(january1, ShouldHappenAfter, january1), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '0' before)!", pretty(january1), pretty(january1)))
-	pass(t, so(january3, ShouldHappenAfter, january1))
-}
-
-func TestShouldHappenOnOrAfter(t *testing.T) {
-	fail(t, so(0, ShouldHappenOnOrAfter), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(0, ShouldHappenOnOrAfter, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(0, ShouldHappenOnOrAfter, 1), shouldUseTimes)
-	fail(t, so(0, ShouldHappenOnOrAfter, time.Now()), shouldUseTimes)
-	fail(t, so(time.Now(), ShouldHappenOnOrAfter, 0), shouldUseTimes)
-
-	fail(t, so(january1, ShouldHappenOnOrAfter, january2), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '24h0m0s' before)!", pretty(january1), pretty(january2)))
-	pass(t, so(january1, ShouldHappenOnOrAfter, january1))
-	pass(t, so(january3, ShouldHappenOnOrAfter, january1))
-}
-
-func TestShouldHappenBetween(t *testing.T) {
-	fail(t, so(0, ShouldHappenBetween), "This assertion requires exactly 2 comparison values (you provided 0).")
-	fail(t, so(0, ShouldHappenBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).")
-
-	fail(t, so(0, ShouldHappenBetween, 1, 2), shouldUseTimes)
-	fail(t, so(0, ShouldHappenBetween, time.Now(), time.Now()), shouldUseTimes)
-	fail(t, so(time.Now(), ShouldHappenBetween, 0, time.Now()), shouldUseTimes)
-	fail(t, so(time.Now(), ShouldHappenBetween, time.Now(), 9), shouldUseTimes)
-
-	fail(t, so(january1, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4)))
-	fail(t, so(january2, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '0' outside threshold)!", pretty(january2), pretty(january2), pretty(january4)))
-	pass(t, so(january3, ShouldHappenBetween, january2, january4))
-	fail(t, so(january4, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '0' outside threshold)!", pretty(january4), pretty(january2), pretty(january4)))
-	fail(t, so(january5, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4)))
-}
-
-func TestShouldHappenOnOrBetween(t *testing.T) {
-	fail(t, so(0, ShouldHappenOnOrBetween), "This assertion requires exactly 2 comparison values (you provided 0).")
-	fail(t, so(0, ShouldHappenOnOrBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).")
-
-	fail(t, so(0, ShouldHappenOnOrBetween, 1, time.Now()), shouldUseTimes)
-	fail(t, so(0, ShouldHappenOnOrBetween, time.Now(), 1), shouldUseTimes)
-	fail(t, so(time.Now(), ShouldHappenOnOrBetween, 0, 1), shouldUseTimes)
-
-	fail(t, so(january1, ShouldHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4)))
-	pass(t, so(january2, ShouldHappenOnOrBetween, january2, january4))
-	pass(t, so(january3, ShouldHappenOnOrBetween, january2, january4))
-	pass(t, so(january4, ShouldHappenOnOrBetween, january2, january4))
-	fail(t, so(january5, ShouldHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4)))
-}
-
-func TestShouldNotHappenOnOrBetween(t *testing.T) {
-	fail(t, so(0, ShouldNotHappenOnOrBetween), "This assertion requires exactly 2 comparison values (you provided 0).")
-	fail(t, so(0, ShouldNotHappenOnOrBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).")
-
-	fail(t, so(0, ShouldNotHappenOnOrBetween, 1, time.Now()), shouldUseTimes)
-	fail(t, so(0, ShouldNotHappenOnOrBetween, time.Now(), 1), shouldUseTimes)
-	fail(t, so(time.Now(), ShouldNotHappenOnOrBetween, 0, 1), shouldUseTimes)
-
-	pass(t, so(january1, ShouldNotHappenOnOrBetween, january2, january4))
-	fail(t, so(january2, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january2), pretty(january2), pretty(january4)))
-	fail(t, so(january3, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january3), pretty(january2), pretty(january4)))
-	fail(t, so(january4, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january4), pretty(january2), pretty(january4)))
-	pass(t, so(january5, ShouldNotHappenOnOrBetween, january2, january4))
-}
-
-func TestShouldHappenWithin(t *testing.T) {
-	fail(t, so(0, ShouldHappenWithin), "This assertion requires exactly 2 comparison values (you provided 0).")
-	fail(t, so(0, ShouldHappenWithin, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).")
-
-	fail(t, so(0, ShouldHappenWithin, 1, 2), shouldUseDurationAndTime)
-	fail(t, so(0, ShouldHappenWithin, oneDay, time.Now()), shouldUseDurationAndTime)
-	fail(t, so(time.Now(), ShouldHappenWithin, 0, time.Now()), shouldUseDurationAndTime)
-
-	fail(t, so(january1, ShouldHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4)))
-	pass(t, so(january2, ShouldHappenWithin, oneDay, january3))
-	pass(t, so(january3, ShouldHappenWithin, oneDay, january3))
-	pass(t, so(january4, ShouldHappenWithin, oneDay, january3))
-	fail(t, so(january5, ShouldHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4)))
-}
-
-func TestShouldNotHappenWithin(t *testing.T) {
-	fail(t, so(0, ShouldNotHappenWithin), "This assertion requires exactly 2 comparison values (you provided 0).")
-	fail(t, so(0, ShouldNotHappenWithin, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).")
-
-	fail(t, so(0, ShouldNotHappenWithin, 1, 2), shouldUseDurationAndTime)
-	fail(t, so(0, ShouldNotHappenWithin, oneDay, time.Now()), shouldUseDurationAndTime)
-	fail(t, so(time.Now(), ShouldNotHappenWithin, 0, time.Now()), shouldUseDurationAndTime)
-
-	pass(t, so(january1, ShouldNotHappenWithin, oneDay, january3))
-	fail(t, so(january2, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january2), pretty(january2), pretty(january4)))
-	fail(t, so(january3, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january3), pretty(january2), pretty(january4)))
-	fail(t, so(january4, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january4), pretty(january2), pretty(january4)))
-	pass(t, so(january5, ShouldNotHappenWithin, oneDay, january3))
-}
-
-func TestShouldBeChronological(t *testing.T) {
-	fail(t, so(0, ShouldBeChronological, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).")
-	fail(t, so(0, ShouldBeChronological), shouldUseTimeSlice)
-	fail(t, so([]time.Time{january5, january1}, ShouldBeChronological),
-		"The 'Time' at index [1] should have happened after the previous one (but it didn't!):\n  [0]: 2013-01-05 00:00:00 +0000 UTC\n  [1]: 2013-01-01 00:00:00 +0000 UTC (see, it happened before!)")
-
-	pass(t, so([]time.Time{january1, january2, january3, january4, january5}, ShouldBeChronological))
-}
-
-const layout = "2006-01-02 15:04"
-
-var january1, _ = time.Parse(layout, "2013-01-01 00:00")
-var january2, _ = time.Parse(layout, "2013-01-02 00:00")
-var january3, _ = time.Parse(layout, "2013-01-03 00:00")
-var january4, _ = time.Parse(layout, "2013-01-04 00:00")
-var january5, _ = time.Parse(layout, "2013-01-05 00:00")
-
-var oneDay, _ = time.ParseDuration("24h0m0s")
-var twoDays, _ = time.ParseDuration("48h0m0s")
-
-func pretty(t time.Time) string {
-	return fmt.Sprintf("%v", t)
-}

+ 0 - 112
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/type.go

@@ -1,112 +0,0 @@
-package assertions
-
-import (
-	"fmt"
-	"reflect"
-)
-
-// ShouldHaveSameTypeAs receives exactly two parameters and compares their underlying types for equality.
-func ShouldHaveSameTypeAs(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	first := reflect.TypeOf(actual)
-	second := reflect.TypeOf(expected[0])
-
-	if equal := ShouldEqual(first, second); equal != success {
-		return serializer.serialize(second, first, fmt.Sprintf(shouldHaveBeenA, actual, second, first))
-	}
-	return success
-}
-
-// ShouldNotHaveSameTypeAs receives exactly two parameters and compares their underlying types for inequality.
-func ShouldNotHaveSameTypeAs(actual interface{}, expected ...interface{}) string {
-	if fail := need(1, expected); fail != success {
-		return fail
-	}
-
-	first := reflect.TypeOf(actual)
-	second := reflect.TypeOf(expected[0])
-
-	if equal := ShouldEqual(first, second); equal == success {
-		return fmt.Sprintf(shouldNotHaveBeenA, actual, second)
-	}
-	return success
-}
-
-// ShouldImplement receives exactly two parameters and ensures
-// that the first implements the interface type of the second.
-func ShouldImplement(actual interface{}, expectedList ...interface{}) string {
-	if fail := need(1, expectedList); fail != success {
-		return fail
-	}
-
-	expected := expectedList[0]
-	if fail := ShouldBeNil(expected); fail != success {
-		return shouldCompareWithInterfacePointer
-	}
-
-	if fail := ShouldNotBeNil(actual); fail != success {
-		return shouldNotBeNilActual
-	}
-
-	var actualType reflect.Type
-	if reflect.TypeOf(actual).Kind() != reflect.Ptr {
-		actualType = reflect.PtrTo(reflect.TypeOf(actual))
-	} else {
-		actualType = reflect.TypeOf(actual)
-	}
-
-	expectedType := reflect.TypeOf(expected)
-	if fail := ShouldNotBeNil(expectedType); fail != success {
-		return shouldCompareWithInterfacePointer
-	}
-
-	expectedInterface := expectedType.Elem()
-
-	if actualType == nil {
-		return fmt.Sprintf(shouldHaveImplemented, expectedInterface, actual)
-	}
-
-	if !actualType.Implements(expectedInterface) {
-		return fmt.Sprintf(shouldHaveImplemented, expectedInterface, actualType)
-	}
-	return success
-}
-
-// ShouldNotImplement receives exactly two parameters and ensures
-// that the first does NOT implement the interface type of the second.
-func ShouldNotImplement(actual interface{}, expectedList ...interface{}) string {
-	if fail := need(1, expectedList); fail != success {
-		return fail
-	}
-
-	expected := expectedList[0]
-	if fail := ShouldBeNil(expected); fail != success {
-		return shouldCompareWithInterfacePointer
-	}
-
-	if fail := ShouldNotBeNil(actual); fail != success {
-		return shouldNotBeNilActual
-	}
-
-	var actualType reflect.Type
-	if reflect.TypeOf(actual).Kind() != reflect.Ptr {
-		actualType = reflect.PtrTo(reflect.TypeOf(actual))
-	} else {
-		actualType = reflect.TypeOf(actual)
-	}
-
-	expectedType := reflect.TypeOf(expected)
-	if fail := ShouldNotBeNil(expectedType); fail != success {
-		return shouldCompareWithInterfacePointer
-	}
-
-	expectedInterface := expectedType.Elem()
-
-	if actualType.Implements(expectedInterface) {
-		return fmt.Sprintf(shouldNotHaveImplemented, actualType, expectedInterface)
-	}
-	return success
-}

+ 0 - 76
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/type_test.go

@@ -1,76 +0,0 @@
-package assertions
-
-import (
-	"bytes"
-	"io"
-	"net/http"
-	"testing"
-)
-
-func TestShouldHaveSameTypeAs(t *testing.T) {
-	serializer = newFakeSerializer()
-
-	fail(t, so(1, ShouldHaveSameTypeAs), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(1, ShouldHaveSameTypeAs, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(nil, ShouldHaveSameTypeAs, 0), "int|<nil>|Expected '<nil>' to be: 'int' (but was: '<nil>')!")
-	fail(t, so(1, ShouldHaveSameTypeAs, "asdf"), "string|int|Expected '1' to be: 'string' (but was: 'int')!")
-
-	pass(t, so(1, ShouldHaveSameTypeAs, 0))
-	pass(t, so(nil, ShouldHaveSameTypeAs, nil))
-}
-
-func TestShouldNotHaveSameTypeAs(t *testing.T) {
-	fail(t, so(1, ShouldNotHaveSameTypeAs), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(1, ShouldNotHaveSameTypeAs, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(1, ShouldNotHaveSameTypeAs, 0), "Expected '1' to NOT be: 'int' (but it was)!")
-	fail(t, so(nil, ShouldNotHaveSameTypeAs, nil), "Expected '<nil>' to NOT be: '<nil>' (but it was)!")
-
-	pass(t, so(nil, ShouldNotHaveSameTypeAs, 0))
-	pass(t, so(1, ShouldNotHaveSameTypeAs, "asdf"))
-}
-
-func TestShouldImplement(t *testing.T) {
-	var ioReader *io.Reader = nil
-	var response http.Response = http.Response{}
-	var responsePtr *http.Response = new(http.Response)
-	var reader = bytes.NewBufferString("")
-
-	fail(t, so(reader, ShouldImplement), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(reader, ShouldImplement, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 2).")
-	fail(t, so(reader, ShouldImplement, ioReader, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(reader, ShouldImplement, "foo"), shouldCompareWithInterfacePointer)
-	fail(t, so(reader, ShouldImplement, 1), shouldCompareWithInterfacePointer)
-	fail(t, so(reader, ShouldImplement, nil), shouldCompareWithInterfacePointer)
-
-	fail(t, so(nil, ShouldImplement, ioReader), shouldNotBeNilActual)
-	fail(t, so(1, ShouldImplement, ioReader), "Expected: 'io.Reader interface support'\nActual:   '*int' does not implement the interface!")
-
-	fail(t, so(response, ShouldImplement, ioReader), "Expected: 'io.Reader interface support'\nActual:   '*http.Response' does not implement the interface!")
-	fail(t, so(responsePtr, ShouldImplement, ioReader), "Expected: 'io.Reader interface support'\nActual:   '*http.Response' does not implement the interface!")
-	pass(t, so(reader, ShouldImplement, ioReader))
-	pass(t, so(reader, ShouldImplement, (*io.Reader)(nil)))
-}
-
-func TestShouldNotImplement(t *testing.T) {
-	var ioReader *io.Reader = nil
-	var response http.Response = http.Response{}
-	var responsePtr *http.Response = new(http.Response)
-	var reader io.Reader = bytes.NewBufferString("")
-
-	fail(t, so(reader, ShouldNotImplement), "This assertion requires exactly 1 comparison values (you provided 0).")
-	fail(t, so(reader, ShouldNotImplement, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 2).")
-	fail(t, so(reader, ShouldNotImplement, ioReader, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 3).")
-
-	fail(t, so(reader, ShouldNotImplement, "foo"), shouldCompareWithInterfacePointer)
-	fail(t, so(reader, ShouldNotImplement, 1), shouldCompareWithInterfacePointer)
-	fail(t, so(reader, ShouldNotImplement, nil), shouldCompareWithInterfacePointer)
-
-	fail(t, so(reader, ShouldNotImplement, ioReader), "Expected         '*bytes.Buffer'\nto NOT implement   'io.Reader' (but it did)!")
-	fail(t, so(nil, ShouldNotImplement, ioReader), shouldNotBeNilActual)
-	pass(t, so(1, ShouldNotImplement, ioReader))
-	pass(t, so(response, ShouldNotImplement, ioReader))
-	pass(t, so(responsePtr, ShouldNotImplement, ioReader))
-}

+ 0 - 75
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/utilities_for_test.go

@@ -1,75 +0,0 @@
-package assertions
-
-import (
-	"fmt"
-	"path"
-	"runtime"
-	"strings"
-	"testing"
-)
-
-func pass(t *testing.T, result string) {
-	if result != success {
-		_, file, line, _ := runtime.Caller(1)
-		base := path.Base(file)
-		t.Errorf("Expectation should have passed but failed (see %s: line %d): '%s'", base, line, result)
-	}
-}
-
-func fail(t *testing.T, actual string, expected string) {
-	actual = format(actual)
-	expected = format(expected)
-
-	if actual != expected {
-		if actual == "" {
-			actual = "(empty)"
-		}
-		_, file, line, _ := runtime.Caller(1)
-		base := path.Base(file)
-		t.Errorf("Expectation should have failed but passed (see %s: line %d). \nExpected: %s\nActual:   %s\n",
-			base, line, expected, actual)
-	}
-}
-func format(message string) string {
-	message = strings.Replace(message, "\n", " ", -1)
-	for strings.Contains(message, "  ") {
-		message = strings.Replace(message, "  ", " ", -1)
-	}
-	return message
-}
-
-func so(actual interface{}, assert func(interface{}, ...interface{}) string, expected ...interface{}) string {
-	return assert(actual, expected...)
-}
-
-type Thing1 struct {
-	a string
-}
-type Thing2 struct {
-	a string
-}
-
-type Thinger interface {
-	Hi()
-}
-
-type Thing struct{}
-
-func (self *Thing) Hi() {}
-
-type IntAlias int
-type StringAlias string
-type StringSliceAlias []string
-type StringStringMapAlias map[string]string
-
-/******** FakeSerialzier ********/
-
-type fakeSerializer struct{}
-
-func (self *fakeSerializer) serialize(expected, actual interface{}, message string) string {
-	return fmt.Sprintf("%v|%v|%s", expected, actual, message)
-}
-
-func newFakeSerializer() *fakeSerializer {
-	return new(fakeSerializer)
-}

+ 0 - 179
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/context.go

@@ -1,179 +0,0 @@
-// Oh the stack trace scanning!
-// The density of comments in this file is evidence that
-// the code doesn't exactly explain itself. Tread with care...
-package convey
-
-import (
-	"errors"
-	"fmt"
-	"runtime"
-	"strconv"
-	"strings"
-	"sync"
-)
-
-const (
-	missingGoTest string = `Top-level calls to Convey(...) need a reference to the *testing.T. 
-		Hint: Convey("description here", t, func() { /* notice that the second argument was the *testing.T (t)! */ }) `
-	extraGoTest string = `Only the top-level call to Convey(...) needs a reference to the *testing.T.`
-)
-
-// suiteContext magically handles all coordination of reporter, runners as they handle calls
-// to Convey, So, and the like. It does this via runtime call stack inspection, making sure
-// that each test function has its own runner, and routes all live registrations
-// to the appropriate runner.
-type suiteContext struct {
-	lock    sync.Mutex
-	runners map[string]*runner // key: testName;
-
-	// stores a correlation to the actual runner for outside-of-stack scenaios
-	locations map[string]string // key: file:line; value: testName (key to runners)
-}
-
-func (self *suiteContext) Run(entry *registration) {
-	if self.current() != nil {
-		panic(extraGoTest)
-	}
-
-	runner := newRunner(buildReporter())
-
-	testName, location, _ := suiteAnchor()
-
-	self.setRunner(location, testName, runner)
-
-	runner.Run(entry)
-
-	self.unsetRunner(location, testName)
-}
-
-func (self *suiteContext) Current() *runner {
-	if runner := self.current(); runner != nil {
-		return runner
-	}
-	panic(missingGoTest)
-}
-func (self *suiteContext) current() *runner {
-	self.lock.Lock()
-	defer self.lock.Unlock()
-
-	if testName, _, err := suiteAnchor(); err == nil {
-		return self.runners[testName]
-	}
-
-	return self.runners[correlate(self.locations)]
-}
-func (self *suiteContext) setRunner(location string, testName string, runner *runner) {
-	self.lock.Lock()
-	defer self.lock.Unlock()
-
-	self.locations[location] = testName
-	self.runners[testName] = runner
-}
-func (self *suiteContext) unsetRunner(location string, testName string) {
-	self.lock.Lock()
-	defer self.lock.Unlock()
-
-	delete(self.locations, location)
-	delete(self.runners, testName)
-}
-
-func newSuiteContext() *suiteContext {
-	return &suiteContext{
-		locations: map[string]string{},
-		runners:   map[string]*runner{},
-	}
-}
-
-//////////////////// Helper Functions ///////////////////////
-
-// suiteAnchor returns the enclosing test function name (including package) and the
-// file:line combination of the top-level Convey. It does this by traversing the
-// call stack in reverse, looking for the go testing harnass call ("testing.tRunner")
-// and then grabs the very next entry.
-func suiteAnchor() (testName, location string, err error) {
-	callers := runtime.Callers(0, callStack)
-
-	for y := callers; y > 0; y-- {
-		callerId, file, conveyLine, found := runtime.Caller(y)
-		if !found {
-			continue
-		}
-
-		if name := runtime.FuncForPC(callerId).Name(); name != goTestHarness {
-			continue
-		}
-
-		callerId, file, conveyLine, _ = runtime.Caller(y - 1)
-		testName = runtime.FuncForPC(callerId).Name()
-		location = fmt.Sprintf("%s:%d", file, conveyLine)
-		return
-	}
-	return "", "", errors.New("Can't resolve test method name! Are you calling Convey() from a `*_test.go` file and a `Test*` method (because you should be)?")
-}
-
-// correlate links the current stack with the appropriate
-// top-level Convey by comparing line numbers in its own stack trace
-// with the registered file:line combo. It's come to this.
-func correlate(locations map[string]string) (testName string) {
-	file, line := resolveTestFileAndLine()
-	closest := -1
-
-	for location, registeredTestName := range locations {
-		locationFile, rawLocationLine := splitFileAndLine(location)
-
-		if locationFile != file {
-			continue
-		}
-
-		locationLine, err := strconv.Atoi(rawLocationLine)
-		if err != nil || locationLine < line {
-			continue
-		}
-
-		if closest == -1 || locationLine < closest {
-			closest = locationLine
-			testName = registeredTestName
-		}
-	}
-	return
-}
-
-// splitFileAndLine receives a path and a line number in a single string,
-// separated by a colon and splits them.
-func splitFileAndLine(value string) (file, line string) {
-	parts := strings.Split(value, ":")
-	if len(parts) == 2 {
-		file = parts[0]
-		line = parts[1]
-	} else if len(parts) > 2 {
-		// 'C:/blah.go:123' (windows drive letter has two colons
-		// '-:--------:---'  instead of just one to separate file and line)
-		file = strings.Join(parts[:2], ":")
-		line = parts[2]
-	}
-	return
-}
-
-// resolveTestFileAndLine is used as a last-ditch effort to correlate an
-// assertion with the right executor and runner.
-func resolveTestFileAndLine() (file string, line int) {
-	callers := runtime.Callers(0, callStack)
-	var found bool
-
-	for y := callers; y > 0; y-- {
-		_, file, line, found = runtime.Caller(y)
-		if !found {
-			continue
-		}
-
-		if strings.HasSuffix(file, "_test.go") {
-			return
-		}
-	}
-	return "", 0
-}
-
-const maxStackDepth = 100               // This had better be enough...
-const goTestHarness = "testing.tRunner" // I hope this doesn't change...
-
-var callStack []uintptr = make([]uintptr, maxStackDepth, maxStackDepth)

+ 0 - 57
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/discovery.go

@@ -1,57 +0,0 @@
-package convey
-
-func discover(items []interface{}) *registration {
-	name, items := parseName(items)
-	test, items := parseGoTest(items)
-	action, items := parseAction(items)
-
-	if len(items) != 0 {
-		panic(parseError)
-	}
-
-	return newRegistration(name, action, test)
-}
-func item(items []interface{}) interface{} {
-	if len(items) == 0 {
-		panic(parseError)
-	}
-	return items[0]
-}
-func parseName(items []interface{}) (string, []interface{}) {
-	if name, parsed := item(items).(string); parsed {
-		return name, items[1:]
-	}
-	panic(parseError)
-}
-func parseGoTest(items []interface{}) (t, []interface{}) {
-	if test, parsed := item(items).(t); parsed {
-		return test, items[1:]
-	}
-	return nil, items
-}
-func parseFailureMode(items []interface{}) (FailureMode, []interface{}) {
-	if mode, parsed := item(items).(FailureMode); parsed {
-		return mode, items[1:]
-	}
-	return FailureInherits, items
-}
-func parseAction(items []interface{}) (*action, []interface{}) {
-	failure, items := parseFailureMode(items)
-
-	if action, parsed := item(items).(func()); parsed {
-		return newAction(action, failure), items[1:]
-	}
-	if item(items) == nil {
-		return newSkippedAction(skipReport, failure), items[1:]
-	}
-	panic(parseError)
-}
-
-// This interface allows us to pass the *testing.T struct
-// throughout the internals of this tool without ever
-// having to import the "testing" package.
-type t interface {
-	Fail()
-}
-
-const parseError = "You must provide a name (string), then a *testing.T (if in outermost scope), an optional FailureMode, and then an action (func())."

+ 0 - 178
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/doc.go

@@ -1,178 +0,0 @@
-// Package convey contains all of the public-facing entry points to this project.
-// This means that it should never be required of the user to import any other
-// packages from this project as they serve internal purposes.
-package convey
-
-import (
-	"fmt"
-
-	"github.com/smartystreets/goconvey/convey/reporting"
-)
-
-////////////////////////////////// Registration //////////////////////////////////
-
-// Convey is the method intended for use when declaring the scopes
-// of a specification. Each scope has a description and a func()
-// which may contain other calls to Convey(), Reset() or Should-style
-// assertions. Convey calls can be nested as far as you see fit.
-//
-// IMPORTANT NOTE: The top-level Convey() within a Test method
-// must conform to the following signature:
-//
-//     Convey(description string, t *testing.T, action func())
-//
-// All other calls should like like this (no need to pass in *testing.T):
-//
-//     Convey(description string, action func())
-//
-// Don't worry, the goconvey will panic if you get it wrong so you can fix it.
-//
-// All Convey()-blocks also take an optional parameter of FailureMode which
-// sets how goconvey should treat failures for So()-assertions in the block and
-// nested blocks. See the constants in this file for the available options.
-//
-// By default it will inherit from its parent block and the top-level blocks
-// start with setting of FailureHalts.
-//
-// This parameter is inserted before the block itself:
-//
-//     Convey(description string, t *testing.T, mode FailureMode, action func())
-//     Convey(description string, mode FailureMode, action func())
-//
-// See the examples package for, well, examples.
-func Convey(items ...interface{}) {
-	register(discover(items))
-}
-
-// SkipConvey is analagous to Convey except that the scope is not executed
-// (which means that child scopes defined within this scope are not run either).
-// The reporter will be notified that this step was skipped.
-func SkipConvey(items ...interface{}) {
-	entry := discover(items)
-	entry.action = newSkippedAction(skipReport, entry.action.failureMode)
-
-	register(entry)
-}
-
-// FocusConvey is has the inverse effect of SkipConvey. If the top-level
-// Convey is changed to `FocusConvey`, only nested scopes that are defined
-// with FocusConvey will be run. The rest will be ignored completely. This
-// is handy when debugging a large suite that runs a misbehaving function
-// repeatedly as you can disable all but one of that function
-// without swaths of `SkipConvey` calls, just a targeted chain of calls
-// to FocusConvey.
-func FocusConvey(items ...interface{}) {
-	entry := discover(items)
-	entry.Focus = true
-
-	register(entry)
-}
-
-func register(entry *registration) {
-	if entry.ShouldBeTopLevel() {
-		suites.Run(entry)
-	} else {
-		suites.Current().Register(entry)
-	}
-}
-
-func skipReport() {
-	suites.Current().Report(reporting.NewSkipReport())
-}
-
-// Reset registers a cleanup function to be run after each Convey()
-// in the same scope. See the examples package for a simple use case.
-func Reset(action func()) {
-	/* TODO: Failure mode configuration */
-	suites.Current().RegisterReset(newAction(action, FailureInherits))
-}
-
-/////////////////////////////////// Assertions ///////////////////////////////////
-
-// assertion is an alias for a function with a signature that the convey.So()
-// method can handle. Any future or custom assertions should conform to this
-// method signature. The return value should be an empty string if the assertion
-// passes and a well-formed failure message if not.
-type assertion func(actual interface{}, expected ...interface{}) string
-
-const assertionSuccess = ""
-
-// So is the means by which assertions are made against the system under test.
-// The majority of exported names in the assertions package begin with the word
-// 'Should' and describe how the first argument (actual) should compare with any
-// of the final (expected) arguments. How many final arguments are accepted
-// depends on the particular assertion that is passed in as the assert argument.
-// See the examples package for use cases and the assertions package for
-// documentation on specific assertion methods.
-func So(actual interface{}, assert assertion, expected ...interface{}) {
-	if result := assert(actual, expected...); result == assertionSuccess {
-		suites.Current().Report(reporting.NewSuccessReport())
-	} else {
-		suites.Current().Report(reporting.NewFailureReport(result))
-	}
-}
-
-// SkipSo is analagous to So except that the assertion that would have been passed
-// to So is not executed and the reporter is notified that the assertion was skipped.
-func SkipSo(stuff ...interface{}) {
-	skipReport()
-}
-
-// FailureMode is a type which determines how the So() blocks should fail
-// if their assertion fails. See constants further down for acceptable values
-type FailureMode string
-
-const (
-
-	// FailureContinues is a failure mode which prevents failing
-	// So()-assertions from halting Convey-block execution, instead
-	// allowing the test to continue past failing So()-assertions.
-	FailureContinues FailureMode = "continue"
-
-	// FailureHalts is the default setting for a top-level Convey()-block
-	// and will cause all failing So()-assertions to halt further execution
-	// in that test-arm and continue on to the next arm.
-	FailureHalts FailureMode = "halt"
-
-	// FailureInherits is the default setting for failure-mode, it will
-	// default to the failure-mode of the parent block. You should never
-	// need to specify this mode in your tests..
-	FailureInherits FailureMode = "inherits"
-)
-
-var defaultFailureMode FailureMode = FailureHalts
-
-// SetDefaultFailureMode allows you to specify the default failure mode
-// for all Convey blocks. It is meant to be used in an init function to
-// allow the default mode to be changd across all tests for an entire packgae
-// but it can be used anywhere.
-func SetDefaultFailureMode(mode FailureMode) {
-	if mode == FailureContinues || mode == FailureHalts {
-		defaultFailureMode = mode
-	} else {
-		panic("You may only use the constants named 'FailureContinues' and 'FailureHalts' as default failure modes.")
-	}
-}
-
-//////////////////////////////////// Print functions ////////////////////////////////////
-
-// Print is analogous to fmt.Print (and it even calls fmt.Print). It ensures that
-// output is aligned with the corresponding scopes in the web UI.
-func Print(items ...interface{}) (written int, err error) {
-	fmt.Fprint(suites.Current(), items...)
-	return fmt.Print(items...)
-}
-
-// Print is analogous to fmt.Println (and it even calls fmt.Println). It ensures that
-// output is aligned with the corresponding scopes in the web UI.
-func Println(items ...interface{}) (written int, err error) {
-	fmt.Fprintln(suites.Current(), items...)
-	return fmt.Println(items...)
-}
-
-// Print is analogous to fmt.Printf (and it even calls fmt.Printf). It ensures that
-// output is aligned with the corresponding scopes in the web UI.
-func Printf(format string, items ...interface{}) (written int, err error) {
-	fmt.Fprintf(suites.Current(), format, items...)
-	return fmt.Printf(format, items...)
-}

+ 0 - 72
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/focused_execution_test.go

@@ -1,72 +0,0 @@
-package convey
-
-import "testing"
-
-func TestFocusOnlyAtTopLevel(t *testing.T) {
-	output := prepare()
-
-	FocusConvey("hi", t, func() {
-		output += "done"
-	})
-
-	expectEqual(t, "done", output)
-}
-
-func TestFocus(t *testing.T) {
-	output := prepare()
-
-	FocusConvey("hi", t, func() {
-		output += "1"
-
-		Convey("bye", func() {
-			output += "2"
-		})
-	})
-
-	expectEqual(t, "1", output)
-}
-
-func TestNestedFocus(t *testing.T) {
-	output := prepare()
-
-	FocusConvey("hi", t, func() {
-		output += "1"
-
-		Convey("This shouldn't run", func() {
-			output += "boink!"
-		})
-
-		FocusConvey("This should run", func() {
-			output += "2"
-
-			FocusConvey("The should run too", func() {
-				output += "3"
-
-			})
-
-			Convey("The should NOT run", func() {
-				output += "blah blah blah!"
-			})
-		})
-	})
-
-	expectEqual(t, "123", output)
-}
-
-func TestForgotTopLevelFocus(t *testing.T) {
-	output := prepare()
-
-	Convey("1", t, func() {
-		output += "1"
-
-		FocusConvey("This will be run because the top-level lacks Focus", func() {
-			output += "2"
-		})
-
-		Convey("3", func() {
-			output += "3"
-		})
-	})
-
-	expectEqual(t, "1213", output)
-}

+ 0 - 37
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/gotest/utils.go

@@ -1,37 +0,0 @@
-// Package gotest contains internal functionality. Although this package
-// contains one or more exported names it is not intended for public
-// consumption. See the examples package for how to use this project.
-package gotest
-
-import (
-	"fmt"
-	"runtime"
-	"strings"
-)
-
-func FormatExternalFileAndLine() string {
-	file, line, _ := ResolveExternalCaller()
-	if line == -1 {
-		return "<unknown caller!>" // panic?
-	}
-	return fmt.Sprintf("%s:%d", file, line)
-}
-
-func ResolveExternalCaller() (file string, line int, name string) {
-	var caller_id uintptr
-	callers := runtime.Callers(0, callStack)
-
-	for x := 0; x < callers; x++ {
-		caller_id, file, line, _ = runtime.Caller(x)
-		if strings.HasSuffix(file, "_test.go") {
-			name = runtime.FuncForPC(caller_id).Name()
-			return
-		}
-	}
-	file, line, name = "<unkown file>", -1, "<unknown name>"
-	return // panic?
-}
-
-const maxStackDepth = 100 // This had better be enough...
-
-var callStack []uintptr = make([]uintptr, maxStackDepth, maxStackDepth)

+ 0 - 72
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/init.go

@@ -1,72 +0,0 @@
-package convey
-
-import (
-	"flag"
-	"os"
-
-	"github.com/smartystreets/goconvey/convey/reporting"
-)
-
-func init() {
-	declareFlags()
-
-	suites = newSuiteContext()
-}
-
-func declareFlags() {
-	flag.BoolVar(&json, "json", false, "When true, emits results in JSON blocks. Default: 'false'")
-	flag.BoolVar(&silent, "silent", false, "When true, all output from GoConvey is suppressed.")
-	flag.BoolVar(&story, "story", false, "When true, emits story output, otherwise emits dot output. When not provided, this flag mirros the value of the '-test.v' flag")
-
-	if noStoryFlagProvided() {
-		story = verboseEnabled
-	}
-
-	// FYI: flag.Parse() is called from the testing package.
-}
-
-func noStoryFlagProvided() bool {
-	return !story && !storyDisabled
-}
-
-func buildReporter() reporting.Reporter {
-	switch {
-	case testReporter != nil:
-		return testReporter
-	case json:
-		return reporting.BuildJsonReporter()
-	case silent:
-		return reporting.BuildSilentReporter()
-	case story:
-		return reporting.BuildStoryReporter()
-	default:
-		return reporting.BuildDotReporter()
-	}
-}
-
-var (
-	suites *suiteContext
-
-	// only set by internal tests
-	testReporter reporting.Reporter
-)
-
-var (
-	json   bool
-	silent bool
-	story  bool
-
-	verboseEnabled = flagFound("-test.v=true")
-	storyDisabled  = flagFound("-story=false")
-)
-
-// flagFound parses the command line args manually for flags defined in other
-// packages. Like the '-v' flag from the "testing" package, for instance.
-func flagFound(flagValue string) bool {
-	for _, arg := range os.Args {
-		if arg == flagValue {
-			return true
-		}
-	}
-	return false
-}

+ 0 - 742
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/isolated_execution_test.go

@@ -1,742 +0,0 @@
-package convey
-
-import (
-	"strconv"
-	"testing"
-	"time"
-)
-
-func TestSingleScope(t *testing.T) {
-	output := prepare()
-
-	Convey("hi", t, func() {
-		output += "done"
-	})
-
-	expectEqual(t, "done", output)
-}
-
-func TestSingleScopeWithMultipleConveys(t *testing.T) {
-	output := prepare()
-
-	Convey("1", t, func() {
-		output += "1"
-	})
-
-	Convey("2", t, func() {
-		output += "2"
-	})
-
-	expectEqual(t, "12", output)
-}
-
-func TestNestedScopes(t *testing.T) {
-	output := prepare()
-
-	Convey("a", t, func() {
-		output += "a "
-
-		Convey("bb", func() {
-			output += "bb "
-
-			Convey("ccc", func() {
-				output += "ccc | "
-			})
-		})
-	})
-
-	expectEqual(t, "a bb ccc | ", output)
-}
-
-func TestNestedScopesWithIsolatedExecution(t *testing.T) {
-	output := prepare()
-
-	Convey("a", t, func() {
-		output += "a "
-
-		Convey("aa", func() {
-			output += "aa "
-
-			Convey("aaa", func() {
-				output += "aaa | "
-			})
-
-			Convey("aaa1", func() {
-				output += "aaa1 | "
-			})
-		})
-
-		Convey("ab", func() {
-			output += "ab "
-
-			Convey("abb", func() {
-				output += "abb | "
-			})
-		})
-	})
-
-	expectEqual(t, "a aa aaa | a aa aaa1 | a ab abb | ", output)
-}
-
-func TestSingleScopeWithConveyAndNestedReset(t *testing.T) {
-	output := prepare()
-
-	Convey("1", t, func() {
-		output += "1"
-
-		Reset(func() {
-			output += "a"
-		})
-	})
-
-	expectEqual(t, "1a", output)
-}
-
-func TestSingleScopeWithMultipleRegistrationsAndReset(t *testing.T) {
-	output := prepare()
-
-	Convey("reset after each nested convey", t, func() {
-		Convey("first output", func() {
-			output += "1"
-		})
-
-		Convey("second output", func() {
-			output += "2"
-		})
-
-		Reset(func() {
-			output += "a"
-		})
-	})
-
-	expectEqual(t, "1a2a", output)
-}
-
-func TestSingleScopeWithMultipleRegistrationsAndMultipleResets(t *testing.T) {
-	output := prepare()
-
-	Convey("each reset is run at end of each nested convey", t, func() {
-		Convey("1", func() {
-			output += "1"
-		})
-
-		Convey("2", func() {
-			output += "2"
-		})
-
-		Reset(func() {
-			output += "a"
-		})
-
-		Reset(func() {
-			output += "b"
-		})
-	})
-
-	expectEqual(t, "1ab2ab", output)
-}
-
-func Test_Failure_AtHigherLevelScopePreventsChildScopesFromRunning(t *testing.T) {
-	output := prepare()
-
-	Convey("This step fails", t, func() {
-		So(1, ShouldEqual, 2)
-
-		Convey("this should NOT be executed", func() {
-			output += "a"
-		})
-	})
-
-	expectEqual(t, "", output)
-}
-
-func Test_Panic_AtHigherLevelScopePreventsChildScopesFromRunning(t *testing.T) {
-	output := prepare()
-
-	Convey("This step panics", t, func() {
-		Convey("this should NOT be executed", func() {
-			output += "1"
-		})
-
-		panic("Hi")
-	})
-
-	expectEqual(t, "", output)
-}
-
-func Test_Panic_InChildScopeDoes_NOT_PreventExecutionOfSiblingScopes(t *testing.T) {
-	output := prepare()
-
-	Convey("This is the parent", t, func() {
-		Convey("This step panics", func() {
-			panic("Hi")
-			output += "1"
-		})
-
-		Convey("This sibling should execute", func() {
-			output += "2"
-		})
-	})
-
-	expectEqual(t, "2", output)
-}
-
-func Test_Failure_InChildScopeDoes_NOT_PreventExecutionOfSiblingScopes(t *testing.T) {
-	output := prepare()
-
-	Convey("This is the parent", t, func() {
-		Convey("This step fails", func() {
-			So(1, ShouldEqual, 2)
-			output += "1"
-		})
-
-		Convey("This sibling should execute", func() {
-			output += "2"
-		})
-	})
-
-	expectEqual(t, "2", output)
-}
-
-func TestResetsAreAlwaysExecutedAfterScope_Panics(t *testing.T) {
-	output := prepare()
-
-	Convey("This is the parent", t, func() {
-		Convey("This step panics", func() {
-			panic("Hi")
-			output += "1"
-		})
-
-		Convey("This sibling step does not panic", func() {
-			output += "a"
-
-			Reset(func() {
-				output += "b"
-			})
-		})
-
-		Reset(func() {
-			output += "2"
-		})
-	})
-
-	expectEqual(t, "2ab2", output)
-}
-
-func TestResetsAreAlwaysExecutedAfterScope_Failures(t *testing.T) {
-	output := prepare()
-
-	Convey("This is the parent", t, func() {
-		Convey("This step fails", func() {
-			So(1, ShouldEqual, 2)
-			output += "1"
-		})
-
-		Convey("This sibling step does not fail", func() {
-			output += "a"
-
-			Reset(func() {
-				output += "b"
-			})
-		})
-
-		Reset(func() {
-			output += "2"
-		})
-	})
-
-	expectEqual(t, "2ab2", output)
-}
-
-func TestSkipTopLevel(t *testing.T) {
-	output := prepare()
-
-	SkipConvey("hi", t, func() {
-		output += "This shouldn't be executed!"
-	})
-
-	expectEqual(t, "", output)
-}
-
-func TestSkipNestedLevel(t *testing.T) {
-	output := prepare()
-
-	Convey("hi", t, func() {
-		output += "yes"
-
-		SkipConvey("bye", func() {
-			output += "no"
-		})
-	})
-
-	expectEqual(t, "yes", output)
-}
-
-func TestSkipNestedLevelSkipsAllChildLevels(t *testing.T) {
-	output := prepare()
-
-	Convey("hi", t, func() {
-		output += "yes"
-
-		SkipConvey("bye", func() {
-			output += "no"
-
-			Convey("byebye", func() {
-				output += "no-no"
-			})
-		})
-	})
-
-	expectEqual(t, "yes", output)
-}
-
-func TestIterativeConveys(t *testing.T) {
-	output := prepare()
-
-	Convey("Test", t, func() {
-		for x := 0; x < 10; x++ {
-			y := strconv.Itoa(x)
-
-			Convey(y, func() {
-				output += y
-			})
-		}
-	})
-
-	expectEqual(t, "0123456789", output)
-}
-
-func TestClosureVariables(t *testing.T) {
-	output := prepare()
-
-	i := 0
-
-	Convey("A", t, func() {
-		i = i + 1
-		j := i
-
-		output += "A" + strconv.Itoa(i) + " "
-
-		Convey("B", func() {
-			k := j
-			j = j + 1
-
-			output += "B" + strconv.Itoa(k) + " "
-
-			Convey("C", func() {
-				output += "C" + strconv.Itoa(k) + strconv.Itoa(j) + " "
-			})
-
-			Convey("D", func() {
-				output += "D" + strconv.Itoa(k) + strconv.Itoa(j) + " "
-			})
-		})
-
-		Convey("C", func() {
-			output += "C" + strconv.Itoa(j) + " "
-		})
-	})
-
-	output += "D" + strconv.Itoa(i) + " "
-
-	expectEqual(t, "A1 B1 C12 A2 B2 D23 A3 C3 D3 ", output)
-}
-
-func TestClosureVariablesWithReset(t *testing.T) {
-	output := prepare()
-
-	i := 0
-
-	Convey("A", t, func() {
-		i = i + 1
-		j := i
-
-		output += "A" + strconv.Itoa(i) + " "
-
-		Reset(func() {
-			output += "R" + strconv.Itoa(i) + strconv.Itoa(j) + " "
-		})
-
-		Convey("B", func() {
-			output += "B" + strconv.Itoa(j) + " "
-		})
-
-		Convey("C", func() {
-			output += "C" + strconv.Itoa(j) + " "
-		})
-	})
-
-	output += "D" + strconv.Itoa(i) + " "
-
-	expectEqual(t, "A1 B1 R11 A2 C2 R22 D2 ", output)
-}
-
-func TestWrappedSimple(t *testing.T) {
-	prepare()
-	output := resetTestString{""}
-
-	Convey("A", t, func() {
-		func() {
-			output.output += "A "
-
-			Convey("B", func() {
-				output.output += "B "
-
-				Convey("C", func() {
-					output.output += "C "
-				})
-
-			})
-
-			Convey("D", func() {
-				output.output += "D "
-			})
-		}()
-	})
-
-	expectEqual(t, "A B C A D ", output.output)
-}
-
-type resetTestString struct {
-	output string
-}
-
-func addReset(o *resetTestString, f func()) func() {
-	return func() {
-		Reset(func() {
-			o.output += "R "
-		})
-
-		f()
-	}
-}
-
-func TestWrappedReset(t *testing.T) {
-	prepare()
-	output := resetTestString{""}
-
-	Convey("A", t, addReset(&output, func() {
-		output.output += "A "
-
-		Convey("B", func() {
-			output.output += "B "
-		})
-
-		Convey("C", func() {
-			output.output += "C "
-		})
-	}))
-
-	expectEqual(t, "A B R A C R ", output.output)
-}
-
-func TestWrappedReset2(t *testing.T) {
-	prepare()
-	output := resetTestString{""}
-
-	Convey("A", t, func() {
-		Reset(func() {
-			output.output += "R "
-		})
-
-		func() {
-			output.output += "A "
-
-			Convey("B", func() {
-				output.output += "B "
-
-				Convey("C", func() {
-					output.output += "C "
-				})
-			})
-
-			Convey("D", func() {
-				output.output += "D "
-			})
-		}()
-	})
-
-	expectEqual(t, "A B C R A D R ", output.output)
-}
-
-func TestInfiniteLoopWithTrailingFail(t *testing.T) {
-	done := make(chan int)
-
-	go func() {
-		Convey("This fails", t, func() {
-			Convey("and this is run", func() {
-				So(true, ShouldEqual, true)
-			})
-
-			/* And this prevents the whole block to be marked as run */
-			So(false, ShouldEqual, true)
-		})
-
-		done <- 1
-	}()
-
-	select {
-	case <-done:
-		return
-	case <-time.After(1 * time.Millisecond):
-		t.Fail()
-	}
-}
-
-func TestOutermostResetInvokedForGrandchildren(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, func() {
-		output += "A "
-
-		Reset(func() {
-			output += "rA "
-		})
-
-		Convey("B", func() {
-			output += "B "
-
-			Reset(func() {
-				output += "rB "
-			})
-
-			Convey("C", func() {
-				output += "C "
-
-				Reset(func() {
-					output += "rC "
-				})
-			})
-
-			Convey("D", func() {
-				output += "D "
-
-				Reset(func() {
-					output += "rD "
-				})
-			})
-		})
-	})
-
-	expectEqual(t, "A B C rC rB rA A B D rD rB rA ", output)
-}
-
-func TestFailureOption(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, FailureHalts, func() {
-		output += "A "
-		So(true, ShouldEqual, true)
-		output += "B "
-		So(false, ShouldEqual, true)
-		output += "C "
-	})
-
-	expectEqual(t, "A B ", output)
-}
-
-func TestFailureOption2(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, func() {
-		output += "A "
-		So(true, ShouldEqual, true)
-		output += "B "
-		So(false, ShouldEqual, true)
-		output += "C "
-	})
-
-	expectEqual(t, "A B ", output)
-}
-
-func TestFailureOption3(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, FailureContinues, func() {
-		output += "A "
-		So(true, ShouldEqual, true)
-		output += "B "
-		So(false, ShouldEqual, true)
-		output += "C "
-	})
-
-	expectEqual(t, "A B C ", output)
-}
-
-func TestFailureOptionInherit(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, FailureContinues, func() {
-		output += "A1 "
-		So(false, ShouldEqual, true)
-		output += "A2 "
-
-		Convey("B", func() {
-			output += "B1 "
-			So(true, ShouldEqual, true)
-			output += "B2 "
-			So(false, ShouldEqual, true)
-			output += "B3 "
-		})
-	})
-
-	expectEqual(t, "A1 A2 B1 B2 B3 ", output)
-}
-
-func TestFailureOptionInherit2(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, FailureHalts, func() {
-		output += "A1 "
-		So(false, ShouldEqual, true)
-		output += "A2 "
-
-		Convey("B", func() {
-			output += "A1 "
-			So(true, ShouldEqual, true)
-			output += "A2 "
-			So(false, ShouldEqual, true)
-			output += "A3 "
-		})
-	})
-
-	expectEqual(t, "A1 ", output)
-}
-
-func TestFailureOptionInherit3(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, FailureHalts, func() {
-		output += "A1 "
-		So(true, ShouldEqual, true)
-		output += "A2 "
-
-		Convey("B", func() {
-			output += "B1 "
-			So(true, ShouldEqual, true)
-			output += "B2 "
-			So(false, ShouldEqual, true)
-			output += "B3 "
-		})
-	})
-
-	expectEqual(t, "A1 A2 B1 B2 ", output)
-}
-
-func TestFailureOptionNestedOverride(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, FailureContinues, func() {
-		output += "A "
-		So(false, ShouldEqual, true)
-		output += "B "
-
-		Convey("C", FailureHalts, func() {
-			output += "C "
-			So(true, ShouldEqual, true)
-			output += "D "
-			So(false, ShouldEqual, true)
-			output += "E "
-		})
-	})
-
-	expectEqual(t, "A B C D ", output)
-}
-
-func TestFailureOptionNestedOverride2(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, FailureHalts, func() {
-		output += "A "
-		So(true, ShouldEqual, true)
-		output += "B "
-
-		Convey("C", FailureContinues, func() {
-			output += "C "
-			So(true, ShouldEqual, true)
-			output += "D "
-			So(false, ShouldEqual, true)
-			output += "E "
-		})
-	})
-
-	expectEqual(t, "A B C D E ", output)
-}
-
-func TestMultipleInvocationInheritance(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, FailureHalts, func() {
-		output += "A1 "
-		So(true, ShouldEqual, true)
-		output += "A2 "
-
-		Convey("B", FailureContinues, func() {
-			output += "B1 "
-			So(true, ShouldEqual, true)
-			output += "B2 "
-			So(false, ShouldEqual, true)
-			output += "B3 "
-		})
-
-		Convey("C", func() {
-			output += "C1 "
-			So(true, ShouldEqual, true)
-			output += "C2 "
-			So(false, ShouldEqual, true)
-			output += "C3 "
-		})
-	})
-
-	expectEqual(t, "A1 A2 B1 B2 B3 A1 A2 C1 C2 ", output)
-}
-
-func TestMultipleInvocationInheritance2(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, FailureContinues, func() {
-		output += "A1 "
-		So(true, ShouldEqual, true)
-		output += "A2 "
-		So(false, ShouldEqual, true)
-		output += "A3 "
-
-		Convey("B", FailureHalts, func() {
-			output += "B1 "
-			So(true, ShouldEqual, true)
-			output += "B2 "
-			So(false, ShouldEqual, true)
-			output += "B3 "
-		})
-
-		Convey("C", func() {
-			output += "C1 "
-			So(true, ShouldEqual, true)
-			output += "C2 "
-			So(false, ShouldEqual, true)
-			output += "C3 "
-		})
-	})
-
-	expectEqual(t, "A1 A2 A3 B1 B2 A1 A2 A3 C1 C2 C3 ", output)
-}
-
-func TestSetDefaultFailureMode(t *testing.T) {
-	output := prepare()
-
-	SetDefaultFailureMode(FailureContinues) // the default is normally FailureHalts
-	defer SetDefaultFailureMode(FailureHalts)
-
-	Convey("A", t, func() {
-		output += "A1 "
-		So(true, ShouldBeFalse)
-		output += "A2 "
-	})
-
-	expectEqual(t, "A1 A2 ", output)
-}
-
-func prepare() string {
-	testReporter = newNilReporter()
-	return ""
-}

+ 0 - 74
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/registration.go

@@ -1,74 +0,0 @@
-package convey
-
-import (
-	"reflect"
-	"runtime"
-
-	"github.com/smartystreets/goconvey/convey/gotest"
-)
-
-type registration struct {
-	Situation string
-	action    *action
-	Test      t
-	File      string
-	Line      int
-	Focus     bool
-}
-
-func (self *registration) ShouldBeTopLevel() bool {
-	return self.Test != nil
-}
-
-func newRegistration(situation string, action *action, test t) *registration {
-	file, line, _ := gotest.ResolveExternalCaller()
-
-	return &registration{
-		Situation: situation,
-		action:    action,
-		Test:      test,
-		File:      file,
-		Line:      line,
-	}
-}
-
-////////////////////////// action ///////////////////////
-
-type action struct {
-	wrapped     func()
-	name        string
-	failureMode FailureMode
-}
-
-func (self *action) Invoke() {
-	self.wrapped()
-}
-
-func newAction(wrapped func(), mode FailureMode) *action {
-	return &action{
-		name:        functionName(wrapped),
-		wrapped:     wrapped,
-		failureMode: mode,
-	}
-}
-
-func newSkippedAction(wrapped func(), mode FailureMode) *action {
-	// The choice to use the filename and line number as the action name
-	// reflects the need for something unique but also that corresponds
-	// in a determinist way to the action itself.
-	return &action{
-		name:        gotest.FormatExternalFileAndLine(),
-		wrapped:     wrapped,
-		failureMode: mode,
-	}
-}
-
-///////////////////////// helpers //////////////////////////////
-
-func functionName(action func()) string {
-	return runtime.FuncForPC(functionId(action)).Name()
-}
-
-func functionId(action func()) uintptr {
-	return reflect.ValueOf(action).Pointer()
-}

+ 0 - 16
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/console.go

@@ -1,16 +0,0 @@
-package reporting
-
-import (
-	"fmt"
-	"io"
-)
-
-type console struct{}
-
-func (self *console) Write(p []byte) (n int, err error) {
-	return fmt.Print(string(p))
-}
-
-func NewConsole() io.Writer {
-	return new(console)
-}

+ 0 - 5
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/doc.go

@@ -1,5 +0,0 @@
-// Package reporting contains internal functionality related
-// to console reporting and output. Although this package has
-// exported names is not intended for public consumption. See the
-// examples package for how to use this project.
-package reporting

+ 0 - 40
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/dot.go

@@ -1,40 +0,0 @@
-package reporting
-
-import "fmt"
-
-type dot struct{ out *Printer }
-
-func (self *dot) BeginStory(story *StoryReport) {}
-
-func (self *dot) Enter(scope *ScopeReport) {}
-
-func (self *dot) Report(report *AssertionResult) {
-	if report.Error != nil {
-		fmt.Print(redColor)
-		self.out.Insert(dotError)
-	} else if report.Failure != "" {
-		fmt.Print(yellowColor)
-		self.out.Insert(dotFailure)
-	} else if report.Skipped {
-		fmt.Print(yellowColor)
-		self.out.Insert(dotSkip)
-	} else {
-		fmt.Print(greenColor)
-		self.out.Insert(dotSuccess)
-	}
-	fmt.Print(resetColor)
-}
-
-func (self *dot) Exit() {}
-
-func (self *dot) EndStory() {}
-
-func (self *dot) Write(content []byte) (written int, err error) {
-	return len(content), nil // no-op
-}
-
-func NewDotReporter(out *Printer) *dot {
-	self := new(dot)
-	self.out = out
-	return self
-}

+ 0 - 40
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/dot_test.go

@@ -1,40 +0,0 @@
-package reporting
-
-import (
-	"errors"
-	"testing"
-)
-
-func TestDotReporterAssertionPrinting(t *testing.T) {
-	monochrome()
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	reporter := NewDotReporter(printer)
-
-	reporter.Report(NewSuccessReport())
-	reporter.Report(NewFailureReport("failed"))
-	reporter.Report(NewErrorReport(errors.New("error")))
-	reporter.Report(NewSkipReport())
-
-	expected := dotSuccess + dotFailure + dotError + dotSkip
-
-	if file.buffer != expected {
-		t.Errorf("\nExpected: '%s'\nActual:  '%s'", expected, file.buffer)
-	}
-}
-
-func TestDotReporterOnlyReportsAssertions(t *testing.T) {
-	monochrome()
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	reporter := NewDotReporter(printer)
-
-	reporter.BeginStory(nil)
-	reporter.Enter(nil)
-	reporter.Exit()
-	reporter.EndStory()
-
-	if file.buffer != "" {
-		t.Errorf("\nExpected: '(blank)'\nActual:  '%s'", file.buffer)
-	}
-}

+ 0 - 33
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/gotest.go

@@ -1,33 +0,0 @@
-package reporting
-
-type gotestReporter struct{ test T }
-
-func (self *gotestReporter) BeginStory(story *StoryReport) {
-	self.test = story.Test
-}
-
-func (self *gotestReporter) Enter(scope *ScopeReport) {}
-
-func (self *gotestReporter) Report(r *AssertionResult) {
-	if !passed(r) {
-		self.test.Fail()
-	}
-}
-
-func (self *gotestReporter) Exit() {}
-
-func (self *gotestReporter) EndStory() {
-	self.test = nil
-}
-
-func (self *gotestReporter) Write(content []byte) (written int, err error) {
-	return len(content), nil // no-op
-}
-
-func NewGoTestReporter() *gotestReporter {
-	return new(gotestReporter)
-}
-
-func passed(r *AssertionResult) bool {
-	return r.Error == nil && r.Failure == ""
-}

+ 0 - 66
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/gotest_test.go

@@ -1,66 +0,0 @@
-package reporting
-
-import "testing"
-
-func TestReporterReceivesSuccessfulReport(t *testing.T) {
-	reporter := NewGoTestReporter()
-	test := new(fakeTest)
-	reporter.BeginStory(NewStoryReport(test))
-	reporter.Report(NewSuccessReport())
-
-	if test.failed {
-		t.Errorf("Should have have marked test as failed--the report reflected success.")
-	}
-}
-
-func TestReporterReceivesFailureReport(t *testing.T) {
-	reporter := NewGoTestReporter()
-	test := new(fakeTest)
-	reporter.BeginStory(NewStoryReport(test))
-	reporter.Report(NewFailureReport("This is a failure."))
-
-	if !test.failed {
-		t.Errorf("Test should have been marked as failed (but it wasn't).")
-	}
-}
-
-func TestReporterReceivesErrorReport(t *testing.T) {
-	reporter := NewGoTestReporter()
-	test := new(fakeTest)
-	reporter.BeginStory(NewStoryReport(test))
-	reporter.Report(NewErrorReport("This is an error."))
-
-	if !test.failed {
-		t.Errorf("Test should have been marked as failed (but it wasn't).")
-	}
-}
-
-func TestReporterIsResetAtTheEndOfTheStory(t *testing.T) {
-	defer catch(t)
-	reporter := NewGoTestReporter()
-	test := new(fakeTest)
-	reporter.BeginStory(NewStoryReport(test))
-	reporter.EndStory()
-
-	reporter.Report(NewSuccessReport())
-}
-
-func TestReporterNoopMethods(t *testing.T) {
-	reporter := NewGoTestReporter()
-	reporter.Enter(NewScopeReport("title", "name"))
-	reporter.Exit()
-}
-
-func catch(t *testing.T) {
-	if r := recover(); r != nil {
-		t.Log("Getting to this point means we've passed (because we caught a panic appropriately).")
-	}
-}
-
-type fakeTest struct {
-	failed bool
-}
-
-func (self *fakeTest) Fail() {
-	self.failed = true
-}

+ 0 - 94
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/init.go

@@ -1,94 +0,0 @@
-package reporting
-
-import (
-	"fmt"
-	"os"
-	"runtime"
-	"strings"
-)
-
-func init() {
-	if !isXterm() {
-		monochrome()
-	}
-
-	if runtime.GOOS == "windows" {
-		success, failure, error_ = dotSuccess, dotFailure, dotError
-	}
-}
-
-func BuildJsonReporter() Reporter {
-	out := NewPrinter(NewConsole())
-	return NewReporters(
-		NewGoTestReporter(),
-		NewJsonReporter(out))
-}
-func BuildDotReporter() Reporter {
-	out := NewPrinter(NewConsole())
-	return NewReporters(
-		NewGoTestReporter(),
-		NewDotReporter(out),
-		NewProblemReporter(out),
-		consoleStatistics)
-}
-func BuildStoryReporter() Reporter {
-	out := NewPrinter(NewConsole())
-	return NewReporters(
-		NewGoTestReporter(),
-		NewStoryReporter(out),
-		NewProblemReporter(out),
-		consoleStatistics)
-}
-func BuildSilentReporter() Reporter {
-	out := NewPrinter(NewConsole())
-	return NewReporters(
-		NewGoTestReporter(),
-		NewProblemReporter(out))
-}
-
-var (
-	newline         = "\n"
-	success         = "✔"
-	failure         = "✘"
-	error_          = "🔥"
-	skip            = "⚠"
-	dotSuccess      = "."
-	dotFailure      = "x"
-	dotError        = "E"
-	dotSkip         = "S"
-	errorTemplate   = "* %s \nLine %d: - %v \n%s\n"
-	failureTemplate = "* %s \nLine %d:\n%s\n"
-)
-
-var (
-	greenColor  = "\033[32m"
-	yellowColor = "\033[33m"
-	redColor    = "\033[31m"
-	resetColor  = "\033[0m"
-)
-
-var consoleStatistics = NewStatisticsReporter(NewPrinter(NewConsole()))
-
-// QuiteMode disables all console output symbols. This is only meant to be used
-// for tests that are internal to goconvey where the output is distracting or
-// otherwise not needed in the test output.
-func QuietMode() {
-	success, failure, error_, skip, dotSuccess, dotFailure, dotError, dotSkip = "", "", "", "", "", "", "", ""
-}
-
-func monochrome() {
-	greenColor, yellowColor, redColor, resetColor = "", "", "", ""
-}
-
-func isXterm() bool {
-	env := fmt.Sprintf("%v", os.Environ())
-	return strings.Contains(env, " TERM=isXterm") ||
-		strings.Contains(env, " TERM=xterm")
-}
-
-// This interface allows us to pass the *testing.T struct
-// throughout the internals of this tool without ever
-// having to import the "testing" package.
-type T interface {
-	Fail()
-}

+ 0 - 88
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/json.go

@@ -1,88 +0,0 @@
-// TODO: under unit test
-
-package reporting
-
-import (
-	"bytes"
-	"encoding/json"
-	"fmt"
-	"strings"
-)
-
-type JsonReporter struct {
-	out     *Printer
-	current *ScopeResult
-	index   map[string]*ScopeResult
-	scopes  []*ScopeResult
-	depth   int
-}
-
-func (self *JsonReporter) BeginStory(story *StoryReport) {}
-
-func (self *JsonReporter) Enter(scope *ScopeReport) {
-	if _, found := self.index[scope.ID]; !found {
-		self.registerScope(scope)
-	}
-	self.depth++
-	self.current = self.index[scope.ID]
-}
-func (self *JsonReporter) registerScope(scope *ScopeReport) {
-	next := newScopeResult(scope.Title, self.depth, scope.File, scope.Line)
-	self.scopes = append(self.scopes, next)
-	self.index[scope.ID] = next
-}
-
-func (self *JsonReporter) Report(report *AssertionResult) {
-	self.current.Assertions = append(self.current.Assertions, report)
-}
-
-func (self *JsonReporter) Exit() {
-	self.depth--
-}
-
-func (self *JsonReporter) EndStory() {
-	self.report()
-	self.reset()
-}
-func (self *JsonReporter) report() {
-	scopes := []string{}
-	for _, scope := range self.scopes {
-		serialized, err := json.Marshal(scope)
-		if err != nil {
-			self.out.Println(jsonMarshalFailure)
-			panic(err)
-		}
-		var buffer bytes.Buffer
-		json.Indent(&buffer, serialized, "", "  ")
-		scopes = append(scopes, buffer.String())
-	}
-	self.out.Print(fmt.Sprintf("%s\n%s,\n%s\n", OpenJson, strings.Join(scopes, ","), CloseJson))
-}
-func (self *JsonReporter) reset() {
-	self.scopes = []*ScopeResult{}
-	self.index = map[string]*ScopeResult{}
-	self.depth = 0
-}
-
-func (self *JsonReporter) Write(content []byte) (written int, err error) {
-	self.current.Output += string(content)
-	return len(content), nil
-}
-
-func NewJsonReporter(out *Printer) *JsonReporter {
-	self := new(JsonReporter)
-	self.out = out
-	self.reset()
-	return self
-}
-
-const OpenJson = ">>>>>"  // "⌦"
-const CloseJson = "<<<<<" // "⌫"
-const jsonMarshalFailure = `
-
-GOCONVEY_JSON_MARSHALL_FAILURE: There was an error when attempting to convert test results to JSON.
-Please file a bug report and reference the code that caused this failure if possible.
-
-Here's the panic:
-
-`

+ 0 - 57
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/printer.go

@@ -1,57 +0,0 @@
-package reporting
-
-import (
-	"fmt"
-	"io"
-	"strings"
-)
-
-type Printer struct {
-	out    io.Writer
-	prefix string
-}
-
-func (self *Printer) Println(message string, values ...interface{}) {
-	formatted := self.format(message, values...) + newline
-	self.out.Write([]byte(formatted))
-}
-
-func (self *Printer) Print(message string, values ...interface{}) {
-	formatted := self.format(message, values...)
-	self.out.Write([]byte(formatted))
-}
-
-func (self *Printer) Insert(text string) {
-	self.out.Write([]byte(text))
-}
-
-func (self *Printer) format(message string, values ...interface{}) string {
-	var formatted string
-	if len(values) == 0 {
-		formatted = self.prefix + message
-	} else {
-		formatted = self.prefix + fmt.Sprintf(message, values...)
-	}
-	indented := strings.Replace(formatted, newline, newline+self.prefix, -1)
-	return strings.TrimRight(indented, space)
-}
-
-func (self *Printer) Indent() {
-	self.prefix += pad
-}
-
-func (self *Printer) Dedent() {
-	if len(self.prefix) >= padLength {
-		self.prefix = self.prefix[:len(self.prefix)-padLength]
-	}
-}
-
-func NewPrinter(out io.Writer) *Printer {
-	self := new(Printer)
-	self.out = out
-	return self
-}
-
-const space = " "
-const pad = space + space
-const padLength = len(pad)

+ 0 - 181
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/printer_test.go

@@ -1,181 +0,0 @@
-package reporting
-
-import "testing"
-
-func TestPrint(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	const expected = "Hello, World!"
-
-	printer.Print(expected)
-
-	if file.buffer != expected {
-		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
-	}
-}
-
-func TestPrintFormat(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	template := "Hi, %s"
-	name := "Ralph"
-	expected := "Hi, Ralph"
-
-	printer.Print(template, name)
-
-	if file.buffer != expected {
-		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
-	}
-}
-
-func TestPrintPreservesEncodedStrings(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	const expected = "= -> %3D"
-	printer.Print(expected)
-
-	if file.buffer != expected {
-		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
-	}
-}
-
-func TestPrintln(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	const expected = "Hello, World!"
-
-	printer.Println(expected)
-
-	if file.buffer != expected+"\n" {
-		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
-	}
-}
-
-func TestPrintlnFormat(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	template := "Hi, %s"
-	name := "Ralph"
-	expected := "Hi, Ralph\n"
-
-	printer.Println(template, name)
-
-	if file.buffer != expected {
-		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
-	}
-}
-
-func TestPrintlnPreservesEncodedStrings(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	const expected = "= -> %3D"
-	printer.Println(expected)
-
-	if file.buffer != expected+"\n" {
-		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
-	}
-}
-
-func TestPrintIndented(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	const message = "Hello, World!\nGoodbye, World!"
-	const expected = "  Hello, World!\n  Goodbye, World!"
-
-	printer.Indent()
-	printer.Print(message)
-
-	if file.buffer != expected {
-		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
-	}
-}
-
-func TestPrintDedented(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	const expected = "Hello, World!\nGoodbye, World!"
-
-	printer.Indent()
-	printer.Dedent()
-	printer.Print(expected)
-
-	if file.buffer != expected {
-		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
-	}
-}
-
-func TestPrintlnIndented(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	const message = "Hello, World!\nGoodbye, World!"
-	const expected = "  Hello, World!\n  Goodbye, World!\n"
-
-	printer.Indent()
-	printer.Println(message)
-
-	if file.buffer != expected {
-		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
-	}
-}
-
-func TestPrintlnDedented(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-	const expected = "Hello, World!\nGoodbye, World!"
-
-	printer.Indent()
-	printer.Dedent()
-	printer.Println(expected)
-
-	if file.buffer != expected+"\n" {
-		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
-	}
-}
-
-func TestDedentTooFarShouldNotPanic(t *testing.T) {
-	defer func() {
-		if r := recover(); r != nil {
-			t.Error("Should not have panicked!")
-		}
-	}()
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-
-	printer.Dedent()
-
-	t.Log("Getting to this point without panicking means we passed.")
-}
-
-func TestInsert(t *testing.T) {
-	file := newMemoryFile()
-	printer := NewPrinter(file)
-
-	printer.Indent()
-	printer.Print("Hi")
-	printer.Insert(" there")
-	printer.Dedent()
-
-	expected := "  Hi there"
-	if file.buffer != expected {
-		t.Errorf("Should have written '%s' but instead wrote '%s'.", expected, file.buffer)
-	}
-}
-
-////////////////// memoryFile ////////////////////
-
-type memoryFile struct {
-	buffer string
-}
-
-func (self *memoryFile) Write(p []byte) (n int, err error) {
-	self.buffer += string(p)
-	return len(p), nil
-}
-
-func (self *memoryFile) String() string {
-	return self.buffer
-}
-
-func newMemoryFile() *memoryFile {
-	return new(memoryFile)
-}

+ 0 - 68
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/problems.go

@@ -1,68 +0,0 @@
-package reporting
-
-import "fmt"
-
-type problem struct {
-	out      *Printer
-	errors   []*AssertionResult
-	failures []*AssertionResult
-}
-
-func (self *problem) BeginStory(story *StoryReport) {}
-
-func (self *problem) Enter(scope *ScopeReport) {}
-
-func (self *problem) Report(report *AssertionResult) {
-	if report.Error != nil {
-		self.errors = append(self.errors, report)
-	} else if report.Failure != "" {
-		self.failures = append(self.failures, report)
-	}
-}
-
-func (self *problem) Exit() {}
-
-func (self *problem) EndStory() {
-	self.show(self.showErrors, redColor)
-	self.show(self.showFailures, yellowColor)
-	self.prepareForNextStory()
-}
-func (self *problem) show(display func(), color string) {
-	fmt.Print(color)
-	display()
-	fmt.Print(resetColor)
-	self.out.Dedent()
-}
-func (self *problem) showErrors() {
-	for i, e := range self.errors {
-		if i == 0 {
-			self.out.Println("\nErrors:\n")
-			self.out.Indent()
-		}
-		self.out.Println(errorTemplate, e.File, e.Line, e.Error, e.StackTrace)
-	}
-}
-func (self *problem) showFailures() {
-	for i, f := range self.failures {
-		if i == 0 {
-			self.out.Println("\nFailures:\n")
-			self.out.Indent()
-		}
-		self.out.Println(failureTemplate, f.File, f.Line, f.Failure)
-	}
-}
-
-func (self *problem) Write(content []byte) (written int, err error) {
-	return len(content), nil // no-op
-}
-
-func NewProblemReporter(out *Printer) *problem {
-	self := new(problem)
-	self.out = out
-	self.prepareForNextStory()
-	return self
-}
-func (self *problem) prepareForNextStory() {
-	self.errors = []*AssertionResult{}
-	self.failures = []*AssertionResult{}
-}

+ 0 - 46
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/problems_test.go

@@ -1,46 +0,0 @@
-package reporting
-
-import (
-	"strings"
-	"testing"
-)
-
-func TestNoopProblemReporterActions(t *testing.T) {
-	file, reporter := setup()
-	reporter.BeginStory(nil)
-	reporter.Enter(nil)
-	reporter.Exit()
-	expected := ""
-	actual := file.String()
-	if expected != actual {
-		t.Errorf("Expected: '(blank)'\nActual:  '%s'", actual)
-	}
-}
-
-func TestReporterPrintsFailuresAndErrorsAtTheEndOfTheStory(t *testing.T) {
-	file, reporter := setup()
-	reporter.Report(NewFailureReport("failed"))
-	reporter.Report(NewErrorReport("error"))
-	reporter.Report(NewSuccessReport())
-	reporter.EndStory()
-
-	result := file.String()
-	if !strings.Contains(result, "Errors:\n") {
-		t.Errorf("Expected errors, found none.")
-	}
-	if !strings.Contains(result, "Failures:\n") {
-		t.Errorf("Expected failures, found none.")
-	}
-	problemCount := strings.Count(result, "*")
-	if problemCount != 2 {
-		t.Errorf("Expected one failure and one error (total of 2 '*' characters). Got %d", problemCount)
-	}
-}
-
-func setup() (file *memoryFile, reporter *problem) {
-	monochrome()
-	file = newMemoryFile()
-	printer := NewPrinter(file)
-	reporter = NewProblemReporter(printer)
-	return
-}

+ 0 - 39
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/reporter.go

@@ -1,39 +0,0 @@
-package reporting
-
-import "io"
-
-type Reporter interface {
-	BeginStory(story *StoryReport)
-	Enter(scope *ScopeReport)
-	Report(r *AssertionResult)
-	Exit()
-	EndStory()
-	io.Writer
-}
-
-type reporters struct{ collection []Reporter }
-
-func (self *reporters) BeginStory(s *StoryReport) { self.foreach(func(r Reporter) { r.BeginStory(s) }) }
-func (self *reporters) Enter(s *ScopeReport)      { self.foreach(func(r Reporter) { r.Enter(s) }) }
-func (self *reporters) Report(a *AssertionResult) { self.foreach(func(r Reporter) { r.Report(a) }) }
-func (self *reporters) Exit()                     { self.foreach(func(r Reporter) { r.Exit() }) }
-func (self *reporters) EndStory()                 { self.foreach(func(r Reporter) { r.EndStory() }) }
-
-func (self *reporters) Write(contents []byte) (written int, err error) {
-	self.foreach(func(r Reporter) {
-		written, err = r.Write(contents)
-	})
-	return written, err
-}
-
-func (self *reporters) foreach(action func(Reporter)) {
-	for _, r := range self.collection {
-		action(r)
-	}
-}
-
-func NewReporters(collection ...Reporter) *reporters {
-	self := new(reporters)
-	self.collection = collection
-	return self
-}

+ 0 - 94
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/reporter_test.go

@@ -1,94 +0,0 @@
-package reporting
-
-import (
-	"runtime"
-	"testing"
-)
-
-func TestEachNestedReporterReceivesTheCallFromTheContainingReporter(t *testing.T) {
-	fake1 := newFakeReporter()
-	fake2 := newFakeReporter()
-	reporter := NewReporters(fake1, fake2)
-
-	reporter.BeginStory(nil)
-	assertTrue(t, fake1.begun)
-	assertTrue(t, fake2.begun)
-
-	reporter.Enter(NewScopeReport("scope", "hi"))
-	assertTrue(t, fake1.entered)
-	assertTrue(t, fake2.entered)
-
-	reporter.Report(NewSuccessReport())
-	assertTrue(t, fake1.reported)
-	assertTrue(t, fake2.reported)
-
-	reporter.Exit()
-	assertTrue(t, fake1.exited)
-	assertTrue(t, fake2.exited)
-
-	reporter.EndStory()
-	assertTrue(t, fake1.ended)
-	assertTrue(t, fake2.ended)
-
-	content := []byte("hi")
-	written, err := reporter.Write(content)
-	assertTrue(t, fake1.written)
-	assertTrue(t, fake2.written)
-	assertEqual(t, written, len(content))
-	assertNil(t, err)
-
-}
-
-func assertTrue(t *testing.T, value bool) {
-	if !value {
-		_, _, line, _ := runtime.Caller(1)
-		t.Errorf("Value should have been true (but was false). See line %d", line)
-	}
-}
-
-func assertEqual(t *testing.T, expected, actual int) {
-	if actual != expected {
-		_, _, line, _ := runtime.Caller(1)
-		t.Errorf("Value should have been %d (but was %d). See line %d", expected, actual, line)
-	}
-}
-
-func assertNil(t *testing.T, err error) {
-	if err != nil {
-		_, _, line, _ := runtime.Caller(1)
-		t.Errorf("Error should have been <nil> (but wasn't). See line %d", err, line)
-	}
-}
-
-type fakeReporter struct {
-	begun    bool
-	entered  bool
-	reported bool
-	exited   bool
-	ended    bool
-	written  bool
-}
-
-func newFakeReporter() *fakeReporter {
-	return &fakeReporter{}
-}
-
-func (self *fakeReporter) BeginStory(story *StoryReport) {
-	self.begun = true
-}
-func (self *fakeReporter) Enter(scope *ScopeReport) {
-	self.entered = true
-}
-func (self *fakeReporter) Report(report *AssertionResult) {
-	self.reported = true
-}
-func (self *fakeReporter) Exit() {
-	self.exited = true
-}
-func (self *fakeReporter) EndStory() {
-	self.ended = true
-}
-func (self *fakeReporter) Write(content []byte) (int, error) {
-	self.written = true
-	return len(content), nil
-}

+ 0 - 179
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/reports.go

@@ -1,179 +0,0 @@
-package reporting
-
-import (
-	"encoding/json"
-	"fmt"
-	"runtime"
-	"strings"
-
-	"github.com/smartystreets/goconvey/convey/gotest"
-)
-
-////////////////// ScopeReport ////////////////////
-
-type ScopeReport struct {
-	Title string
-	ID    string
-	File  string
-	Line  int
-}
-
-func NewScopeReport(title, name string) *ScopeReport {
-	file, line, _ := gotest.ResolveExternalCaller()
-	self := new(ScopeReport)
-	self.Title = title
-	self.ID = fmt.Sprintf("%s|%s", title, name)
-	self.File = file
-	self.Line = line
-	return self
-}
-
-////////////////// ScopeResult ////////////////////
-
-type ScopeResult struct {
-	Title      string
-	File       string
-	Line       int
-	Depth      int
-	Assertions []*AssertionResult
-	Output     string
-}
-
-func newScopeResult(title string, depth int, file string, line int) *ScopeResult {
-	self := new(ScopeResult)
-	self.Title = title
-	self.Depth = depth
-	self.File = file
-	self.Line = line
-	self.Assertions = []*AssertionResult{}
-	return self
-}
-
-/////////////////// StoryReport /////////////////////
-
-type StoryReport struct {
-	Test T
-	Name string
-	File string
-	Line int
-}
-
-func NewStoryReport(test T) *StoryReport {
-	file, line, name := gotest.ResolveExternalCaller()
-	name = removePackagePath(name)
-	self := new(StoryReport)
-	self.Test = test
-	self.Name = name
-	self.File = file
-	self.Line = line
-	return self
-}
-
-// name comes in looking like "github.com/smartystreets/goconvey/examples.TestName".
-// We only want the stuff after the last '.', which is the name of the test function.
-func removePackagePath(name string) string {
-	parts := strings.Split(name, ".")
-	return parts[len(parts)-1]
-}
-
-/////////////////// FailureView ////////////////////////
-
-type FailureView struct {
-	Message  string
-	Expected string
-	Actual   string
-}
-
-////////////////////AssertionResult //////////////////////
-
-type AssertionResult struct {
-	File       string
-	Line       int
-	Expected   string
-	Actual     string
-	Failure    string
-	Error      interface{}
-	StackTrace string
-	Skipped    bool
-}
-
-func NewFailureReport(failure string) *AssertionResult {
-	report := new(AssertionResult)
-	report.File, report.Line = caller()
-	report.StackTrace = stackTrace()
-	parseFailure(failure, report)
-	return report
-}
-func parseFailure(failure string, report *AssertionResult) {
-	view := new(FailureView)
-	err := json.Unmarshal([]byte(failure), view)
-	if err == nil {
-		report.Failure = view.Message
-		report.Expected = view.Expected
-		report.Actual = view.Actual
-	} else {
-		report.Failure = failure
-	}
-}
-func NewErrorReport(err interface{}) *AssertionResult {
-	report := new(AssertionResult)
-	report.File, report.Line = caller()
-	report.StackTrace = fullStackTrace()
-	report.Error = fmt.Sprintf("%v", err)
-	return report
-}
-func NewSuccessReport() *AssertionResult {
-	return new(AssertionResult)
-}
-func NewSkipReport() *AssertionResult {
-	report := new(AssertionResult)
-	report.File, report.Line = caller()
-	report.StackTrace = fullStackTrace()
-	report.Skipped = true
-	return report
-}
-
-func caller() (file string, line int) {
-	file, line, _ = gotest.ResolveExternalCaller()
-	return
-}
-
-func stackTrace() string {
-	buffer := make([]byte, 1024*64)
-	n := runtime.Stack(buffer, false)
-	return removeInternalEntries(string(buffer[:n]))
-}
-func fullStackTrace() string {
-	buffer := make([]byte, 1024*64)
-	n := runtime.Stack(buffer, true)
-	return removeInternalEntries(string(buffer[:n]))
-}
-func removeInternalEntries(stack string) string {
-	lines := strings.Split(stack, newline)
-	filtered := []string{}
-	for _, line := range lines {
-		if !isExternal(line) {
-			filtered = append(filtered, line)
-		}
-	}
-	return strings.Join(filtered, newline)
-}
-func isExternal(line string) bool {
-	for _, p := range internalPackages {
-		if strings.Contains(line, p) {
-			return true
-		}
-	}
-	return false
-}
-
-// NOTE: any new packages that host goconvey packages will need to be added here!
-// An alternative is to scan the goconvey directory and then exclude stuff like
-// the examples package but that's nasty too.
-var internalPackages = []string{
-	"goconvey/assertions",
-	"goconvey/convey",
-	"goconvey/execution",
-	"goconvey/gotest",
-	"goconvey/reporting",
-}

+ 0 - 79
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/statistics.go

@@ -1,79 +0,0 @@
-package reporting
-
-import "fmt"
-
-func (self *statistics) BeginStory(story *StoryReport) {}
-
-func (self *statistics) Enter(scope *ScopeReport) {}
-
-func (self *statistics) Report(report *AssertionResult) {
-	if !self.failing && report.Failure != "" {
-		self.failing = true
-	}
-	if !self.erroring && report.Error != nil {
-		self.erroring = true
-	}
-	if report.Skipped {
-		self.skipped += 1
-	} else {
-		self.total++
-	}
-}
-
-func (self *statistics) Exit() {}
-
-func (self *statistics) EndStory() {
-	self.reportAssertions()
-	self.reportSkippedSections()
-	self.completeReport()
-}
-func (self *statistics) reportAssertions() {
-	self.decideColor()
-	self.out.Print("\n%d %s thus far", self.total, plural("assertion", self.total))
-}
-func (self *statistics) decideColor() {
-	if self.failing && !self.erroring {
-		fmt.Print(yellowColor)
-	} else if self.erroring {
-		fmt.Print(redColor)
-	} else {
-		fmt.Print(greenColor)
-	}
-}
-func (self *statistics) reportSkippedSections() {
-	if self.skipped > 0 {
-		fmt.Print(yellowColor)
-		self.out.Print(" (one or more sections skipped)")
-		self.skipped = 0
-	}
-}
-func (self *statistics) completeReport() {
-	fmt.Print(resetColor)
-	self.out.Print("\n")
-	self.out.Print("\n")
-}
-
-func (self *statistics) Write(content []byte) (written int, err error) {
-	return len(content), nil // no-op
-}
-
-func NewStatisticsReporter(out *Printer) *statistics {
-	self := statistics{}
-	self.out = out
-	return &self
-}
-
-type statistics struct {
-	out      *Printer
-	total    int
-	failing  bool
-	erroring bool
-	skipped  int
-}
-
-func plural(word string, count int) string {
-	if count == 1 {
-		return word
-	}
-	return word + "s"
-}

+ 0 - 65
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/story.go

@@ -1,65 +0,0 @@
-// TODO: in order for this reporter to be completely honest
-// we need to retrofit to be more like the json reporter such that:
-// 1. it maintains ScopeResult collections, which count assertions
-// 2. it reports only after EndStory(), so that all tick marks
-//    are placed near the appropriate title.
-// 3. Under unit test
-
-package reporting
-
-import "fmt"
-
-type story struct {
-	out        *Printer
-	titlesById map[string]string
-}
-
-func (self *story) BeginStory(story *StoryReport) {}
-
-func (self *story) Enter(scope *ScopeReport) {
-	self.out.Indent()
-
-	if _, found := self.titlesById[scope.ID]; !found {
-		self.out.Println("")
-		self.out.Print(scope.Title)
-		self.out.Insert(" ")
-		self.titlesById[scope.ID] = scope.Title
-	}
-}
-
-func (self *story) Report(report *AssertionResult) {
-	if report.Error != nil {
-		fmt.Print(redColor)
-		self.out.Insert(error_)
-	} else if report.Failure != "" {
-		fmt.Print(yellowColor)
-		self.out.Insert(failure)
-	} else if report.Skipped {
-		fmt.Print(yellowColor)
-		self.out.Insert(skip)
-	} else {
-		fmt.Print(greenColor)
-		self.out.Insert(success)
-	}
-	fmt.Print(resetColor)
-}
-
-func (self *story) Exit() {
-	self.out.Dedent()
-}
-
-func (self *story) EndStory() {
-	self.titlesById = make(map[string]string)
-	self.out.Println("\n")
-}
-
-func (self *story) Write(content []byte) (written int, err error) {
-	return len(content), nil // no-op
-}
-
-func NewStoryReporter(out *Printer) *story {
-	self := new(story)
-	self.out = out
-	self.titlesById = make(map[string]string)
-	return self
-}

+ 0 - 270
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting_hooks_test.go

@@ -1,270 +0,0 @@
-package convey
-
-import (
-	"fmt"
-	"net/http"
-	"net/http/httptest"
-	"path"
-	"runtime"
-	"strconv"
-	"strings"
-	"testing"
-
-	"github.com/smartystreets/goconvey/convey/reporting"
-)
-
-func TestSingleScopeReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		So(1, ShouldEqual, 1)
-	})
-
-	expectEqual(t, "Begin|A|Success|Exit|End", myReporter.wholeStory())
-}
-
-func TestNestedScopeReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		Convey("B", func() {
-			So(1, ShouldEqual, 1)
-		})
-	})
-
-	expectEqual(t, "Begin|A|B|Success|Exit|Exit|End", myReporter.wholeStory())
-}
-
-func TestFailureReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		So(1, ShouldBeNil)
-	})
-
-	expectEqual(t, "Begin|A|Failure|Exit|End", myReporter.wholeStory())
-}
-
-func TestFirstFailureEndsScopeExecution(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		So(1, ShouldBeNil)
-		So(nil, ShouldBeNil)
-	})
-
-	expectEqual(t, "Begin|A|Failure|Exit|End", myReporter.wholeStory())
-}
-
-func TestComparisonFailureDeserializedAndReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		So("hi", ShouldEqual, "bye")
-	})
-
-	expectEqual(t, "Begin|A|Failure(bye/hi)|Exit|End", myReporter.wholeStory())
-}
-
-func TestNestedFailureReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		Convey("B", func() {
-			So(2, ShouldBeNil)
-		})
-	})
-
-	expectEqual(t, "Begin|A|B|Failure|Exit|Exit|End", myReporter.wholeStory())
-}
-
-func TestSuccessAndFailureReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		So(nil, ShouldBeNil)
-		So(1, ShouldBeNil)
-	})
-
-	expectEqual(t, "Begin|A|Success|Failure|Exit|End", myReporter.wholeStory())
-}
-
-func TestIncompleteActionReportedAsSkipped(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		Convey("B", nil)
-	})
-
-	expectEqual(t, "Begin|A|B|Skipped|Exit|Exit|End", myReporter.wholeStory())
-}
-
-func TestSkippedConveyReportedAsSkipped(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		SkipConvey("B", func() {
-			So(1, ShouldEqual, 1)
-		})
-	})
-
-	expectEqual(t, "Begin|A|B|Skipped|Exit|Exit|End", myReporter.wholeStory())
-}
-
-func TestMultipleSkipsAreReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		Convey("0", func() {
-			So(nil, ShouldBeNil)
-		})
-
-		SkipConvey("1", func() {})
-		SkipConvey("2", func() {})
-
-		Convey("3", nil)
-		Convey("4", nil)
-
-		Convey("5", func() {
-			So(nil, ShouldBeNil)
-		})
-	})
-
-	expected := "Begin" +
-		"|A|0|Success|Exit|Exit" +
-		"|A|1|Skipped|Exit|Exit" +
-		"|A|2|Skipped|Exit|Exit" +
-		"|A|3|Skipped|Exit|Exit" +
-		"|A|4|Skipped|Exit|Exit" +
-		"|A|5|Success|Exit|Exit" +
-		"|End"
-
-	expectEqual(t, expected, myReporter.wholeStory())
-}
-
-func TestSkippedAssertionIsNotReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		SkipSo(1, ShouldEqual, 1)
-	})
-
-	expectEqual(t, "Begin|A|Skipped|Exit|End", myReporter.wholeStory())
-}
-
-func TestMultipleSkippedAssertionsAreNotReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		SkipSo(1, ShouldEqual, 1)
-		So(1, ShouldEqual, 1)
-		SkipSo(1, ShouldEqual, 1)
-	})
-
-	expectEqual(t, "Begin|A|Skipped|Success|Skipped|Exit|End", myReporter.wholeStory())
-}
-
-func TestErrorByManualPanicReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		panic("Gopher alert!")
-	})
-
-	expectEqual(t, "Begin|A|Error|Exit|End", myReporter.wholeStory())
-}
-
-func TestIterativeConveysReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		for x := 0; x < 3; x++ {
-			Convey(strconv.Itoa(x), func() {
-				So(x, ShouldEqual, x)
-			})
-		}
-	})
-
-	expectEqual(t, "Begin|A|0|Success|Exit|Exit|A|1|Success|Exit|Exit|A|2|Success|Exit|Exit|End", myReporter.wholeStory())
-}
-
-func TestEmbeddedAssertionReported(t *testing.T) {
-	myReporter, test := setupFakeReporter()
-
-	Convey("A", test, func() {
-		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			So(r.FormValue("msg"), ShouldEqual, "ping")
-		}))
-		http.DefaultClient.Get(ts.URL + "?msg=ping")
-	})
-
-	expectEqual(t, "Begin|A|Success|Exit|End", myReporter.wholeStory())
-}
-
-func expectEqual(t *testing.T, expected interface{}, actual interface{}) {
-	if expected != actual {
-		_, file, line, _ := runtime.Caller(1)
-		t.Errorf("Expected '%v' to be '%v' but it wasn't. See '%s' at line %d.",
-			actual, expected, path.Base(file), line)
-	}
-}
-
-func setupFakeReporter() (*fakeReporter, *fakeGoTest) {
-	myReporter := new(fakeReporter)
-	myReporter.calls = []string{}
-	testReporter = myReporter
-	return myReporter, new(fakeGoTest)
-}
-
-type fakeReporter struct {
-	calls []string
-}
-
-func (self *fakeReporter) BeginStory(story *reporting.StoryReport) {
-	self.calls = append(self.calls, "Begin")
-}
-
-func (self *fakeReporter) Enter(scope *reporting.ScopeReport) {
-	self.calls = append(self.calls, scope.Title)
-}
-
-func (self *fakeReporter) Report(report *reporting.AssertionResult) {
-	if report.Error != nil {
-		self.calls = append(self.calls, "Error")
-	} else if report.Failure != "" {
-		message := "Failure"
-		if report.Expected != "" || report.Actual != "" {
-			message += fmt.Sprintf("(%s/%s)", report.Expected, report.Actual)
-		}
-		self.calls = append(self.calls, message)
-	} else if report.Skipped {
-		self.calls = append(self.calls, "Skipped")
-	} else {
-		self.calls = append(self.calls, "Success")
-	}
-}
-
-func (self *fakeReporter) Exit() {
-	self.calls = append(self.calls, "Exit")
-}
-
-func (self *fakeReporter) EndStory() {
-	self.calls = append(self.calls, "End")
-}
-
-func (self *fakeReporter) Write(content []byte) (int, error) {
-	return len(content), nil // no-op
-}
-
-func (self *fakeReporter) wholeStory() string {
-	return strings.Join(self.calls, "|")
-}
-
-////////////////////////////////
-
-type fakeGoTest struct{}
-
-func (self *fakeGoTest) Fail()                                     {}
-func (self *fakeGoTest) Fatalf(format string, args ...interface{}) {}
-
-var test t = new(fakeGoTest)

+ 0 - 92
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/runner.go

@@ -1,92 +0,0 @@
-package convey
-
-import (
-	"github.com/smartystreets/goconvey/convey/reporting"
-)
-
-type runner struct {
-	top         *scope
-	active      *scope
-	reporter    reporting.Reporter
-	failureMode FailureMode
-	focus       bool
-}
-
-func (self *runner) Register(entry *registration) {
-	if self.focus && !entry.Focus {
-		return
-	}
-
-	self.active.adopt(newScope(entry, self.reporter))
-}
-
-func (self *runner) RegisterReset(action *action) {
-	self.active.registerReset(action)
-}
-
-func (self *runner) Run(entry *registration) {
-	self.active = self.top
-	self.focus = entry.Focus
-	self.failureMode = defaultFailureMode
-
-	self.Register(entry)
-	self.reporter.BeginStory(reporting.NewStoryReport(entry.Test))
-
-	for !self.top.visited() {
-		self.top.visit(self)
-	}
-
-	self.reporter.EndStory()
-}
-
-func newRunner(reporter reporting.Reporter) *runner {
-	// Top-level is always using a nilReporter
-	scope := newScope(newRegistration(topLevel, newAction(func() {}, FailureInherits), nil), newNilReporter())
-
-	return &runner{
-		reporter: reporter,
-		top:      scope,
-		active:   scope,
-	}
-}
-
-func (self *runner) Report(result *reporting.AssertionResult) {
-	self.reporter.Report(result)
-
-	if result.Failure != "" && self.failureMode == FailureHalts {
-		panic(failureHalt)
-	}
-}
-
-func (self *runner) Write(content []byte) (written int, err error) {
-	return self.reporter.Write(content)
-}
-
-func (self *runner) setFailureMode(mode FailureMode) FailureMode {
-	old := self.failureMode
-
-	if mode != FailureInherits {
-		self.failureMode = mode
-	}
-
-	return old
-}
-
-func last(group []string) string {
-	return group[len(group)-1]
-}
-
-const topLevel = "TOP"
-const failureHalt = "___FAILURE_HALT___"
-
-//////////////////////// nilReporter /////////////////////////////
-
-type nilReporter struct{}
-
-func (self *nilReporter) BeginStory(story *reporting.StoryReport)  {}
-func (self *nilReporter) Enter(scope *reporting.ScopeReport)       {}
-func (self *nilReporter) Report(report *reporting.AssertionResult) {}
-func (self *nilReporter) Exit()                                    {}
-func (self *nilReporter) EndStory()                                {}
-func (self *nilReporter) Write(p []byte) (int, error)              { return len(p), nil }
-func newNilReporter() *nilReporter                                 { return &nilReporter{} }

+ 0 - 116
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/scope.go

@@ -1,116 +0,0 @@
-package convey
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/smartystreets/goconvey/convey/reporting"
-)
-
-type scope struct {
-	name       string
-	title      string
-	action     *action
-	children   map[string]*scope
-	birthOrder []*scope
-	child      int
-	resetOrder []string
-	resets     map[string]*action
-	panicked   bool
-	reporter   reporting.Reporter
-	report     *reporting.ScopeReport
-}
-
-func (parent *scope) adopt(child *scope) {
-	i := parent.getChildIndex(child)
-
-	if i == -1 {
-		parent.children[child.name] = child
-		parent.birthOrder = append(parent.birthOrder, child)
-	} else {
-		/* We need to replace the action to retain the closed over variables from
-		   the specific invocation of the parent scope, enabling the enclosing
-		   parent scope to serve as a set-up for the child scope */
-		parent.birthOrder[i].action = child.action
-	}
-}
-
-func (parent *scope) getChildIndex(child *scope) int {
-	for i, ordered := range parent.birthOrder {
-		if ordered.name == child.name && ordered.title == child.title {
-			return i
-		}
-	}
-
-	return -1
-}
-
-func (self *scope) registerReset(action *action) {
-	self.resets[action.name] = action
-	for _, name := range self.resetOrder {
-		if name == action.name {
-			return
-		}
-	}
-	self.resetOrder = append(self.resetOrder, action.name)
-}
-
-func (self *scope) visited() bool {
-	return self.panicked || self.child >= len(self.birthOrder)
-}
-
-func (parent *scope) visit(runner *runner) {
-	runner.active = parent
-	defer parent.exit()
-
-	oldMode := runner.setFailureMode(parent.action.failureMode)
-	defer runner.setFailureMode(oldMode)
-
-	parent.reporter.Enter(parent.report)
-	parent.action.Invoke()
-	parent.visitNextChild(runner)
-	parent.cleanup()
-}
-func (parent *scope) visitNextChild(runner *runner) {
-	if len(parent.birthOrder) > parent.child {
-		child := parent.birthOrder[parent.child]
-
-		child.visit(runner)
-
-		if child.visited() {
-			parent.child++
-		}
-	}
-}
-func (parent *scope) cleanup() {
-	for _, name := range parent.resetOrder {
-		reset := parent.resets[name]
-		reset.Invoke()
-	}
-}
-func (parent *scope) exit() {
-	if problem := recover(); problem != nil {
-		if strings.HasPrefix(fmt.Sprintf("%v", problem), extraGoTest) {
-			panic(problem)
-		}
-		if problem != failureHalt {
-			parent.reporter.Report(reporting.NewErrorReport(problem))
-		}
-		parent.panicked = true
-	}
-	parent.reporter.Exit()
-}
-
-func newScope(entry *registration, reporter reporting.Reporter) *scope {
-	return &scope{
-		reporter:   reporter,
-		name:       entry.action.name,
-		title:      entry.Situation,
-		action:     entry.action,
-		children:   make(map[string]*scope),
-		birthOrder: []*scope{},
-		resetOrder: []string{},
-		resets:     make(map[string]*action),
-		report:     reporting.NewScopeReport(entry.Situation, entry.action.name),
-	}
-}

+ 0 - 185
Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/story_conventions_test.go

@@ -1,185 +0,0 @@
-package convey
-
-import (
-	"fmt"
-	"strings"
-	"testing"
-)
-
-func TestMissingTopLevelGoTestReferenceCausesPanic(t *testing.T) {
-	output := map[string]bool{}
-
-	defer expectEqual(t, false, output["good"])
-	defer requireGoTestReference(t)
-
-	Convey("Hi", func() {
-		output["bad"] = true // this shouldn't happen
-	})
-}
-
-func requireGoTestReference(t *testing.T) {
-	err := recover()
-	if err == nil {
-		t.Error("We should have recovered a panic here (because of a missing *testing.T reference)!")
-	} else {
-		expectEqual(t, missingGoTest, err)
-	}
-}
-
-func TestMissingTopLevelGoTestReferenceAfterGoodExample(t *testing.T) {
-	output := map[string]bool{}
-
-	defer func() {
-		expectEqual(t, true, output["good"])
-		expectEqual(t, false, output["bad"])
-	}()
-	defer requireGoTestReference(t)
-
-	Convey("Good example", t, func() {
-		output["good"] = true
-	})
-
-	Convey("Bad example", func() {
-		output["bad"] = true // shouldn't happen
-	})
-}
-
-func TestExtraReferencePanics(t *testing.T) {
-	output := map[string]bool{}
-
-	defer func() {
-		err := recover()
-		if err == nil {
-			t.Error("We should have recovered a panic here (because of an extra *testing.T reference)!")
-		} else if !strings.HasPrefix(fmt.Sprintf("%v", err), extraGoTest) {
-			t.Error("Should have panicked with the 'extra go test' error!")
-		}
-		if output["bad"] {
-			t.Error("We should NOT have run the bad example!")
-		}
-	}()
-
-	Convey("Good example", t, func() {
-		Convey("Bad example - passing in *testing.T a second time!", t, func() {
-			output["bad"] = true // shouldn't happen
-		})
-	})
-}
-
-func TestParseRegistrationMissingRequiredElements(t *testing.T) {
-	defer func() {
-		if r := recover(); r != nil {
-			if r != "You must provide a name (string), then a *testing.T (if in outermost scope), an optional FailureMode, and then an action (func())." {
-				t.Errorf("Incorrect panic message.")
-			}
-		}
-	}()
-
-	Convey()
-
-	t.Errorf("goTest should have panicked in Convey(...) and then recovered in the defer func().")
-}
-
-func TestParseRegistration_MissingNameString(t *testing.T) {
-	defer func() {
-		if r := recover(); r != nil {
-			if r != parseError {
-				t.Errorf("Incorrect panic message.")
-			}
-		}
-	}()
-
-	action := func() {}
-
-	Convey(action)
-
-	t.Errorf("goTest should have panicked in Convey(...) and then recovered in the defer func().")
-}
-
-func TestParseRegistration_MissingActionFunc(t *testing.T) {
-	defer func() {
-		if r := recover(); r != nil {
-			if r != parseError {
-				t.Errorf("Incorrect panic message: '%s'", r)
-			}
-		}
-	}()
-
-	Convey("Hi there", 12345)
-
-	t.Errorf("goTest should have panicked in Convey(...) and then recovered in the defer func().")
-}
-
-func TestFailureModeParameterButMissing(t *testing.T) {
-	defer func() {
-		if r := recover(); r != nil {
-			if r != parseError {
-				t.Errorf("Incorrect panic message.")
-			}
-		} else {
-			t.Errorf("Expected panic")
-		}
-	}()
-
-	prepare()
-
-	Convey("Foobar", t, FailureHalts)
-}
-
-func TestFailureModeParameterWithAction(t *testing.T) {
-	prepare()
-
-	defer func() {
-		if r := recover(); r != nil {
-			t.Errorf("Unexpected panic")
-		}
-	}()
-
-	Convey("Foobar", t, FailureHalts, func() {})
-}
-
-func TestExtraConveyParameters(t *testing.T) {
-	defer func() {
-		if r := recover(); r != nil {
-			if r != parseError {
-				t.Errorf("Incorrect panic message.")
-			}
-		} else {
-			t.Errorf("Expected panic")
-		}
-	}()
-
-	prepare()
-
-	Convey("Foobar", t, FailureHalts, func() {}, "This is not supposed to be here")
-}
-
-func TestExtraConveyParameters2(t *testing.T) {
-	defer func() {
-		if r := recover(); r != nil {
-			if r != parseError {
-				t.Errorf("Incorrect panic message.")
-			}
-		} else {
-			t.Errorf("Expected panic")
-		}
-	}()
-
-	prepare()
-
-	Convey("Foobar", t, func() {}, "This is not supposed to be here")
-}
-
-func TestExtraConveyParameters3(t *testing.T) {
-	output := prepare()
-
-	Convey("A", t, func() {
-		output += "A "
-
-		Convey("B", func() {
-			output += "B "
-		}, "This is not supposed to be here")
-	})
-
-	expectEqual(t, "A ", output)
-}

+ 89 - 4
Godeps/_workspace/src/gopkg.in/ini.v1/README.md

@@ -121,11 +121,15 @@ v, err = cfg.Section("").Key("BOOL").Bool()
 v, err = cfg.Section("").Key("FLOAT64").Float64()
 v, err = cfg.Section("").Key("INT").Int()
 v, err = cfg.Section("").Key("INT64").Int64()
+v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339)
+v, err = cfg.Section("").Key("TIME").Time() // RFC3339
 
 v = cfg.Section("").Key("BOOL").MustBool()
 v = cfg.Section("").Key("FLOAT64").MustFloat64()
 v = cfg.Section("").Key("INT").MustInt()
 v = cfg.Section("").Key("INT64").MustInt64()
+v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339)
+v = cfg.Section("").Key("TIME").MustTime() // RFC3339
 
 // Methods start with Must also accept one argument for default value
 // when key not found or fail to parse value to given type.
@@ -136,6 +140,8 @@ v = cfg.Section("").Key("BOOL").MustBool(true)
 v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25)
 v = cfg.Section("").Key("INT").MustInt(10)
 v = cfg.Section("").Key("INT64").MustInt64(99)
+v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now())
+v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339
 ```
 
 What if my value is three-line long?
@@ -170,6 +176,7 @@ v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"})
 v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75})
 v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30})
 v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30})
+v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3})
 ```
 
 Default value will be presented if value of key is not in candidates you given, and default value does not need be one of candidates.
@@ -181,11 +188,12 @@ vals = cfg.Section("").Key("STRINGS").Strings(",")
 vals = cfg.Section("").Key("FLOAT64S").Float64s(",")
 vals = cfg.Section("").Key("INTS").Ints(",")
 vals = cfg.Section("").Key("INT64S").Int64s(",")
+vals = cfg.Section("").Key("TIMES").Times(",")
 ```
 
-### Advanced Usage
+## Advanced Usage
 
-#### Recursive Values
+### Recursive Values
 
 For all value of keys, there is a special syntax `%(<name>)s`, where `<name>` is the key name in same section or default section, and `%(<name>)s` will be replaced by corresponding value(empty string if key not found). You can use this syntax at most 99 level of recursions.
 
@@ -205,7 +213,7 @@ cfg.Section("author").Key("GITHUB").String()		// https://github.com/Unknwon
 cfg.Section("package").Key("FULL_NAME").String()	// github.com/go-ini/ini
 ```
 
-#### Parent-child Sections
+### Parent-child Sections
 
 You can use `.` in section name to indicate parent-child relationship between two or more sections. If the key not found in the child section, library will try again on its parent section until there is no parent section.
 
@@ -224,7 +232,7 @@ CLONE_URL = https://%(IMPORT_PATH)s
 cfg.Section("package.sub").Key("CLONE_URL").String()	// https://gopkg.in/ini.v1
 ```
 
-#### Auto-increment Key Names
+### Auto-increment Key Names
 
 If key name is `-` in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter.
 
@@ -239,6 +247,83 @@ If key name is `-` in data source, then it would be seen as special syntax for a
 cfg.Section("features").KeyStrings()	// []{"#1", "#2", "#3"}
 ```
 
+### Map To Struct
+
+Want more objective way to play with INI? Cool.
+
+```ini
+Name = Unknwon
+age = 21
+Male = true
+Born = 1993-01-01T20:17:05Z
+
+[Note]
+Content = Hi is a good man!
+Cities = HangZhou, Boston
+```
+
+```go
+type Note struct {
+	Content string
+	Cities  []string
+}
+
+type Person struct {
+	Name string
+	Age  int `ini:"age"`
+	Male bool
+	Born time.Time
+	Note
+	Created time.Time `ini:"-"`
+}
+
+func main() {
+	cfg, err := ini.Load("path/to/ini")
+	// ...
+	p := new(Person)
+	err = cfg.MapTo(p)
+	// ...
+
+	// Things can be simpler.
+	err = ini.MapTo(p, "path/to/ini")
+	// ...
+
+	// Just map a section? Fine.
+	n := new(Note)
+	err = cfg.Section("Note").MapTo(n)
+	// ...
+}
+```
+
+#### Name Mapper
+
+To save your time and make your code cleaner, this library supports [`NameMapper`](https://gowalker.org/gopkg.in/ini.v1#NameMapper) between struct field and actual secion and key name.
+
+There are 2 built-in name mappers:
+
+- `AllCapsUnderscore`: it converts to format `ALL_CAPS_UNDERSCORE` then match section or key.
+- `TitleUnderscore`: it converts to format `title_underscore` then match section or key.
+
+To use them:
+
+```go
+type Info struct{
+	PackageName string
+}
+
+func main() {
+	err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("packag_name=ini"))
+	// ...
+
+	cfg, err := ini.Load("PACKAGE_NAME=ini")
+	// ...
+	info := new(Info)
+	cfg.NameMapper = ini.AllCapsUnderscore
+	err = cfg.MapTo(info)
+	// ...
+}
+```
+
 ## Getting Help
 
 - [API Documentation](https://gowalker.org/gopkg.in/ini.v1)

+ 85 - 0
Godeps/_workspace/src/gopkg.in/ini.v1/README_ZH.md

@@ -116,11 +116,15 @@ v, err = cfg.Section("").Key("BOOL").Bool()
 v, err = cfg.Section("").Key("FLOAT64").Float64()
 v, err = cfg.Section("").Key("INT").Int()
 v, err = cfg.Section("").Key("INT64").Int64()
+v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339)
+v, err = cfg.Section("").Key("TIME").Time() // RFC3339
 
 v = cfg.Section("").Key("BOOL").MustBool()
 v = cfg.Section("").Key("FLOAT64").MustFloat64()
 v = cfg.Section("").Key("INT").MustInt()
 v = cfg.Section("").Key("INT64").MustInt64()
+v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339)
+v = cfg.Section("").Key("TIME").MustTime() // RFC3339
 
 // 由 Must 开头的方法名允许接收一个相同类型的参数来作为默认值,
 // 当键不存在或者转换失败时,则会直接返回该默认值。
@@ -131,6 +135,8 @@ v = cfg.Section("").Key("BOOL").MustBool(true)
 v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25)
 v = cfg.Section("").Key("INT").MustInt(10)
 v = cfg.Section("").Key("INT64").MustInt64(99)
+v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now())
+v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339
 ```
 
 如果我的值有好多行怎么办?
@@ -165,6 +171,7 @@ v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"})
 v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75})
 v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30})
 v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30})
+v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3})
 ```
 
 如果获取到的值不是候选值的任意一个,则会返回默认值,而默认值不需要是候选值中的一员。
@@ -176,6 +183,7 @@ vals = cfg.Section("").Key("STRINGS").Strings(",")
 vals = cfg.Section("").Key("FLOAT64S").Float64s(",")
 vals = cfg.Section("").Key("INTS").Ints(",")
 vals = cfg.Section("").Key("INT64S").Int64s(",")
+vals = cfg.Section("").Key("TIMES").Times(",")
 ```
 
 ### 高级用法
@@ -234,6 +242,83 @@ cfg.Section("package.sub").Key("CLONE_URL").String()	// https://gopkg.in/ini.v1
 cfg.Section("features").KeyStrings()	// []{"#1", "#2", "#3"}
 ```
 
+### 映射到结构
+
+想要使用更加面向对象的方式玩转 INI 吗?好主意。
+
+```ini
+Name = Unknwon
+age = 21
+Male = true
+Born = 1993-01-01T20:17:05Z
+
+[Note]
+Content = Hi is a good man!
+Cities = HangZhou, Boston
+```
+
+```go
+type Note struct {
+	Content string
+	Cities  []string
+}
+
+type Person struct {
+	Name string
+	Age  int `ini:"age"`
+	Male bool
+	Born time.Time
+	Note
+	Created time.Time `ini:"-"`
+}
+
+func main() {
+	cfg, err := ini.Load("path/to/ini")
+	// ...
+	p := new(Person)
+	err = cfg.MapTo(p)
+	// ...
+
+	// 一切竟可以如此的简单。
+	err = ini.MapTo(p, "path/to/ini")
+	// ...
+
+	// 嗯哼?只需要映射一个分区吗?
+	n := new(Note)
+	err = cfg.Section("Note").MapTo(n)
+	// ...
+}
+```
+
+#### 名称映射器(Name Mapper)
+
+为了节省您的时间并简化代码,本库支持类型为 [`NameMapper`](https://gowalker.org/gopkg.in/ini.v1#NameMapper) 的名称映射器,该映射器负责结构字段名与分区名和键名之间的映射。
+
+目前有 2 款内置的映射器:
+
+- `AllCapsUnderscore`:该映射器将字段名转换至格式 `ALL_CAPS_UNDERSCORE` 后再去匹配分区名和键名。
+- `TitleUnderscore`:该映射器将字段名转换至格式 `title_underscore` 后再去匹配分区名和键名。
+
+使用方法:
+
+```go
+type Info struct{
+	PackageName string
+}
+
+func main() {
+	err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("packag_name=ini"))
+	// ...
+
+	cfg, err := ini.Load("PACKAGE_NAME=ini")
+	// ...
+	info := new(Info)
+	cfg.NameMapper = ini.AllCapsUnderscore
+	err = cfg.MapTo(info)
+	// ...
+}
+```
+
 ## 获取帮助
 
 - [API 文档](https://gowalker.org/gopkg.in/ini.v1)

+ 82 - 9
Godeps/_workspace/src/gopkg.in/ini.v1/ini.go

@@ -27,14 +27,21 @@ import (
 	"strconv"
 	"strings"
 	"sync"
+	"time"
 )
 
 const (
 	DEFAULT_SECTION = "DEFAULT"
 	// Maximum allowed depth when recursively substituing variable names.
 	_DEPTH_VALUES = 99
+
+	_VERSION = "1.0.1"
 )
 
+func Version() string {
+	return _VERSION
+}
+
 var (
 	LineBreak = "\n"
 
@@ -157,6 +164,16 @@ func (k *Key) Int64() (int64, error) {
 	return strconv.ParseInt(k.String(), 10, 64)
 }
 
+// TimeFormat parses with given format and returns time.Time type value.
+func (k *Key) TimeFormat(format string) (time.Time, error) {
+	return time.Parse(format, k.String())
+}
+
+// Time parses with RFC3339 format and returns time.Time type value.
+func (k *Key) Time() (time.Time, error) {
+	return k.TimeFormat(time.RFC3339)
+}
+
 // MustString returns default value if key value is empty.
 func (k *Key) MustString(defaultVal string) string {
 	val := k.String()
@@ -179,31 +196,47 @@ func (k *Key) MustBool(defaultVal ...bool) bool {
 // MustFloat64 always returns value without error,
 // it returns 0.0 if error occurs.
 func (k *Key) MustFloat64(defaultVal ...float64) float64 {
-	value, err := k.Float64()
+	val, err := k.Float64()
 	if len(defaultVal) > 0 && err != nil {
 		return defaultVal[0]
 	}
-	return value
+	return val
 }
 
 // MustInt always returns value without error,
 // it returns 0 if error occurs.
 func (k *Key) MustInt(defaultVal ...int) int {
-	value, err := k.Int()
+	val, err := k.Int()
 	if len(defaultVal) > 0 && err != nil {
 		return defaultVal[0]
 	}
-	return value
+	return val
 }
 
 // MustInt64 always returns value without error,
 // it returns 0 if error occurs.
 func (k *Key) MustInt64(defaultVal ...int64) int64 {
-	value, err := k.Int64()
+	val, err := k.Int64()
+	if len(defaultVal) > 0 && err != nil {
+		return defaultVal[0]
+	}
+	return val
+}
+
+// MustTimeFormat always parses with given format and returns value without error,
+// it returns zero value if error occurs.
+func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time {
+	val, err := k.TimeFormat(format)
 	if len(defaultVal) > 0 && err != nil {
 		return defaultVal[0]
 	}
-	return value
+	return val
+}
+
+// MustTime always parses with RFC3339 format and returns value without error,
+// it returns zero value if error occurs.
+func (k *Key) MustTime(defaultVal ...time.Time) time.Time {
+	return k.MustTimeFormat(time.RFC3339, defaultVal...)
 }
 
 // In always returns value without error,
@@ -218,7 +251,7 @@ func (k *Key) In(defaultVal string, candidates []string) string {
 	return defaultVal
 }
 
-// In always returns value without error,
+// InFloat64 always returns value without error,
 // it returns default value if error occurs or doesn't fit into candidates.
 func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 {
 	val := k.MustFloat64()
@@ -230,7 +263,7 @@ func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 {
 	return defaultVal
 }
 
-// In always returns value without error,
+// InInt always returns value without error,
 // it returns default value if error occurs or doesn't fit into candidates.
 func (k *Key) InInt(defaultVal int, candidates []int) int {
 	val := k.MustInt()
@@ -242,7 +275,7 @@ func (k *Key) InInt(defaultVal int, candidates []int) int {
 	return defaultVal
 }
 
-// In always returns value without error,
+// InInt64 always returns value without error,
 // it returns default value if error occurs or doesn't fit into candidates.
 func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 {
 	val := k.MustInt64()
@@ -254,6 +287,24 @@ func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 {
 	return defaultVal
 }
 
+// InTimeFormat always parses with given format and returns value without error,
+// it returns default value if error occurs or doesn't fit into candidates.
+func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time {
+	val := k.MustTimeFormat(format)
+	for _, cand := range candidates {
+		if val == cand {
+			return val
+		}
+	}
+	return defaultVal
+}
+
+// InTime always parses with RFC3339 format and returns value without error,
+// it returns default value if error occurs or doesn't fit into candidates.
+func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time {
+	return k.InTimeFormat(time.RFC3339, defaultVal, candidates)
+}
+
 // Strings returns list of string devide by given delimiter.
 func (k *Key) Strings(delim string) []string {
 	str := k.String()
@@ -298,6 +349,21 @@ func (k *Key) Int64s(delim string) []int64 {
 	return vals
 }
 
+// TimesFormat parses with given format and returns list of time.Time devide by given delimiter.
+func (k *Key) TimesFormat(format, delim string) []time.Time {
+	strs := k.Strings(delim)
+	vals := make([]time.Time, len(strs))
+	for i := range strs {
+		vals[i], _ = time.Parse(format, strs[i])
+	}
+	return vals
+}
+
+// Times parses with RFC3339 format and returns list of time.Time devide by given delimiter.
+func (k *Key) Times(delim string) []time.Time {
+	return k.TimesFormat(time.RFC3339, delim)
+}
+
 // SetValue changes key value.
 func (k *Key) SetValue(v string) {
 	k.value = v
@@ -446,6 +512,8 @@ type File struct {
 
 	// To keep data in order.
 	sectionList []string
+
+	NameMapper
 }
 
 // newFile initializes File object with given data sources.
@@ -803,6 +871,11 @@ func (f *File) SaveTo(filename string) (err error) {
 			if _, err = buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
 				return err
 			}
+		} else {
+			// Write nothing if default section is empty.
+			if len(sec.keyList) == 0 {
+				continue
+			}
 		}
 
 		for _, kname := range sec.keyList {

+ 38 - 1
Godeps/_workspace/src/gopkg.in/ini.v1/ini_test.go

@@ -18,10 +18,17 @@ import (
 	"fmt"
 	"strings"
 	"testing"
+	"time"
 
 	. "github.com/smartystreets/goconvey/convey"
 )
 
+func Test_Version(t *testing.T) {
+	Convey("Get version", t, func() {
+		So(Version(), ShouldEqual, _VERSION)
+	})
+}
+
 const _CONF_DATA = `
 ; Package name
 NAME = ini
@@ -57,11 +64,13 @@ STRING = str
 BOOL = true
 FLOAT64 = 1.25
 INT = 10
+TIME = 2015-01-01T20:17:05Z
 
 [array]
 STRINGS = en, zh, de
 FLOAT64S = 1.1, 2.2, 3.3
 INTS = 1, 2, 3
+TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
 
 [note]
 
@@ -206,12 +215,19 @@ func Test_Values(t *testing.T) {
 			So(err, ShouldBeNil)
 			So(v4, ShouldEqual, 10)
 
+			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
+			So(err, ShouldBeNil)
+			v5, err := sec.Key("TIME").Time()
+			So(err, ShouldBeNil)
+			So(v5.String(), ShouldEqual, t.String())
+
 			Convey("Must get values with type", func() {
 				So(sec.Key("STRING").MustString("404"), ShouldEqual, "str")
 				So(sec.Key("BOOL").MustBool(), ShouldBeTrue)
 				So(sec.Key("FLOAT64").MustFloat64(), ShouldEqual, 1.25)
 				So(sec.Key("INT").MustInt(), ShouldEqual, 10)
 				So(sec.Key("INT").MustInt64(), ShouldEqual, 10)
+				So(sec.Key("TIME").MustTime().String(), ShouldEqual, t.String())
 
 				Convey("Must get values with default value", func() {
 					So(sec.Key("STRING_404").MustString("404"), ShouldEqual, "404")
@@ -219,6 +235,10 @@ func Test_Values(t *testing.T) {
 					So(sec.Key("FLOAT64_404").MustFloat64(2.5), ShouldEqual, 2.5)
 					So(sec.Key("INT_404").MustInt(15), ShouldEqual, 15)
 					So(sec.Key("INT_404").MustInt64(15), ShouldEqual, 15)
+
+					t, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z")
+					So(err, ShouldBeNil)
+					So(sec.Key("TIME_404").MustTime(t).String(), ShouldEqual, t.String())
 				})
 			})
 		})
@@ -230,11 +250,18 @@ func Test_Values(t *testing.T) {
 			So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10)
 			So(sec.Key("INT").InInt64(0, []int64{10, 20, 30}), ShouldEqual, 10)
 
+			zt, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
+			So(err, ShouldBeNil)
+			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
+			So(err, ShouldBeNil)
+			So(sec.Key("TIME").InTime(zt, []time.Time{t, time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())
+
 			Convey("Get value with candidates and default value", func() {
 				So(sec.Key("STRING_404").In("str", []string{"str", "arr", "types"}), ShouldEqual, "str")
 				So(sec.Key("FLOAT64_404").InFloat64(1.25, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
 				So(sec.Key("INT_404").InInt(10, []int{10, 20, 30}), ShouldEqual, 10)
 				So(sec.Key("INT64_404").InInt64(10, []int64{10, 20, 30}), ShouldEqual, 10)
+				So(sec.Key("TIME_404").InTime(t, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())
 			})
 		})
 
@@ -257,6 +284,13 @@ func Test_Values(t *testing.T) {
 			for i, v := range []int64{1, 2, 3} {
 				So(vals3[i], ShouldEqual, v)
 			}
+
+			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
+			So(err, ShouldBeNil)
+			vals4 := sec.Key("TIMES").Times(",")
+			for i, v := range []time.Time{t, t, t} {
+				So(vals4[i].String(), ShouldEqual, v.String())
+			}
 		})
 
 		Convey("Get key hash", func() {
@@ -270,7 +304,7 @@ func Test_Values(t *testing.T) {
 		})
 
 		Convey("Get key strings", func() {
-			So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,FLOAT64,INT")
+			So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,FLOAT64,INT,TIME")
 		})
 
 		Convey("Delete a key", func() {
@@ -338,6 +372,9 @@ func Test_File_SaveTo(t *testing.T) {
 		So(err, ShouldBeNil)
 		So(cfg, ShouldNotBeNil)
 
+		cfg.Section("").Key("NAME").Comment = "Package name"
+		cfg.Section("author").Comment = `Information about package author
+# Bio can be written in multiple lines.`
 		So(cfg.SaveTo("testdata/conf_out.ini"), ShouldBeNil)
 	})
 }

+ 214 - 0
Godeps/_workspace/src/gopkg.in/ini.v1/struct.go

@@ -0,0 +1,214 @@
+// Copyright 2014 Unknwon
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package ini
+
+import (
+	"errors"
+	"fmt"
+	"reflect"
+	"time"
+	"unicode"
+)
+
+// NameMapper represents a ini tag name mapper.
+type NameMapper func(string) string
+
+// Built-in name getters.
+var (
+	// AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
+	AllCapsUnderscore NameMapper = func(raw string) string {
+		newstr := make([]rune, 0, 10)
+		for i, chr := range raw {
+			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
+				if i > 0 {
+					newstr = append(newstr, '_')
+				}
+			}
+			newstr = append(newstr, unicode.ToUpper(chr))
+		}
+		return string(newstr)
+	}
+	// TitleUnderscore converts to format title_underscore.
+	TitleUnderscore NameMapper = func(raw string) string {
+		newstr := make([]rune, 0, 10)
+		for i, chr := range raw {
+			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
+				if i > 0 {
+					newstr = append(newstr, '_')
+				}
+				chr -= ('A' - 'a')
+			}
+			newstr = append(newstr, chr)
+		}
+		return string(newstr)
+	}
+)
+
+func (s *Section) parseFieldName(raw, actual string) string {
+	if len(actual) > 0 {
+		return actual
+	}
+	if s.f.NameMapper != nil {
+		return s.f.NameMapper(raw)
+	}
+	return raw
+}
+
+func parseDelim(actual string) string {
+	if len(actual) > 0 {
+		return actual
+	}
+	return ","
+}
+
+var reflectTime = reflect.TypeOf(time.Now()).Kind()
+
+func setWithProperType(kind reflect.Kind, key *Key, field reflect.Value, delim string) error {
+	switch kind {
+	case reflect.String:
+		field.SetString(key.String())
+	case reflect.Bool:
+		boolVal, err := key.Bool()
+		if err != nil {
+			return err
+		}
+		field.SetBool(boolVal)
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		intVal, err := key.Int64()
+		if err != nil {
+			return err
+		}
+		field.SetInt(intVal)
+	case reflect.Float64:
+		floatVal, err := key.Float64()
+		if err != nil {
+			return err
+		}
+		field.SetFloat(floatVal)
+	case reflectTime:
+		timeVal, err := key.Time()
+		if err != nil {
+			return err
+		}
+		field.Set(reflect.ValueOf(timeVal))
+	case reflect.Slice:
+		vals := key.Strings(delim)
+		numVals := len(vals)
+		if numVals == 0 {
+			return nil
+		}
+
+		sliceOf := field.Type().Elem().Kind()
+
+		var times []time.Time
+		if sliceOf == reflectTime {
+			times = key.Times(delim)
+		}
+
+		slice := reflect.MakeSlice(field.Type(), numVals, numVals)
+		for i := 0; i < numVals; i++ {
+			switch sliceOf {
+			case reflectTime:
+				slice.Index(i).Set(reflect.ValueOf(times[i]))
+			default:
+				slice.Index(i).Set(reflect.ValueOf(vals[i]))
+			}
+		}
+		field.Set(slice)
+	default:
+		return fmt.Errorf("unsupported type '%s'", kind)
+	}
+	return nil
+}
+
+func (s *Section) mapTo(val reflect.Value) error {
+	if val.Kind() == reflect.Ptr {
+		val = val.Elem()
+	}
+	typ := val.Type()
+
+	for i := 0; i < typ.NumField(); i++ {
+		field := val.Field(i)
+		tpField := typ.Field(i)
+
+		tag := tpField.Tag.Get("ini")
+		if tag == "-" {
+			continue
+		}
+
+		fieldName := s.parseFieldName(tpField.Name, tag)
+		if len(fieldName) == 0 || !field.CanSet() {
+			continue
+		}
+
+		if tpField.Type.Kind() == reflect.Struct {
+			if sec, err := s.f.GetSection(fieldName); err == nil {
+				if err = sec.mapTo(field); err != nil {
+					return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
+				}
+				continue
+			}
+		} else if tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous {
+			field.Set(reflect.New(tpField.Type.Elem()))
+			if sec, err := s.f.GetSection(fieldName); err == nil {
+				if err = sec.mapTo(field); err != nil {
+					return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
+				}
+				continue
+			}
+		}
+
+		if key, err := s.GetKey(fieldName); err == nil {
+			if err = setWithProperType(tpField.Type.Kind(), key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
+				return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
+			}
+		}
+	}
+	return nil
+}
+
+// MapTo maps section to given struct.
+func (s *Section) MapTo(v interface{}) error {
+	typ := reflect.TypeOf(v)
+	val := reflect.ValueOf(v)
+	if typ.Kind() == reflect.Ptr {
+		typ = typ.Elem()
+		val = val.Elem()
+	} else {
+		return errors.New("cannot map to non-pointer struct")
+	}
+
+	return s.mapTo(val)
+}
+
+// MapTo maps file to given struct.
+func (f *File) MapTo(v interface{}) error {
+	return f.Section("").MapTo(v)
+}
+
+// MapTo maps data sources to given struct with name mapper.
+func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
+	cfg, err := Load(source, others...)
+	if err != nil {
+		return err
+	}
+	cfg.NameMapper = mapper
+	return cfg.MapTo(v)
+}
+
+// MapTo maps data sources to given struct.
+func MapTo(v, source interface{}, others ...interface{}) error {
+	return MapToWithMapper(v, nil, source, others...)
+}

+ 183 - 0
Godeps/_workspace/src/gopkg.in/ini.v1/struct_test.go

@@ -0,0 +1,183 @@
+// Copyright 2014 Unknwon
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package ini
+
+import (
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/smartystreets/goconvey/convey"
+)
+
+type testNested struct {
+	Cities []string `delim:"|"`
+	Visits []time.Time
+	Note   string
+	Unused int `ini:"-"`
+}
+
+type testEmbeded struct {
+	GPA float64
+}
+
+type testStruct struct {
+	Name         string `ini:"NAME"`
+	Age          int
+	Male         bool
+	Money        float64
+	Born         time.Time
+	Others       testNested
+	*testEmbeded `ini:"grade"`
+	Unused       int `ini:"-"`
+}
+
+const _CONF_DATA_STRUCT = `
+NAME = Unknwon
+Age = 21
+Male = true
+Money = 1.25
+Born = 1993-10-07T20:17:05Z
+
+[Others]
+Cities = HangZhou|Boston
+Visits = 1993-10-07T20:17:05Z, 1993-10-07T20:17:05Z
+Note = Hello world!
+
+[grade]
+GPA = 2.8
+`
+
+type unsupport struct {
+	Byte byte
+}
+
+type unsupport2 struct {
+	Others struct {
+		Cities byte
+	}
+}
+
+type unsupport3 struct {
+	Cities byte
+}
+
+type unsupport4 struct {
+	*unsupport3 `ini:"Others"`
+}
+
+type invalidInt struct {
+	Age int
+}
+
+type invalidBool struct {
+	Male bool
+}
+
+type invalidFloat struct {
+	Money float64
+}
+
+type invalidTime struct {
+	Born time.Time
+}
+
+type emptySlice struct {
+	Cities []string
+}
+
+const _INVALID_DATA_CONF_STRUCT = `
+Age = age
+Male = 123
+Money = money
+Born = nil
+Cities = 
+`
+
+func Test_Struct(t *testing.T) {
+	Convey("Map file to struct", t, func() {
+		ts := new(testStruct)
+		So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)
+
+		So(ts.Name, ShouldEqual, "Unknwon")
+		So(ts.Age, ShouldEqual, 21)
+		So(ts.Male, ShouldBeTrue)
+		So(ts.Money, ShouldEqual, 1.25)
+
+		t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
+		So(err, ShouldBeNil)
+		So(ts.Born.String(), ShouldEqual, t.String())
+
+		So(strings.Join(ts.Others.Cities, ","), ShouldEqual, "HangZhou,Boston")
+		So(ts.Others.Visits[0].String(), ShouldEqual, t.String())
+		So(ts.Others.Note, ShouldEqual, "Hello world!")
+		So(ts.testEmbeded.GPA, ShouldEqual, 2.8)
+	})
+
+	Convey("Map to non-pointer struct", t, func() {
+		cfg, err := Load([]byte(_CONF_DATA_STRUCT))
+		So(err, ShouldBeNil)
+		So(cfg, ShouldNotBeNil)
+
+		So(cfg.MapTo(testStruct{}), ShouldNotBeNil)
+	})
+
+	Convey("Map to unsupported type", t, func() {
+		cfg, err := Load([]byte(_CONF_DATA_STRUCT))
+		So(err, ShouldBeNil)
+		So(cfg, ShouldNotBeNil)
+
+		cfg.NameMapper = func(raw string) string {
+			if raw == "Byte" {
+				return "NAME"
+			}
+			return raw
+		}
+		So(cfg.MapTo(&unsupport{}), ShouldNotBeNil)
+		So(cfg.MapTo(&unsupport2{}), ShouldNotBeNil)
+		So(cfg.MapTo(&unsupport4{}), ShouldNotBeNil)
+	})
+
+	Convey("Map from invalid data source", t, func() {
+		So(MapTo(&testStruct{}, "hi"), ShouldNotBeNil)
+	})
+
+	Convey("Map to wrong types", t, func() {
+		So(MapTo(&invalidInt{}, []byte(_INVALID_DATA_CONF_STRUCT)), ShouldNotBeNil)
+		So(MapTo(&invalidBool{}, []byte(_INVALID_DATA_CONF_STRUCT)), ShouldNotBeNil)
+		So(MapTo(&invalidFloat{}, []byte(_INVALID_DATA_CONF_STRUCT)), ShouldNotBeNil)
+		So(MapTo(&invalidTime{}, []byte(_INVALID_DATA_CONF_STRUCT)), ShouldNotBeNil)
+		So(MapTo(&emptySlice{}, []byte(_INVALID_DATA_CONF_STRUCT)), ShouldBeNil)
+	})
+}
+
+type testMapper struct {
+	PackageName string
+}
+
+func Test_NameGetter(t *testing.T) {
+	Convey("Test name mappers", t, func() {
+		So(MapToWithMapper(&testMapper{}, TitleUnderscore, []byte("packag_name=ini")), ShouldBeNil)
+
+		cfg, err := Load([]byte("PACKAGE_NAME=ini"))
+		So(err, ShouldBeNil)
+		So(cfg, ShouldNotBeNil)
+
+		cfg.NameMapper = AllCapsUnderscore
+		tg := new(testMapper)
+		So(cfg.MapTo(tg), ShouldBeNil)
+		So(tg.PackageName, ShouldEqual, "ini")
+	})
+}