[DRE-commits] [ruby-oauth] 02/05: manually add 0.5.3

Praveen Arimbrathodiyil praveen at moszumanska.debian.org
Tue Jul 11 15:26:20 UTC 2017


This is an automated email from the git hooks/post-receive script.

praveen pushed a commit to branch master
in repository ruby-oauth.

commit ae1cc1c452d59a676bcfcc16ceeb8913a284866b
Author: Pirate Praveen <praveen at debian.org>
Date:   Mon Jul 10 19:18:05 2017 +0530

    manually add 0.5.3
---
 .codeclimate.yml                                   |   16 +
 .gitignore                                         |    4 +
 .rubocop.yml                                       | 1156 ++++++++++++++++++++
 .travis.yml                                        |   16 +
 Gemfile                                            |   17 +-
 Gemfile.lock                                       |   47 -
 HISTORY                                            |   77 +-
 README.rdoc                                        |   30 +-
 Rakefile                                           |   28 +-
 bin/oauth                                          |   10 +-
 lib/digest/hmac.rb                                 |  104 --
 lib/oauth.rb                                       |    7 +-
 lib/oauth/cli.rb                                   |  396 +------
 lib/oauth/cli/authorize_command.rb                 |   71 ++
 lib/oauth/cli/base_command.rb                      |  208 ++++
 lib/oauth/cli/help_command.rb                      |   22 +
 lib/oauth/cli/query_command.rb                     |   25 +
 lib/oauth/cli/sign_command.rb                      |   81 ++
 lib/oauth/cli/version_command.rb                   |    7 +
 lib/oauth/client/action_controller_request.rb      |    1 -
 lib/oauth/client/em_http.rb                        |    1 -
 lib/oauth/client/helper.rb                         |    4 +
 lib/oauth/client/net_http.rb                       |   17 +-
 lib/oauth/consumer.rb                              |   43 +-
 lib/oauth/core_ext.rb                              |   26 +-
 lib/oauth/helper.rb                                |   18 +-
 .../request_proxy/action_controller_request.rb     |   30 +-
 lib/oauth/request_proxy/base.rb                    |   10 +-
 lib/oauth/request_proxy/net_http.rb                |    2 +-
 lib/oauth/request_proxy/rest_client_request.rb     |   62 ++
 lib/oauth/request_proxy/typhoeus_request.rb        |    7 +-
 lib/oauth/signature/base.rb                        |   32 +-
 lib/oauth/signature/hmac/base.rb                   |   15 -
 lib/oauth/signature/hmac/md5.rb                    |    8 -
 lib/oauth/signature/hmac/rmd160.rb                 |    8 -
 lib/oauth/signature/hmac/sha1.rb                   |   16 +-
 lib/oauth/signature/hmac/sha2.rb                   |    8 -
 lib/oauth/signature/md5.rb                         |   13 -
 lib/oauth/signature/plaintext.rb                   |    6 +
 lib/oauth/signature/rsa/sha1.rb                    |   10 +-
 lib/oauth/signature/sha1.rb                        |   13 -
 lib/oauth/tokens/access_token.rb                   |   12 +
 lib/oauth/tokens/request_token.rb                  |    7 +-
 lib/oauth/tokens/token.rb                          |    2 +-
 lib/oauth/version.rb                               |    3 +
 metadata.yml                                       |  270 -----
 oauth.gemspec                                      |  179 +--
 tasks/deployment.rake                              |   34 -
 tasks/environment.rake                             |    7 -
 tasks/website.rake                                 |   17 -
 test/cases/oauth_case.rb                           |    5 +-
 .../1_0-final/test_normalize_request_parameters.rb |    4 +-
 test/integration/consumer_test.rb                  |   36 +-
 test/support/minitest_helpers.rb                   |   22 +
 test/test_helper.rb                                |   48 +-
 test/test_signature.rb                             |   22 -
 test/{ => units}/test_access_token.rb              |    6 +-
 .../test_action_controller_request_proxy.rb        |   36 +-
 test/units/test_cli.rb                             |  304 +++++
 test/{ => units}/test_consumer.rb                  |   58 +-
 test/{ => units}/test_curb_request_proxy.rb        |    4 +-
 test/{ => units}/test_em_http_client.rb            |    4 +-
 test/{ => units}/test_em_http_request_proxy.rb     |    4 +-
 test/{ => units}/test_hmac_sha1.rb                 |    4 +-
 test/{ => units}/test_net_http_client.rb           |   46 +-
 test/{ => units}/test_net_http_request_proxy.rb    |    4 +-
 test/{ => units}/test_oauth_helper.rb              |   12 +-
 test/{ => units}/test_rack_request_proxy.rb        |    7 +-
 test/{ => units}/test_request_token.rb             |   15 +-
 test/units/test_rest_client_request_proxy.rb       |   81 ++
 test/{ => units}/test_rsa_sha1.rb                  |   42 +-
 test/{ => units}/test_server.rb                    |   16 +-
 test/units/test_signature.rb                       |   15 +
 test/{ => units}/test_signature_base.rb            |   15 +-
 test/units/test_signature_hmac_sha1.rb             |   41 +
 test/{ => units}/test_signature_plain_text.rb      |    5 +-
 test/{ => units}/test_token.rb                     |    5 +-
 test/{ => units}/test_typhoeus_request_proxy.rb    |   29 +-
 78 files changed, 2757 insertions(+), 1336 deletions(-)

diff --git a/.codeclimate.yml b/.codeclimate.yml
new file mode 100644
index 0000000..9303219
--- /dev/null
+++ b/.codeclimate.yml
@@ -0,0 +1,16 @@
+---
+engines:
+  duplication:
+    enabled: true
+    config:
+      languages:
+      - ruby
+  fixme:
+    enabled: true
+  rubocop:
+    enabled: true
+ratings:
+  paths:
+  - "**.rb"
+exclude_paths:
+- test/
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ff17441
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.bundle
+Gemfile.lock
+coverage
+*.gem
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..3f1d222
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,1156 @@
+AllCops:
+  DisabledByDefault: true
+
+#################### Lint ################################
+
+Lint/AmbiguousOperator:
+  Description: >-
+                 Checks for ambiguous operators in the first argument of a
+                 method invocation without parentheses.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-as-args'
+  Enabled: true
+
+Lint/AmbiguousRegexpLiteral:
+  Description: >-
+                 Checks for ambiguous regexp literals in the first argument of
+                 a method invocation without parenthesis.
+  Enabled: true
+
+Lint/AssignmentInCondition:
+  Description: "Don't use assignment in conditions."
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition'
+  Enabled: true
+
+Lint/BlockAlignment:
+  Description: 'Align block ends correctly.'
+  Enabled: true
+
+Lint/CircularArgumentReference:
+  Description: "Don't refer to the keyword argument in the default value."
+  Enabled: true
+
+Lint/ConditionPosition:
+  Description: >-
+                 Checks for condition placed in a confusing position relative to
+                 the keyword.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#same-line-condition'
+  Enabled: true
+
+Lint/Debugger:
+  Description: 'Check for debugger calls.'
+  Enabled: true
+
+Lint/DefEndAlignment:
+  Description: 'Align ends corresponding to defs correctly.'
+  Enabled: true
+
+Lint/DeprecatedClassMethods:
+  Description: 'Check for deprecated class method calls.'
+  Enabled: true
+
+Lint/DuplicateMethods:
+  Description: 'Check for duplicate methods calls.'
+  Enabled: true
+
+Lint/EachWithObjectArgument:
+  Description: 'Check for immutable argument given to each_with_object.'
+  Enabled: true
+
+Lint/ElseLayout:
+  Description: 'Check for odd code arrangement in an else block.'
+  Enabled: true
+
+Lint/EmptyEnsure:
+  Description: 'Checks for empty ensure block.'
+  Enabled: true
+
+Lint/EmptyInterpolation:
+  Description: 'Checks for empty string interpolation.'
+  Enabled: true
+
+Lint/EndAlignment:
+  Description: 'Align ends correctly.'
+  Enabled: true
+
+Lint/EndInMethod:
+  Description: 'END blocks should not be placed inside method definitions.'
+  Enabled: true
+
+Lint/EnsureReturn:
+  Description: 'Do not use return in an ensure block.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-return-ensure'
+  Enabled: true
+
+Lint/Eval:
+  Description: 'The use of eval represents a serious security risk.'
+  Enabled: true
+
+Lint/FormatParameterMismatch:
+  Description: 'The number of parameters to format/sprint must match the fields.'
+  Enabled: true
+
+Lint/HandleExceptions:
+  Description: "Don't suppress exception."
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions'
+  Enabled: true
+
+Lint/InvalidCharacterLiteral:
+  Description: >-
+                 Checks for invalid character literals with a non-escaped
+                 whitespace character.
+  Enabled: true
+
+Lint/LiteralInCondition:
+  Description: 'Checks of literals used in conditions.'
+  Enabled: true
+
+Lint/LiteralInInterpolation:
+  Description: 'Checks for literals used in interpolation.'
+  Enabled: true
+
+Lint/Loop:
+  Description: >-
+                 Use Kernel#loop with break rather than begin/end/until or
+                 begin/end/while for post-loop tests.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#loop-with-break'
+  Enabled: true
+
+Lint/NestedMethodDefinition:
+  Description: 'Do not use nested method definitions.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-methods'
+  Enabled: true
+
+Lint/NonLocalExitFromIterator:
+  Description: 'Do not use return in iterator to cause non-local exit.'
+  Enabled: true
+
+Lint/ParenthesesAsGroupedExpression:
+  Description: >-
+                 Checks for method calls with a space before the opening
+                 parenthesis.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-no-spaces'
+  Enabled: true
+
+Lint/RequireParentheses:
+  Description: >-
+                 Use parentheses in the method call to avoid confusion
+                 about precedence.
+  Enabled: true
+
+Lint/RescueException:
+  Description: 'Avoid rescuing the Exception class.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-blind-rescues'
+  Enabled: true
+
+Lint/ShadowingOuterLocalVariable:
+  Description: >-
+                 Do not use the same name as outer local variable
+                 for block arguments or block local variables.
+  Enabled: true
+
+Lint/StringConversionInInterpolation:
+  Description: 'Checks for Object#to_s usage in string interpolation.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-to-s'
+  Enabled: true
+
+Lint/UnderscorePrefixedVariableName:
+  Description: 'Do not use prefix `_` for a variable that is used.'
+  Enabled: true
+
+Lint/UnneededDisable:
+  Description: >-
+                 Checks for rubocop:disable comments that can be removed.
+                 Note: this cop is not disabled when disabling all cops.
+                 It must be explicitly disabled.
+  Enabled: true
+
+Lint/UnusedBlockArgument:
+  Description: 'Checks for unused block arguments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars'
+  Enabled: true
+
+Lint/UnusedMethodArgument:
+  Description: 'Checks for unused method arguments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars'
+  Enabled: true
+
+Lint/UnreachableCode:
+  Description: 'Unreachable code.'
+  Enabled: true
+
+Lint/UselessAccessModifier:
+  Description: 'Checks for useless access modifiers.'
+  Enabled: true
+
+Lint/UselessAssignment:
+  Description: 'Checks for useless assignment to a local variable.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars'
+  Enabled: true
+
+Lint/UselessComparison:
+  Description: 'Checks for comparison of something with itself.'
+  Enabled: true
+
+Lint/UselessElseWithoutRescue:
+  Description: 'Checks for useless `else` in `begin..end` without `rescue`.'
+  Enabled: true
+
+Lint/UselessSetterCall:
+  Description: 'Checks for useless setter call to a local variable.'
+  Enabled: true
+
+Lint/Void:
+  Description: 'Possible use of operator/literal/variable in void context.'
+  Enabled: true
+
+###################### Metrics ####################################
+
+Metrics/AbcSize:
+  Description: >-
+                 A calculated magnitude based on number of assignments,
+                 branches, and conditions.
+  Reference: 'http://c2.com/cgi/wiki?AbcMetric'
+  Enabled: false
+  Max: 20
+
+Metrics/BlockNesting:
+  Description: 'Avoid excessive block nesting'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#three-is-the-number-thou-shalt-count'
+  Enabled: true
+  Max: 4
+
+Metrics/ClassLength:
+  Description: 'Avoid classes longer than 250 lines of code.'
+  Enabled: true
+  Max: 250
+
+Metrics/CyclomaticComplexity:
+  Description: >-
+                 A complexity metric that is strongly correlated to the number
+                 of test cases needed to validate a method.
+  Enabled: true
+
+Metrics/LineLength:
+  Description: 'Limit lines to 80 characters.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#80-character-limits'
+  Enabled: false
+
+Metrics/MethodLength:
+  Description: 'Avoid methods longer than 30 lines of code.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods'
+  Enabled: true
+  Max: 30
+
+Metrics/ModuleLength:
+  Description: 'Avoid modules longer than 250 lines of code.'
+  Enabled: true
+  Max: 250
+
+Metrics/ParameterLists:
+  Description: 'Avoid parameter lists longer than three or four parameters.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#too-many-params'
+  Enabled: true
+
+Metrics/PerceivedComplexity:
+  Description: >-
+                 A complexity metric geared towards measuring complexity for a
+                 human reader.
+  Enabled: false
+
+##################### Performance #############################
+
+Performance/Count:
+  Description: >-
+                  Use `count` instead of `select...size`, `reject...size`,
+                  `select...count`, `reject...count`, `select...length`,
+                  and `reject...length`.
+  Enabled: true
+
+Performance/Detect:
+  Description: >-
+                  Use `detect` instead of `select.first`, `find_all.first`,
+                  `select.last`, and `find_all.last`.
+  Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerabledetect-vs-enumerableselectfirst-code'
+  Enabled: true
+
+Performance/FlatMap:
+  Description: >-
+                  Use `Enumerable#flat_map`
+                  instead of `Enumerable#map...Array#flatten(1)`
+                  or `Enumberable#collect..Array#flatten(1)`
+  Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerablemaparrayflatten-vs-enumerableflat_map-code'
+  Enabled: true
+  EnabledForFlattenWithoutParams: false
+  # If enabled, this cop will warn about usages of
+  # `flatten` being called without any parameters.
+  # This can be dangerous since `flat_map` will only flatten 1 level, and
+  # `flatten` without any parameters can flatten multiple levels.
+
+Performance/ReverseEach:
+  Description: 'Use `reverse_each` instead of `reverse.each`.'
+  Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerablereverseeach-vs-enumerablereverse_each-code'
+  Enabled: true
+
+Performance/Sample:
+  Description: >-
+                  Use `sample` instead of `shuffle.first`,
+                  `shuffle.last`, and `shuffle[Fixnum]`.
+  Reference: 'https://github.com/JuanitoFatas/fast-ruby#arrayshufflefirst-vs-arraysample-code'
+  Enabled: true
+
+Performance/Size:
+  Description: >-
+                  Use `size` instead of `count` for counting
+                  the number of elements in `Array` and `Hash`.
+  Reference: 'https://github.com/JuanitoFatas/fast-ruby#arraycount-vs-arraysize-code'
+  Enabled: true
+
+Performance/StringReplacement:
+  Description: >-
+                  Use `tr` instead of `gsub` when you are replacing the same
+                  number of characters. Use `delete` instead of `gsub` when
+                  you are deleting characters.
+  Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringgsub-vs-stringtr-code'
+  Enabled: true
+
+##################### Rails ##################################
+
+Rails/ActionFilter:
+  Description: 'Enforces consistent use of action filter methods.'
+  Enabled: false
+
+Rails/Date:
+  Description: >-
+                  Checks the correct usage of date aware methods,
+                  such as Date.today, Date.current etc.
+  Enabled: false
+
+Rails/Delegate:
+  Description: 'Prefer delegate method for delegations.'
+  Enabled: false
+
+Rails/FindBy:
+  Description: 'Prefer find_by over where.first.'
+  Enabled: false
+
+Rails/FindEach:
+  Description: 'Prefer all.find_each over all.find.'
+  Enabled: false
+
+Rails/HasAndBelongsToMany:
+  Description: 'Prefer has_many :through to has_and_belongs_to_many.'
+  Enabled: false
+
+Rails/Output:
+  Description: 'Checks for calls to puts, print, etc.'
+  Enabled: false
+
+Rails/ReadWriteAttribute:
+  Description: >-
+                 Checks for read_attribute(:attr) and
+                 write_attribute(:attr, val).
+  Enabled: false
+
+Rails/ScopeArgs:
+  Description: 'Checks the arguments of ActiveRecord scopes.'
+  Enabled: false
+
+Rails/TimeZone:
+  Description: 'Checks the correct usage of time zone aware methods.'
+  StyleGuide: 'https://github.com/bbatsov/rails-style-guide#time'
+  Reference: 'http://danilenko.org/2012/7/6/rails_timezones'
+  Enabled: false
+
+Rails/Validation:
+  Description: 'Use validates :attribute, hash of validations.'
+  Enabled: false
+
+################## Style #################################
+
+Style/AccessModifierIndentation:
+  Description: Check indentation of private/protected visibility modifiers.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-public-private-protected'
+  Enabled: false
+
+Style/AccessorMethodName:
+  Description: Check the naming of accessor methods for get_/set_.
+  Enabled: false
+
+Style/Alias:
+  Description: 'Use alias_method instead of alias.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#alias-method'
+  Enabled: false
+
+Style/AlignArray:
+  Description: >-
+                 Align the elements of an array literal if they span more than
+                 one line.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#align-multiline-arrays'
+  Enabled: false
+
+Style/AlignHash:
+  Description: >-
+                 Align the elements of a hash literal if they span more than
+                 one line.
+  Enabled: false
+
+Style/AlignParameters:
+  Description: >-
+                 Align the parameters of a method call if they span more
+                 than one line.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-double-indent'
+  Enabled: false
+
+Style/AndOr:
+  Description: 'Use &&/|| instead of and/or.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-and-or-or'
+  Enabled: false
+
+Style/ArrayJoin:
+  Description: 'Use Array#join instead of Array#*.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#array-join'
+  Enabled: false
+
+Style/AsciiComments:
+  Description: 'Use only ascii symbols in comments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-comments'
+  Enabled: false
+
+Style/AsciiIdentifiers:
+  Description: 'Use only ascii symbols in identifiers.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-identifiers'
+  Enabled: false
+
+Style/Attr:
+  Description: 'Checks for uses of Module#attr.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr'
+  Enabled: false
+
+Style/BeginBlock:
+  Description: 'Avoid the use of BEGIN blocks.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-BEGIN-blocks'
+  Enabled: false
+
+Style/BarePercentLiterals:
+  Description: 'Checks if usage of %() or %Q() matches configuration.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q-shorthand'
+  Enabled: false
+
+Style/BlockComments:
+  Description: 'Do not use block comments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-block-comments'
+  Enabled: false
+
+Style/BlockEndNewline:
+  Description: 'Put end statement of multiline block on its own line.'
+  Enabled: false
+
+Style/BlockDelimiters:
+  Description: >-
+                Avoid using {...} for multi-line blocks (multiline chaining is
+                always ugly).
+                Prefer {...} over do...end for single-line blocks.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks'
+  Enabled: false
+
+Style/BracesAroundHashParameters:
+  Description: 'Enforce braces style around hash parameters.'
+  Enabled: false
+
+Style/CaseEquality:
+  Description: 'Avoid explicit use of the case equality operator(===).'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-case-equality'
+  Enabled: false
+
+Style/CaseIndentation:
+  Description: 'Indentation of when in a case/when/[else/]end.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-when-to-case'
+  Enabled: false
+
+Style/CharacterLiteral:
+  Description: 'Checks for uses of character literals.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-character-literals'
+  Enabled: false
+
+Style/ClassAndModuleCamelCase:
+  Description: 'Use CamelCase for classes and modules.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#camelcase-classes'
+  Enabled: false
+
+Style/ClassAndModuleChildren:
+  Description: 'Checks style of children classes and modules.'
+  Enabled: false
+
+Style/ClassCheck:
+  Description: 'Enforces consistent use of `Object#is_a?` or `Object#kind_of?`.'
+  Enabled: false
+
+Style/ClassMethods:
+  Description: 'Use self when defining module/class methods.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#def-self-class-methods'
+  Enabled: false
+
+Style/ClassVars:
+  Description: 'Avoid the use of class variables.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-class-vars'
+  Enabled: false
+
+Style/ClosingParenthesisIndentation:
+  Description: 'Checks the indentation of hanging closing parentheses.'
+  Enabled: false
+
+Style/ColonMethodCall:
+  Description: 'Do not use :: for method call.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#double-colons'
+  Enabled: false
+
+Style/CommandLiteral:
+  Description: 'Use `` or %x around command literals.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-x'
+  Enabled: false
+
+Style/CommentAnnotation:
+  Description: 'Checks formatting of annotation comments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#annotate-keywords'
+  Enabled: false
+
+Style/CommentIndentation:
+  Description: 'Indentation of comments.'
+  Enabled: false
+
+Style/ConstantName:
+  Description: 'Constants should use SCREAMING_SNAKE_CASE.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#screaming-snake-case'
+  Enabled: false
+
+Style/DefWithParentheses:
+  Description: 'Use def with parentheses when there are arguments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens'
+  Enabled: false
+
+Style/DeprecatedHashMethods:
+  Description: 'Checks for use of deprecated Hash methods.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-key'
+  Enabled: false
+
+Style/Documentation:
+  Description: 'Document classes and non-namespace modules.'
+  Enabled: false
+
+Style/DotPosition:
+  Description: 'Checks the position of the dot in multi-line method calls.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains'
+  Enabled: false
+
+Style/DoubleNegation:
+  Description: 'Checks for uses of double negation (!!).'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-bang-bang'
+  Enabled: false
+
+Style/EachWithObject:
+  Description: 'Prefer `each_with_object` over `inject` or `reduce`.'
+  Enabled: false
+
+Style/ElseAlignment:
+  Description: 'Align elses and elsifs correctly.'
+  Enabled: false
+
+Style/EmptyElse:
+  Description: 'Avoid empty else-clauses.'
+  Enabled: false
+
+Style/EmptyLineBetweenDefs:
+  Description: 'Use empty lines between defs.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#empty-lines-between-methods'
+  Enabled: false
+
+Style/EmptyLines:
+  Description: "Don't use several empty lines in a row."
+  Enabled: false
+
+Style/EmptyLinesAroundAccessModifier:
+  Description: "Keep blank lines around access modifiers."
+  Enabled: false
+
+Style/EmptyLinesAroundBlockBody:
+  Description: "Keeps track of empty lines around block bodies."
+  Enabled: false
+
+Style/EmptyLinesAroundClassBody:
+  Description: "Keeps track of empty lines around class bodies."
+  Enabled: false
+
+Style/EmptyLinesAroundModuleBody:
+  Description: "Keeps track of empty lines around module bodies."
+  Enabled: false
+
+Style/EmptyLinesAroundMethodBody:
+  Description: "Keeps track of empty lines around method bodies."
+  Enabled: false
+
+Style/EmptyLiteral:
+  Description: 'Prefer literals to Array.new/Hash.new/String.new.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#literal-array-hash'
+  Enabled: false
+
+Style/EndBlock:
+  Description: 'Avoid the use of END blocks.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-END-blocks'
+  Enabled: false
+
+Style/EndOfLine:
+  Description: 'Use Unix-style line endings.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#crlf'
+  Enabled: false
+
+Style/EvenOdd:
+  Description: 'Favor the use of Fixnum#even? && Fixnum#odd?'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods'
+  Enabled: false
+
+Style/ExtraSpacing:
+  Description: 'Do not use unnecessary spacing.'
+  Enabled: false
+
+Style/FileName:
+  Description: 'Use snake_case for source file names.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-files'
+  Enabled: false
+
+Style/InitialIndentation:
+  Description: >-
+    Checks the indentation of the first non-blank non-comment line in a file.
+  Enabled: false
+
+Style/FirstParameterIndentation:
+  Description: 'Checks the indentation of the first parameter in a method call.'
+  Enabled: false
+
+Style/FlipFlop:
+  Description: 'Checks for flip flops'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-flip-flops'
+  Enabled: false
+
+Style/For:
+  Description: 'Checks use of for or each in multiline loops.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-for-loops'
+  Enabled: false
+
+Style/FormatString:
+  Description: 'Enforce the use of Kernel#sprintf, Kernel#format or String#%.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#sprintf'
+  Enabled: false
+
+Style/GlobalVars:
+  Description: 'Do not introduce global variables.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#instance-vars'
+  Reference: 'http://www.zenspider.com/Languages/Ruby/QuickRef.html'
+  Enabled: false
+
+Style/GuardClause:
+  Description: 'Check for conditionals that can be replaced with guard clauses'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals'
+  Enabled: false
+
+Style/HashSyntax:
+  Description: >-
+                 Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax
+                 { :a => 1, :b => 2 }.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-literals'
+  Enabled: false
+
+Style/IfUnlessModifier:
+  Description: >-
+                 Favor modifier if/unless usage when you have a
+                 single-line body.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier'
+  Enabled: false
+
+Style/IfWithSemicolon:
+  Description: 'Do not use if x; .... Use the ternary operator instead.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-semicolon-ifs'
+  Enabled: false
+
+Style/IndentationConsistency:
+  Description: 'Keep indentation straight.'
+  Enabled: false
+
+Style/IndentationWidth:
+  Description: 'Use 2 spaces for indentation.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-indentation'
+  Enabled: false
+
+Style/IndentArray:
+  Description: >-
+                 Checks the indentation of the first element in an array
+                 literal.
+  Enabled: false
+
+Style/IndentHash:
+  Description: 'Checks the indentation of the first key in a hash literal.'
+  Enabled: false
+
+Style/InfiniteLoop:
+  Description: 'Use Kernel#loop for infinite loops.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#infinite-loop'
+  Enabled: false
+
+Style/Lambda:
+  Description: 'Use the new lambda literal syntax for single-line blocks.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#lambda-multi-line'
+  Enabled: false
+
+Style/LambdaCall:
+  Description: 'Use lambda.call(...) instead of lambda.(...).'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#proc-call'
+  Enabled: false
+
+Style/LeadingCommentSpace:
+  Description: 'Comments should start with a space.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-space'
+  Enabled: false
+
+Style/LineEndConcatenation:
+  Description: >-
+                 Use \ instead of + or << to concatenate two string literals at
+                 line end.
+  Enabled: false
+
+Style/MethodCallParentheses:
+  Description: 'Do not use parentheses for method calls with no arguments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-args-no-parens'
+  Enabled: false
+
+Style/MethodDefParentheses:
+  Description: >-
+                 Checks if the method definitions have or don't have
+                 parentheses.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens'
+  Enabled: false
+
+Style/MethodName:
+  Description: 'Use the configured style when naming methods.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars'
+  Enabled: false
+
+Style/ModuleFunction:
+  Description: 'Checks for usage of `extend self` in modules.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#module-function'
+  Enabled: false
+
+Style/MultilineBlockChain:
+  Description: 'Avoid multi-line chains of blocks.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks'
+  Enabled: false
+
+Style/MultilineBlockLayout:
+  Description: 'Ensures newlines after multiline block do statements.'
+  Enabled: false
+
+Style/MultilineIfThen:
+  Description: 'Do not use then for multi-line if/unless.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-then'
+  Enabled: false
+
+Style/MultilineOperationIndentation:
+  Description: >-
+                 Checks indentation of binary operations that span more than
+                 one line.
+  Enabled: false
+
+Style/MultilineTernaryOperator:
+  Description: >-
+                 Avoid multi-line ?: (the ternary operator);
+                 use if/unless instead.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-multiline-ternary'
+  Enabled: false
+
+Style/NegatedIf:
+  Description: >-
+                 Favor unless over if for negative conditions
+                 (or control flow or).
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#unless-for-negatives'
+  Enabled: false
+
+Style/NegatedWhile:
+  Description: 'Favor until over while for negative conditions.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#until-for-negatives'
+  Enabled: false
+
+Style/NestedTernaryOperator:
+  Description: 'Use one expression per branch in a ternary operator.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-ternary'
+  Enabled: false
+
+Style/Next:
+  Description: 'Use `next` to skip iteration instead of a condition at the end.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals'
+  Enabled: false
+
+Style/NilComparison:
+  Description: 'Prefer x.nil? to x == nil.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods'
+  Enabled: false
+
+Style/NonNilCheck:
+  Description: 'Checks for redundant nil checks.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-non-nil-checks'
+  Enabled: false
+
+Style/Not:
+  Description: 'Use ! instead of not.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bang-not-not'
+  Enabled: false
+
+Style/NumericLiterals:
+  Description: >-
+                 Add underscores to large numeric literals to improve their
+                 readability.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscores-in-numerics'
+  Enabled: false
+
+Style/OneLineConditional:
+  Description: >-
+                 Favor the ternary operator(?:) over
+                 if/then/else/end constructs.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#ternary-operator'
+  Enabled: false
+
+Style/OpMethod:
+  Description: 'When defining binary operators, name the argument other.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#other-arg'
+  Enabled: false
+
+Style/OptionalArguments:
+  Description: >-
+                 Checks for optional arguments that do not appear at the end
+                 of the argument list
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#optional-arguments'
+  Enabled: false
+
+Style/ParallelAssignment:
+  Description: >-
+                  Check for simple usages of parallel assignment.
+                  It will only warn when the number of variables
+                  matches on both sides of the assignment.
+                  This also provides performance benefits
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parallel-assignment'
+  Enabled: false
+
+Style/ParenthesesAroundCondition:
+  Description: >-
+                 Don't use parentheses around the condition of an
+                 if/unless/while.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-parens-if'
+  Enabled: false
+
+Style/PercentLiteralDelimiters:
+  Description: 'Use `%`-literal delimiters consistently'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-literal-braces'
+  Enabled: false
+
+Style/PercentQLiterals:
+  Description: 'Checks if uses of %Q/%q match the configured preference.'
+  Enabled: false
+
+Style/PerlBackrefs:
+  Description: 'Avoid Perl-style regex back references.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers'
+  Enabled: false
+
+Style/PredicateName:
+  Description: 'Check the names of predicate methods.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark'
+  Enabled: false
+
+Style/Proc:
+  Description: 'Use proc instead of Proc.new.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#proc'
+  Enabled: false
+
+Style/RaiseArgs:
+  Description: 'Checks the arguments passed to raise/fail.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#exception-class-messages'
+  Enabled: false
+
+Style/RedundantBegin:
+  Description: "Don't use begin blocks when they are not needed."
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#begin-implicit'
+  Enabled: false
+
+Style/RedundantException:
+  Description: "Checks for an obsolete RuntimeException argument in raise/fail."
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-explicit-runtimeerror'
+  Enabled: false
+
+Style/RedundantReturn:
+  Description: "Don't use return where it's not required."
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-explicit-return'
+  Enabled: false
+
+Style/RedundantSelf:
+  Description: "Don't use self where it's not needed."
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-self-unless-required'
+  Enabled: false
+
+Style/RegexpLiteral:
+  Description: 'Use / or %r around regular expressions.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-r'
+  Enabled: false
+
+Style/RescueEnsureAlignment:
+  Description: 'Align rescues and ensures correctly.'
+  Enabled: false
+
+Style/RescueModifier:
+  Description: 'Avoid using rescue in its modifier form.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-rescue-modifiers'
+  Enabled: false
+
+Style/SelfAssignment:
+  Description: >-
+                 Checks for places where self-assignment shorthand should have
+                 been used.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#self-assignment'
+  Enabled: false
+
+Style/Semicolon:
+  Description: "Don't use semicolons to terminate expressions."
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-semicolon'
+  Enabled: false
+
+Style/SignalException:
+  Description: 'Checks for proper usage of fail and raise.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#fail-method'
+  Enabled: false
+
+Style/SingleLineBlockParams:
+  Description: 'Enforces the names of some block params.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#reduce-blocks'
+  Enabled: false
+
+Style/SingleLineMethods:
+  Description: 'Avoid single-line methods.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-single-line-methods'
+  Enabled: false
+
+Style/SpaceBeforeFirstArg:
+  Description: >-
+                 Checks that exactly one space is used between a method name
+                 and the first argument for method calls without parentheses.
+  Enabled: true
+
+Style/SpaceAfterColon:
+  Description: 'Use spaces after colons.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators'
+  Enabled: false
+
+Style/SpaceAfterComma:
+  Description: 'Use spaces after commas.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators'
+  Enabled: false
+
+Style/SpaceAroundKeyword:
+  Description: 'Use spaces around keywords.'
+  Enabled: false
+
+Style/SpaceAfterMethodName:
+  Description: >-
+                 Do not put a space between a method name and the opening
+                 parenthesis in a method definition.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-no-spaces'
+  Enabled: false
+
+Style/SpaceAfterNot:
+  Description: Tracks redundant space after the ! operator.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-space-bang'
+  Enabled: false
+
+Style/SpaceAfterSemicolon:
+  Description: 'Use spaces after semicolons.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators'
+  Enabled: false
+
+Style/SpaceBeforeBlockBraces:
+  Description: >-
+                 Checks that the left block brace has or doesn't have space
+                 before it.
+  Enabled: false
+
+Style/SpaceBeforeComma:
+  Description: 'No spaces before commas.'
+  Enabled: false
+
+Style/SpaceBeforeComment:
+  Description: >-
+                 Checks for missing space between code and a comment on the
+                 same line.
+  Enabled: false
+
+Style/SpaceBeforeSemicolon:
+  Description: 'No spaces before semicolons.'
+  Enabled: false
+
+Style/SpaceInsideBlockBraces:
+  Description: >-
+                 Checks that block braces have or don't have surrounding space.
+                 For blocks taking parameters, checks that the left brace has
+                 or doesn't have trailing space.
+  Enabled: false
+
+Style/SpaceAroundBlockParameters:
+  Description: 'Checks the spacing inside and after block parameters pipes.'
+  Enabled: false
+
+Style/SpaceAroundEqualsInParameterDefault:
+  Description: >-
+                 Checks that the equals signs in parameter default assignments
+                 have or don't have surrounding space depending on
+                 configuration.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-around-equals'
+  Enabled: false
+
+Style/SpaceAroundOperators:
+  Description: 'Use a single space around operators.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators'
+  Enabled: false
+
+Style/SpaceInsideBrackets:
+  Description: 'No spaces after [ or before ].'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces'
+  Enabled: false
+
+Style/SpaceInsideHashLiteralBraces:
+  Description: "Use spaces inside hash literal braces - or don't."
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators'
+  Enabled: false
+
+Style/SpaceInsideParens:
+  Description: 'No spaces after ( or before ).'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces'
+  Enabled: false
+
+Style/SpaceInsideRangeLiteral:
+  Description: 'No spaces inside range literals.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-space-inside-range-literals'
+  Enabled: false
+
+Style/SpaceInsideStringInterpolation:
+  Description: 'Checks for padding/surrounding spaces inside string interpolation.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#string-interpolation'
+  Enabled: false
+
+Style/SpecialGlobalVars:
+  Description: 'Avoid Perl-style global variables.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms'
+  Enabled: false
+
+Style/StringLiterals:
+  Description: 'Checks if uses of quotes match the configured preference.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#consistent-string-literals'
+  Enabled: false
+
+Style/StringLiteralsInInterpolation:
+  Description: >-
+                 Checks if uses of quotes inside expressions in interpolated
+                 strings match the configured preference.
+  Enabled: false
+
+Style/StructInheritance:
+  Description: 'Checks for inheritance from Struct.new.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-extend-struct-new'
+  Enabled: false
+
+Style/SymbolLiteral:
+  Description: 'Use plain symbols instead of string symbols when possible.'
+  Enabled: false
+
+Style/SymbolProc:
+  Description: 'Use symbols as procs instead of blocks when possible.'
+  Enabled: false
+
+Style/Tab:
+  Description: 'No hard tabs.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-indentation'
+  Enabled: false
+
+Style/TrailingBlankLines:
+  Description: 'Checks trailing blank lines and final newline.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#newline-eof'
+  Enabled: false
+
+Style/TrailingCommaInArguments:
+  Description: 'Checks for trailing comma in parameter lists.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-params-comma'
+  Enabled: false
+
+Style/TrailingCommaInLiteral:
+  Description: 'Checks for trailing comma in literals.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas'
+  Enabled: false
+
+Style/TrailingWhitespace:
+  Description: 'Avoid trailing whitespace.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace'
+  Enabled: false
+
+Style/TrivialAccessors:
+  Description: 'Prefer attr_* methods to trivial readers/writers.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr_family'
+  Enabled: false
+
+Style/UnlessElse:
+  Description: >-
+                 Do not use unless with else. Rewrite these with the positive
+                 case first.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-else-with-unless'
+  Enabled: false
+
+Style/UnneededCapitalW:
+  Description: 'Checks for %W when interpolation is not needed.'
+  Enabled: false
+
+Style/UnneededPercentQ:
+  Description: 'Checks for %q/%Q when single quotes or double quotes would do.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q'
+  Enabled: false
+
+Style/TrailingUnderscoreVariable:
+  Description: >-
+                 Checks for the usage of unneeded trailing underscores at the
+                 end of parallel variable assignment.
+  Enabled: false
+
+Style/VariableInterpolation:
+  Description: >-
+                 Don't interpolate global, instance and class variables
+                 directly in strings.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#curlies-interpolate'
+  Enabled: false
+
+Style/VariableName:
+  Description: 'Use the configured style when naming variables.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars'
+  Enabled: false
+
+Style/WhenThen:
+  Description: 'Use when x then ... for one-line cases.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#one-line-cases'
+  Enabled: false
+
+Style/WhileUntilDo:
+  Description: 'Checks for redundant do after while or until.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-multiline-while-do'
+  Enabled: false
+
+Style/WhileUntilModifier:
+  Description: >-
+                 Favor modifier while/until usage when you have a
+                 single-line body.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#while-as-a-modifier'
+  Enabled: false
+
+Style/WordArray:
+  Description: 'Use %w or %W for arrays of words.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-w'
+  Enabled: false
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6a61b9d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,16 @@
+language: ruby
+
+rvm:
+- "ruby-head"
+- "2.4.0"
+- "2.3"
+- "2.2"
+- "2.1"
+- "2.0"
+
+addons:
+  code_climate:
+    repo_token: 8f697ca756250f0c2c54170ae27e8a9c459d18a0236903b11291c88291b3aac9
+
+after_success:
+  - bundle exec codeclimate-test-reporter
diff --git a/Gemfile b/Gemfile
index c5c59f7..fa75df1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,16 +1,3 @@
-source :rubygems
+source 'https://rubygems.org'
 
-
-group :development do
-  gem 'rake'
-  gem 'jeweler'
-end
-
-group :test do
-  gem 'actionpack', '~>2.3.8'
-  gem 'mocha', '>=0.9.8'
-  gem 'typhoeus', '>=0.1.13'
-  gem 'em-http-request', "0.2.11"
-  gem 'curb', ">= 0.6.6.0"
-  gem 'webmock'
-end
+gemspec
diff --git a/Gemfile.lock b/Gemfile.lock
deleted file mode 100644
index dd920ea..0000000
--- a/Gemfile.lock
+++ /dev/null
@@ -1,47 +0,0 @@
-GEM
-  remote: http://rubygems.org/
-  specs:
-    actionpack (2.3.14)
-      activesupport (= 2.3.14)
-      rack (~> 1.1.0)
-    activesupport (2.3.14)
-    addressable (2.2.7)
-    crack (0.3.1)
-    curb (0.8.0)
-    em-http-request (0.2.11)
-      addressable (>= 2.0.0)
-      eventmachine (>= 0.12.9)
-    eventmachine (0.12.10)
-    git (1.2.5)
-    jeweler (1.8.3)
-      bundler (~> 1.0)
-      git (>= 1.2.5)
-      rake
-      rdoc
-    json (1.6.6)
-    metaclass (0.0.1)
-    mime-types (1.18)
-    mocha (0.11.1)
-      metaclass (~> 0.0.1)
-    rack (1.1.3)
-    rake (0.9.2.2)
-    rdoc (3.12)
-      json (~> 1.4)
-    typhoeus (0.3.3)
-      mime-types
-    webmock (1.8.6)
-      addressable (>= 2.2.7)
-      crack (>= 0.1.7)
-
-PLATFORMS
-  ruby
-
-DEPENDENCIES
-  actionpack (~> 2.3.8)
-  curb (>= 0.6.6.0)
-  em-http-request (= 0.2.11)
-  jeweler
-  mocha (>= 0.9.8)
-  rake
-  typhoeus (>= 0.1.13)
-  webmock
diff --git a/HISTORY b/HISTORY
index a48db07..088290b 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,3 +1,76 @@
+=== CURRENT
+
+
+
+=== 0.5.3 2017-05-24
+
+* Removing legacy scripts (James Pinto)
+* Fix #145 - broken CLI required loading active_support (James Pinto)
+
+=== 0.5.2 2017-05-17
+
+* Adding a development dependency that had not been mentioned (James Pinto)
+* Use assert_nil so as to silence a Minitest 6 deprecation warning (James Pinto)
+* Stop bundling tests files in the gem (Michal Papis)
+* Minor cleanup on tests (James Pinto)
+* TravisCI no longer needs libcurl-dev (James Pinto)
+* Nokogiri 1.7 does not accept Ruby 2.0 (James Pinto)
+* Upgrading to CodeClimate 1.0 (James Pinto)
+* Adding support to Ruby 2.4 and head (James Pinto)
+* Locking gemspec to Rails 4 so as to allow our next version for Rails 5 (James Pinto)
+* Fix #113 adding paths when a full URL has been specified   (James Pinto)
+* moving development dependency to gemspec (James Pinto)
+* Silencing 'Net::HTTPResponse#header is obsolete' (James Pinto)
+* Silencing some test warnings (James Pinto)
+* Silencing 'loading in progress, circular require considered harmful' (James Pinto)
+* Silence 'URI.escape obsolete' (James Pinto)
+* Refactored CLI (James Pinto)
+* Bug Fix, webmock 2.0 has introduced a new bug (James Pinto)
+* Moving test files into test/units/ (James Pinto)
+* Adding CodeClimate (James Pinto)
+* Reimplementing #82 - Debug Output Option (James Pinto)
+* Making a test/support dir (James Pinto)
+* Fix #177 - Adjusting to webmock latest recommended implementation for minitest (James Pinto)
+* Adding support to Ruby 2.4 and head (James Pinto)
+* Upgrading to CodeClimate 1.0 (James Pinto)
+* Nokogiri 1.7 does not accept Ruby 2.0 (James Pinto)
+
+=== 0.5.1 2016-02-29
+
+* Proper handling for empty query string in RequestToken#build_authorize_url (midchildan,
+  Harald Sitter)
+* Loosen some development dependencies. Add libcurl-dev to travis
+* Add license info to the gemspec (Robert Reiz)
+* Fixes to travis config. Switch to rubygems for installation and loading
+* Remove obsolete comment (Arthur Nogueira Neves)
+* Remove jeweler from gemspec
+* Replace calls to String#blank? with its implementation (Sergio Gil Pérez de la Manga)
+
+=== 0.5.0 2016-02-20
+
+* Fix ability to pass in an authorize url with a query string (Roger Smith)
+* Add support for HTTP PATCH method (Richard Huang)
+* Allow reading private key from a string (Khaja Minhajuddin)
+* Fix bug in signature verification (r-stu31)
+* Use standard key name (`oauth_token_secret`) in Token#to_query (Craig Walker)
+* Fix error in CLI when using `query` without supplying a method (grafikchaos)
+* Compatibility fix for Typhoeus >= 0.5.0 (Chad Feller)
+* Add rest-client proxy (Khem Veasna)
+* Rails 3+ / ActiveSupport::SafeBuffer patch (Clif Reeder)
+* Handle `nil` token gracefully for RequestToken#authorize_url (Brian John)
+* Replace jeweler with real spec and bundler tasks
+* Extract version to separate file
+* Fix typhoeus compatibility (Vladimir Mikhailov)
+* Use OpenSSL for all digest and hashing. Remove signature methods not defined by OAuth spec.
+  Add byebug. (Kevin Hughes)
+* Fix oauth cli option parser on Ruby 2.2 (Felix Bünemann)
+* Change token requests to exclude `oauth_body_hash`. Update doc links in comments. (John Remmen)
+* Update gemspec for security fixes. Convert to Minitest. Add .travis.yml. (Kevin Hughes)
+* Allow reading certificate file path from environment variable. Add CentOS cert file path
+  (Danil Vlasov)
+* Fix some warnings (amatsuda)
+* Various fixes/updates to README (Evan Arnold, Jonathan Camenisch, Brian John, Ankur Sethi)
+
 === 0.4.7 2012-09-03
 
 * Fix merging paths if the path is not empty
@@ -157,8 +230,8 @@
 
 == 0.2 2008-1-19 All together now release
 
-This is a big release, where we have merged the efforts of various parties into one common library. 
-This means there are definitely some API changes you should be aware of. They should be minimal 
+This is a big release, where we have merged the efforts of various parties into one common library.
+This means there are definitely some API changes you should be aware of. They should be minimal
 but please have a look at the unit tests.
 
 == 0.1.2 2007-12-1
diff --git a/README.rdoc b/README.rdoc
index 5932a24..da7106c 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -1,5 +1,11 @@
 = Ruby OAuth
 
+== Status
+
+{<img src="https://travis-ci.org/oauth-xx/oauth-ruby.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/oauth-xx/oauth-ruby]
+
+
+
 == What
 
 This is a RubyGem for implementing both OAuth clients and servers in Ruby applications.
@@ -10,13 +16,13 @@ See the OAuth specs http://oauth.net/core/1.0/
 
   sudo gem install oauth
 
-The source code is now hosted on the OAuth GitHub Project http://github.com/oauth/oauth-ruby
+The source code is now hosted on the OAuth GitHub Project http://github.com/oauth-xx/oauth-ruby
 
 == The basics
 
 This is a ruby library which is intended to be used in creating Ruby Consumer and Service Provider applications. It is NOT a Rails plugin, but could easily be used for the foundation for such a Rails plugin.
 
-As a matter of fact it has been pulled out from an OAuth Rails Plugin http://code.google.com/p/oauth-plugin/ which now requires this GEM.
+As a matter of fact it has been pulled out from an OAuth Rails GEM (https://rubygems.org/gems/oauth-plugin https://github.com/pelle/oauth-plugin) which now uses this gem as a dependency.
 
 == Demonstration of usage
 
@@ -31,11 +37,15 @@ Create a new consumer instance by passing it a configuration hash:
 Start the process by requesting a token
 
   @request_token = @consumer.get_request_token(:oauth_callback => @callback_url)
-  session[:request_token] = @request_token
+
+  session[:token] = request_token.token
+  session[:token_secret] = request_token.secret
   redirect_to @request_token.authorize_url(:oauth_callback => @callback_url)
 
 When user returns create an access_token
 
+  hash = { oauth_token: session[:token], oauth_token_secret: session[:token_secret]}
+  request_token  = OAuth::RequestToken.from_hash(@consumer, hash)
   @access_token = @request_token.get_access_token
   @photos = @access_token.get('/photos.xml')
 
@@ -44,9 +54,9 @@ Now that you have an access token, you can use Typhoeus to interact with the OAu
   require 'oauth/request_proxy/typhoeus_request'
   oauth_params = {:consumer => oauth_consumer, :token => access_token}
   hydra = Typhoeus::Hydra.new
-  req = Typhoeus::Request.new(uri, options) 
+  req = Typhoeus::Request.new(uri, options) # :method needs to be specified in options
   oauth_helper = OAuth::Client::Helper.new(req, oauth_params.merge(:request_uri => uri))
-  req.headers.merge!({"Authorization" => oauth_helper.header}) # Signs the request
+  req.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
   hydra.queue(req)
   hydra.run
   @response = req.response
@@ -54,22 +64,22 @@ Now that you have an access token, you can use Typhoeus to interact with the OAu
 
 == More Information
 
-* RDoc: http://rdoc.info/projects/oauth/oauth-ruby/
+* RDoc: http://rdoc.info/github/oauth-xx/oauth-ruby/master/frames
 * Mailing List/Google Group: http://groups.google.com/group/oauth-ruby
 
 == How to submit patches
 
-The source code is now hosted on the OAuth GitHub Project http://github.com/oauth/oauth-ruby
+The source code is now hosted on the OAuth GitHub Project http://github.com/oauth-xx/oauth-ruby
 
 To submit a patch, please fork the oauth project and create a patch with tests. Once you're happy with it send a pull request and post a message to the google group.
 
 == License
 
-This code is free to use under the terms of the MIT license. 
+This code is free to use under the terms of the MIT license.
 
 == Contact
 
-OAuth Ruby has been created and maintained by a large number of talented individuals. 
+OAuth Ruby has been created and maintained by a large number of talented individuals.
 The current maintainer is Aaron Quint (quirkey).
 
-Comments are welcome. Send an email to via the OAuth Ruby mailing list http://groups.google.com/group/oauth-ruby
\ No newline at end of file
+Comments are welcome. Send an email to via the OAuth Ruby mailing list http://groups.google.com/group/oauth-ruby
diff --git a/Rakefile b/Rakefile
index 17782d1..eee4d40 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,30 +1,6 @@
-%w[rubygems rake rake/clean rake/testtask fileutils].each { |f| require f }
-$LOAD_PATH << File.dirname(__FILE__) + '/lib'
-require 'oauth'
+%w[rubygems rake rake/clean rake/testtask fileutils bundler].each { |f| require f }
 
-begin
-  require 'jeweler'
-  Jeweler::Tasks.new do |s|
-    s.name = %q{oauth}
-    s.version = OAuth::VERSION
-    s.authors = ["Pelle Braendgaard", "Blaine Cook", "Larry Halff", "Jesse Clark", "Jon Crosby", "Seth Fitzsimmons", "Matt Sanford", "Aaron Quint"]
-    s.email = "oauth-ruby at googlegroups.com"
-    s.description = "OAuth Core Ruby implementation"
-    s.summary = s.description
-    s.rubyforge_project = %q{oauth}
-    s.add_development_dependency(%q<actionpack>, [">=2.3.5"])
-    s.add_development_dependency(%q<rack>, [">= 1.0.0"])
-    s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
-    s.add_development_dependency(%q<typhoeus>, [">= 0.1.13"])
-    s.add_development_dependency(%q<em-http-request>, [">= 0.2.10"])
-    s.add_development_dependency(%q<curb>, [">= 0.6.6.0"])
-    
-    s.files.include '.gemtest'
-  end
-  Jeweler::GemcutterTasks.new
-rescue LoadError
-  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
-end
+Bundler::GemHelper.install_tasks
 
 Rake::TestTask.new do |t|
   t.libs << "test"
diff --git a/bin/oauth b/bin/oauth
index 8a97ac3..0b01c83 100755
--- a/bin/oauth
+++ b/bin/oauth
@@ -1,5 +1,11 @@
 #!/usr/bin/env ruby
 
-require "oauth/cli"
+require_relative "../lib/oauth"
+require 'oauth/cli'
 
-OAuth::CLI.execute(STDOUT, STDIN, STDERR, ARGV)
\ No newline at end of file
+Signal.trap("INT") { puts; exit(1) } # don't dump a backtrace on a ^C
+
+ARGV << 'help' if ARGV.empty?
+command = ARGV.shift
+
+OAuth::CLI.new(STDOUT, STDIN, STDERR, command, ARGV).run
diff --git a/lib/digest/hmac.rb b/lib/digest/hmac.rb
deleted file mode 100644
index 28711db..0000000
--- a/lib/digest/hmac.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# = digest/hmac.rb
-#
-# An implementation of HMAC keyed-hashing algorithm
-#
-# == Overview
-#
-# This library adds a method named hmac() to Digest classes, which
-# creates a Digest class for calculating HMAC digests.
-#
-# == Examples
-#
-#   require 'digest/hmac'
-#
-#   # one-liner example
-#   puts Digest::HMAC.hexdigest("data", "hash key", Digest::SHA1)
-#
-#   # rather longer one
-#   hmac = Digest::HMAC.new("foo", Digest::RMD160)
-#
-#   buf = ""
-#   while stream.read(16384, buf)
-#     hmac.update(buf)
-#   end
-#
-#   puts hmac.bubblebabble
-#
-# == License
-#
-# Copyright (c) 2006 Akinori MUSHA <knu at iDaemons.org>
-#
-# Documentation by Akinori MUSHA
-#
-# All rights reserved.  You can redistribute and/or modify it under
-# the same terms as Ruby.
-#
-#   $Id: hmac.rb 14881 2008-01-04 07:26:14Z akr $
-#
-
-require 'digest'
-
-unless defined?(Digest::HMAC)
-  module Digest
-    class HMAC < Digest::Class
-      def initialize(key, digester)
-        @md = digester.new
-
-        block_len = @md.block_length
-
-        if key.bytesize > block_len
-          key = @md.digest(key)
-        end
-
-        ipad = Array.new(block_len).fill(0x36)
-        opad = Array.new(block_len).fill(0x5c)
-
-        key.bytes.each_with_index { |c, i|
-          ipad[i] ^= c
-          opad[i] ^= c
-        }
-
-        @key = key.freeze
-        @ipad = ipad.inject('') { |s, c| s << c.chr }.freeze
-        @opad = opad.inject('') { |s, c| s << c.chr }.freeze
-        @md.update(@ipad)
-      end
-
-      def initialize_copy(other)
-        @md = other.instance_eval { @md.clone }
-      end
-
-      def update(text)
-        @md.update(text)
-        self
-      end
-      alias << update
-
-      def reset
-        @md.reset
-        @md.update(@ipad)
-        self
-      end
-
-      def finish
-        d = @md.digest!
-        @md.update(@opad)
-        @md.update(d)
-        @md.digest!
-      end
-      private :finish
-
-      def digest_length
-        @md.digest_length
-      end
-
-      def block_length
-        @md.block_length
-      end
-
-      def inspect
-        sprintf('#<%s: key=%s, digest=%s>', self.class.name, @key.inspect, @md.inspect.sub(/^\#<(.*)>$/) { $1 });
-      end
-    end
-  end
-end
diff --git a/lib/oauth.rb b/lib/oauth.rb
index 89231f7..48d8976 100644
--- a/lib/oauth.rb
+++ b/lib/oauth.rb
@@ -1,8 +1,7 @@
-$LOAD_PATH << File.dirname(__FILE__) unless $LOAD_PATH.include?(File.dirname(__FILE__))
+root = File.dirname(__FILE__)
+$LOAD_PATH << root unless $LOAD_PATH.include?(root)
 
-module OAuth
-  VERSION = "0.4.7"
-end
+require 'oauth/version'
 
 require 'oauth/oauth'
 require 'oauth/core_ext'
diff --git a/lib/oauth/cli.rb b/lib/oauth/cli.rb
index c547f72..8c1dece 100644
--- a/lib/oauth/cli.rb
+++ b/lib/oauth/cli.rb
@@ -1,378 +1,56 @@
 require 'optparse'
-require 'oauth'
+require 'oauth/cli/base_command'
+require 'oauth/cli/help_command'
+require 'oauth/cli/query_command'
+require 'oauth/cli/authorize_command'
+require 'oauth/cli/sign_command'
+require 'oauth/cli/version_command'
+require 'active_support/core_ext/string/inflections'
 
 module OAuth
   class CLI
-    SUPPORTED_COMMANDS = {
-      "authorize" => "Obtain an access token and secret for a user",
-      "debug"     => "Verbosely generate an OAuth signature",
-      "query"     => "Query a protected resource",
-      "sign"      => "Generate an OAuth signature",
-      "version"   => "Display the current version of the library"
-    }
-
-    attr_reader :command
-    attr_reader :options
-    attr_reader :stdout, :stdin
-
-    def self.execute(stdout, stdin, stderr, arguments = [])
-      self.new.execute(stdout, stdin, stderr, arguments)
-    end
-
-    def initialize
-      @options = {}
-
-      # don't dump a backtrace on a ^C
-      trap(:INT) {
-        exit
-      }
-    end
-
-    def execute(stdout, stdin, stderr, arguments = [])
-      @stdout = stdout
-      @stdin  = stdin
-      @stderr = stderr
-      extract_command_and_parse_options(arguments)
-
-      if sufficient_options? && valid_command?
-        if command == "debug"
-          @command = "sign"
-          @options[:verbose] = true
-        end
-
-        case command
-        # TODO move command logic elsewhere
-        when "authorize"
-          begin
-            consumer = OAuth::Consumer.new \
-              options[:oauth_consumer_key],
-              options[:oauth_consumer_secret],
-              :access_token_url  => options[:access_token_url],
-              :authorize_url     => options[:authorize_url],
-              :request_token_url => options[:request_token_url],
-              :scheme            => options[:scheme],
-              :http_method       => options[:method].to_s.downcase.to_sym
-
-            # parameters for OAuth 1.0a
-            oauth_verifier = nil
-
-            # get a request token
-            request_token = consumer.get_request_token({ :oauth_callback => options[:oauth_callback] }, { "scope" => options[:scope] })
-
-            if request_token.callback_confirmed?
-              stdout.puts "Server appears to support OAuth 1.0a; enabling support."
-              options[:version] = "1.0a"
-            end
-
-            stdout.puts "Please visit this url to authorize:"
-            stdout.puts request_token.authorize_url
-
-            if options[:version] == "1.0a"
-              stdout.puts "Please enter the verification code provided by the SP (oauth_verifier):"
-              oauth_verifier = stdin.gets.chomp
-            else
-              stdout.puts "Press return to continue..."
-              stdin.gets
-            end
-
-            begin
-              # get an access token
-              access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
-
-              stdout.puts "Response:"
-              access_token.params.each do |k,v|
-                stdout.puts "  #{k}: #{v}" unless k.is_a?(Symbol)
-              end
-            rescue OAuth::Unauthorized => e
-              stderr.puts "A problem occurred while attempting to obtain an access token:"
-              stderr.puts e
-              stderr.puts e.request.body
-            end
-          rescue OAuth::Unauthorized => e
-            stderr.puts "A problem occurred while attempting to authorize:"
-            stderr.puts e
-            stderr.puts e.request.body
-          end
-        when "query"
-          consumer = OAuth::Consumer.new \
-            options[:oauth_consumer_key],
-            options[:oauth_consumer_secret],
-            :scheme => options[:scheme]
-
-          access_token = OAuth::AccessToken.new(consumer, options[:oauth_token], options[:oauth_token_secret])
-
-          # append params to the URL
-          uri = URI.parse(options[:uri])
-          params = prepare_parameters.map { |k,v| v.map { |v2| "#{URI.encode(k)}=#{URI.encode(v2)}" } * "&" }
-          uri.query = [uri.query, *params].reject { |x| x.nil? } * "&"
-          p uri.to_s
-
-          response = access_token.request(options[:method].downcase.to_sym, uri.to_s)
-          puts "#{response.code} #{response.message}"
-          puts response.body
-        when "sign"
-          parameters = prepare_parameters
-
-          request = OAuth::RequestProxy.proxy \
-             "method"     => options[:method],
-             "uri"        => options[:uri],
-             "parameters" => parameters
-
-          if verbose?
-            stdout.puts "OAuth parameters:"
-            request.oauth_parameters.each do |k,v|
-              stdout.puts "  " + [k, v] * ": "
-            end
-            stdout.puts
-
-            if request.non_oauth_parameters.any?
-              stdout.puts "Parameters:"
-              request.non_oauth_parameters.each do |k,v|
-                stdout.puts "  " + [k, v] * ": "
-              end
-              stdout.puts
-            end
-          end
-
-          request.sign! \
-            :consumer_secret => options[:oauth_consumer_secret],
-            :token_secret    => options[:oauth_token_secret]
-
-          if verbose?
-            stdout.puts "Method: #{request.method}"
-            stdout.puts "URI: #{request.uri}"
-            stdout.puts "Normalized params: #{request.normalized_parameters}" unless options[:xmpp]
-            stdout.puts "Signature base string: #{request.signature_base_string}"
-
-            if options[:xmpp]
-              stdout.puts
-              stdout.puts "XMPP Stanza:"
-              stdout.puts <<-EOS
-  <oauth xmlns='urn:xmpp:oauth:0'>
-    <oauth_consumer_key>#{request.oauth_consumer_key}</oauth_consumer_key>
-    <oauth_token>#{request.oauth_token}</oauth_token>
-    <oauth_signature_method>#{request.oauth_signature_method}</oauth_signature_method>
-    <oauth_signature>#{request.oauth_signature}</oauth_signature>
-    <oauth_timestamp>#{request.oauth_timestamp}</oauth_timestamp>
-    <oauth_nonce>#{request.oauth_nonce}</oauth_nonce>
-    <oauth_version>#{request.oauth_version}</oauth_version>
-  </oauth>
-              EOS
-              stdout.puts
-              stdout.puts "Note: You may want to use bare JIDs in your URI."
-              stdout.puts
-            else
-              stdout.puts "OAuth Request URI: #{request.signed_uri}"
-              stdout.puts "Request URI: #{request.signed_uri(false)}"
-              stdout.puts "Authorization header: #{request.oauth_header(:realm => options[:realm])}"
-            end
-            stdout.puts "Signature:         #{request.oauth_signature}"
-            stdout.puts "Escaped signature: #{OAuth::Helper.escape(request.oauth_signature)}"
-          else
-            stdout.puts request.oauth_signature
-          end
-        when "version"
-          puts "OAuth for Ruby #{OAuth::VERSION}"
-        end
-      else
-        usage
-      end
+    def self.puts_red(string)
+      puts "\033[0;91m#{string}\033[0m"
     end
 
-  protected
-
-    def extract_command_and_parse_options(arguments)
-      @command = arguments[-1]
-      parse_options(arguments[0..-1])
-    end
-
-    def option_parser(arguments = "")
-      # TODO add realm parameter
-      # TODO add user-agent parameter
-      option_parser = OptionParser.new do |opts|
-        opts.banner = "Usage: #{$0} [options] <command>"
-
-        # defaults
-        options[:oauth_nonce] = OAuth::Helper.generate_key
-        options[:oauth_signature_method] = "HMAC-SHA1"
-        options[:oauth_timestamp] = OAuth::Helper.generate_timestamp
-        options[:oauth_version] = "1.0"
-        options[:method] = :post
-        options[:params] = []
-        options[:scheme] = :header
-        options[:version] = "1.0"
-
-        ## Common Options
-
-        opts.on("-B", "--body", "Use the request body for OAuth parameters.") do
-          options[:scheme] = :body
-        end
-
-        opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
-          options[:oauth_consumer_key] = v
-        end
-
-        opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
-          options[:oauth_consumer_secret] = v
-        end
-
-        opts.on("-H", "--header", "Use the 'Authorization' header for OAuth parameters (default).") do
-          options[:scheme] = :header
-        end
-
-        opts.on("-Q", "--query-string", "Use the query string for OAuth parameters.") do
-          options[:scheme] = :query_string
-        end
-
-        opts.on("-O", "--options FILE", "Read options from a file") do |v|
-          arguments.unshift(*open(v).readlines.map { |l| l.chomp.split(" ") }.flatten)
-        end
-
-        ## Options for signing and making requests
-
-        opts.separator("\n  options for signing and querying")
-
-        opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
-          options[:method] = v
-        end
-
-        opts.on("--nonce NONCE", "Specifies the none to use.") do |v|
-          options[:oauth_nonce] = v
-        end
-
-        opts.on("--parameters PARAMS", "Specifies the parameters to use when signing.") do |v|
-          options[:params] << v
-        end
-
-        opts.on("--signature-method METHOD", "Specifies the signature method to use; defaults to HMAC-SHA1.") do |v|
-          options[:oauth_signature_method] = v
-        end
-
-        opts.on("--secret SECRET", "Specifies the token secret to use.") do |v|
-          options[:oauth_token_secret] = v
-        end
-
-        opts.on("--timestamp TIMESTAMP", "Specifies the timestamp to use.") do |v|
-          options[:oauth_timestamp] = v
-        end
-
-        opts.on("--token TOKEN", "Specifies the token to use.") do |v|
-          options[:oauth_token] = v
-        end
-
-        opts.on("--realm REALM", "Specifies the realm to use.") do |v|
-          options[:realm] = v
-        end
-
-        opts.on("--uri URI", "Specifies the URI to use when signing.") do |v|
-          options[:uri] = v
-        end
-
-        opts.on(:OPTIONAL, "--version VERSION", "Specifies the OAuth version to use.") do |v|
-          if v
-            options[:oauth_version] = v
-          else
-            @command = "version"
-          end
-        end
-
-        opts.on("--no-version", "Omit oauth_version.") do
-          options[:oauth_version] = nil
-        end
-
-        opts.on("--xmpp", "Generate XMPP stanzas.") do
-          options[:xmpp] = true
-          options[:method] ||= "iq"
-        end
-
-        opts.on("-v", "--verbose", "Be verbose.") do
-          options[:verbose] = true
-        end
-
-        ## Options for authorization
-
-        opts.separator("\n  options for authorization")
-
-        opts.on("--access-token-url URL", "Specifies the access token URL.") do |v|
-          options[:access_token_url] = v
-        end
-
-        opts.on("--authorize-url URL", "Specifies the authorization URL.") do |v|
-          options[:authorize_url] = v
-        end
-
-        opts.on("--callback-url URL", "Specifies a callback URL.") do |v|
-          options[:oauth_callback] = v
-        end
-
-        opts.on("--request-token-url URL", "Specifies the request token URL.") do |v|
-          options[:request_token_url] = v
-        end
+    ALIASES = {
+      'h' => 'help',
+      'v' => 'version',
+      'q' => 'query',
+      'a' => 'authorize',
+      's' => 'sign',
+    }
 
-        opts.on("--scope SCOPE", "Specifies the scope (Google-specific).") do |v|
-          options[:scope] = v
-        end
-      end
+    def initialize(stdout, stdin, stderr, command, arguments)
+      klass = get_command_class(parse_command(command))
+      @command = klass.new(stdout, stdin, stderr, arguments)
+      @help_command = HelpCommand.new(stdout, stdin, stderr, [])
     end
 
-    def parse_options(arguments)
-      option_parser(arguments).parse!(arguments)
+    def run
+      @command.run
     end
 
-    def prepare_parameters
-      escaped_pairs = options[:params].collect do |pair|
-        if pair =~ /:/
-          Hash[*pair.split(":", 2)].collect do |k,v|
-            [CGI.escape(k.strip), CGI.escape(v.strip)] * "="
-          end
-        else
-          pair
-        end
-      end
+    private
 
-      querystring = escaped_pairs * "&"
-      cli_params = CGI.parse(querystring)
-
-      {
-        "oauth_consumer_key"     => options[:oauth_consumer_key],
-        "oauth_nonce"            => options[:oauth_nonce],
-        "oauth_timestamp"        => options[:oauth_timestamp],
-        "oauth_token"            => options[:oauth_token],
-        "oauth_signature_method" => options[:oauth_signature_method],
-        "oauth_version"          => options[:oauth_version]
-      }.reject { |k,v| v.nil? || v == "" }.merge(cli_params)
+    def get_command_class(command)
+      Object.const_get("OAuth::CLI::#{command.camelize}Command")
     end
 
-    def sufficient_options?
-      case command
-      # TODO move command logic elsewhere
-      when "authorize"
-        options[:oauth_consumer_key] && options[:oauth_consumer_secret] &&
-          options[:access_token_url] && options[:authorize_url] &&
-          options[:request_token_url]
-      when "version"
-        true
+    def parse_command(command)
+      case command = command.to_s.downcase
+      when '--version', '-v'
+        'version'
+      when '--help', '-h', nil, ''
+        'help'
+      when *ALIASES.keys
+        ALIASES[command]
+      when *ALIASES.values
+        command
       else
-        options[:oauth_consumer_key] && options[:oauth_consumer_secret] &&
-          options[:method] && options[:uri]
-      end
-    end
-
-    def usage
-      stdout.puts option_parser.help
-      stdout.puts
-      stdout.puts "Available commands:"
-      SUPPORTED_COMMANDS.each do |command, desc|
-        puts "   #{command.ljust(15)}#{desc}"
+        OAuth::CLI.puts_red "Command '#{command}' not found"
+        'help'
       end
     end
-
-    def valid_command?
-      SUPPORTED_COMMANDS.keys.include?(command)
-    end
-
-    def verbose?
-      options[:verbose]
-    end
   end
 end
diff --git a/lib/oauth/cli/authorize_command.rb b/lib/oauth/cli/authorize_command.rb
new file mode 100644
index 0000000..e43ebb5
--- /dev/null
+++ b/lib/oauth/cli/authorize_command.rb
@@ -0,0 +1,71 @@
+class OAuth::CLI
+  class AuthorizeCommand < BaseCommand
+
+    def required_options
+      [:uri]
+    end
+
+    def _run
+      request_token = get_request_token
+
+      if request_token.callback_confirmed?
+        puts "Server appears to support OAuth 1.0a; enabling support."
+        options[:version] = "1.0a"
+      end
+
+      puts "Please visit this url to authorize:"
+      puts request_token.authorize_url
+
+      # parameters for OAuth 1.0a
+      oauth_verifier = ask_user_for_verifier
+
+      verbosely_get_access_token(request_token, oauth_verifier)
+    end
+
+    def get_request_token
+      consumer = get_consumer
+      scope_options = options[:scope] ? { "scope" => options[:scope] } : {}
+      consumer.get_request_token({ :oauth_callback => options[:oauth_callback] }, scope_options)
+    rescue OAuth::Unauthorized => e
+      alert "A problem occurred while attempting to authorize:"
+      alert e
+      alert e.request.body
+    end
+
+    def get_consumer
+      OAuth::Consumer.new \
+        options[:oauth_consumer_key],
+        options[:oauth_consumer_secret],
+        :access_token_url  => options[:access_token_url],
+        :authorize_url     => options[:authorize_url],
+        :request_token_url => options[:request_token_url],
+        :scheme            => options[:scheme],
+        :http_method       => options[:method].to_s.downcase.to_sym
+    end
+
+
+    def ask_user_for_verifier
+      if options[:version] == "1.0a"
+        puts "Please enter the verification code provided by the SP (oauth_verifier):"
+        @stdin.gets.chomp
+      else
+        puts "Press return to continue..."
+        @stdin.gets
+        nil
+      end
+    end
+
+    def verbosely_get_access_token(request_token, oauth_verifier)
+      access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
+
+      puts "Response:"
+      access_token.params.each do |k,v|
+        puts "  #{k}: #{v}" unless k.is_a?(Symbol)
+      end
+    rescue OAuth::Unauthorized => e
+      alert "A problem occurred while attempting to obtain an access token:"
+      alert e
+      alert e.request.body
+    end
+  end
+end
diff --git a/lib/oauth/cli/base_command.rb b/lib/oauth/cli/base_command.rb
new file mode 100644
index 0000000..3f65112
--- /dev/null
+++ b/lib/oauth/cli/base_command.rb
@@ -0,0 +1,208 @@
+class OAuth::CLI
+  class BaseCommand
+    def initialize(stdout, stdin, stderr, arguments)
+      @stdout, @stdin, @stderr = stdout, stdin, stderr
+
+      @options = {}
+      option_parser.parse!(arguments)
+    end
+
+    def run
+      missing = required_options - options.keys
+      if missing.empty?
+        _run
+      else
+        show_missing(missing)
+        puts option_parser.help
+      end
+    end
+
+    def required_options
+      []
+    end
+
+    protected
+
+    attr_reader :options
+
+    def show_missing(array)
+      array = array.map { |s| "--#{s}" }.join(' ')
+      OAuth::CLI.puts_red "Options missing to OAuth CLI: #{array}"
+    end
+
+    def xmpp?
+      options[:xmpp]
+    end
+
+    def verbose?
+      options[:verbose]
+    end
+
+    def puts(string=nil)
+      @stdout.puts(string)
+    end
+
+    def alert(string=nil)
+      @stderr.puts(string)
+    end
+
+    def parameters
+      @parameters ||= begin
+        escaped_pairs = options[:params].collect do |pair|
+          if pair =~ /:/
+            Hash[*pair.split(":", 2)].collect do |k,v|
+              [CGI.escape(k.strip), CGI.escape(v.strip)] * "="
+            end
+          else
+            pair
+          end
+        end
+
+        querystring = escaped_pairs * "&"
+        cli_params = CGI.parse(querystring)
+
+        {
+          "oauth_consumer_key"     => options[:oauth_consumer_key],
+          "oauth_nonce"            => options[:oauth_nonce],
+          "oauth_timestamp"        => options[:oauth_timestamp],
+          "oauth_token"            => options[:oauth_token],
+          "oauth_signature_method" => options[:oauth_signature_method],
+          "oauth_version"          => options[:oauth_version]
+        }.reject { |_k,v| v.nil? || v == "" }.merge(cli_params)
+      end
+    end
+
+    def option_parser
+      @option_parser ||= OptionParser.new do |opts|
+        opts.banner = "Usage: oauth <command> [ARGS]"
+
+        _option_parser_defaults
+        _option_parser_common(opts)
+        _option_parser_sign_and_query(opts)
+        _option_parser_authorization(opts)
+      end
+    end
+
+    def _option_parser_defaults
+      options[:oauth_nonce] = OAuth::Helper.generate_key
+      options[:oauth_signature_method] = "HMAC-SHA1"
+      options[:oauth_timestamp] = OAuth::Helper.generate_timestamp
+      options[:oauth_version] = "1.0"
+      options[:method] = :post
+      options[:params] = []
+      options[:scheme] = :header
+      options[:version] = "1.0"
+    end
+
+    def _option_parser_common(opts)
+      ## Common Options
+
+      opts.on("-B", "--body", "Use the request body for OAuth parameters.") do
+        options[:scheme] = :body
+      end
+
+      opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
+        options[:oauth_consumer_key] = v
+      end
+
+      opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
+        options[:oauth_consumer_secret] = v
+      end
+
+      opts.on("-H", "--header", "Use the 'Authorization' header for OAuth parameters (default).") do
+        options[:scheme] = :header
+      end
+
+      opts.on("-Q", "--query-string", "Use the query string for OAuth parameters.") do
+        options[:scheme] = :query_string
+      end
+
+      opts.on("-O", "--options FILE", "Read options from a file") do |v|
+        arguments = open(v).readlines.map { |l| l.chomp.split(" ") }.flatten
+        options2 = parse_options(arguments)
+        options.merge!(options2)
+      end
+    end
+
+    def _option_parser_sign_and_query(opts)
+      opts.separator("\n  options for signing and querying")
+
+      opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
+        options[:method] = v
+      end
+
+      opts.on("--nonce NONCE", "Specifies the none to use.") do |v|
+        options[:oauth_nonce] = v
+      end
+
+      opts.on("--parameters PARAMS", "Specifies the parameters to use when signing.") do |v|
+        options[:params] << v
+      end
+
+      opts.on("--signature-method METHOD", "Specifies the signature method to use; defaults to HMAC-SHA1.") do |v|
+        options[:oauth_signature_method] = v
+      end
+
+      opts.on("--token TOKEN", "Specifies the token to use.") do |v|
+        options[:oauth_token] = v
+      end
+
+      opts.on("--secret SECRET", "Specifies the token secret to use.") do |v|
+        options[:oauth_token_secret] = v
+      end
+
+      opts.on("--timestamp TIMESTAMP", "Specifies the timestamp to use.") do |v|
+        options[:oauth_timestamp] = v
+      end
+
+      opts.on("--realm REALM", "Specifies the realm to use.") do |v|
+        options[:realm] = v
+      end
+
+      opts.on("--uri URI", "Specifies the URI to use when signing.") do |v|
+        options[:uri] = v
+      end
+
+      opts.on("--version [VERSION]", "Specifies the OAuth version to use.") do |v|
+        options[:oauth_version] = v
+      end
+
+      opts.on("--no-version", "Omit oauth_version.") do
+        options[:oauth_version] = nil
+      end
+
+      opts.on("--xmpp", "Generate XMPP stanzas.") do
+        options[:xmpp] = true
+        options[:method] ||= "iq"
+      end
+
+      opts.on("-v", "--verbose", "Be verbose.") do
+        options[:verbose] = true
+      end
+    end
+
+    def _option_parser_authorization(opts)
+      opts.separator("\n  options for authorization")
+
+      opts.on("--access-token-url URL", "Specifies the access token URL.") do |v|
+        options[:access_token_url] = v
+      end
+
+      opts.on("--authorize-url URL", "Specifies the authorization URL.") do |v|
+        options[:authorize_url] = v
+      end
+
+      opts.on("--callback-url URL", "Specifies a callback URL.") do |v|
+        options[:oauth_callback] = v
+      end
+
+      opts.on("--request-token-url URL", "Specifies the request token URL.") do |v|
+        options[:request_token_url] = v
+      end
+
+      opts.on("--scope SCOPE", "Specifies the scope (Google-specific).") do |v|
+        options[:scope] = v
+      end
+    end
+  end
+end
diff --git a/lib/oauth/cli/help_command.rb b/lib/oauth/cli/help_command.rb
new file mode 100644
index 0000000..15ba414
--- /dev/null
+++ b/lib/oauth/cli/help_command.rb
@@ -0,0 +1,22 @@
+class OAuth::CLI
+  class HelpCommand < BaseCommand
+    def run
+      puts <<-EOT
+  Usage: oauth COMMAND [ARGS]
+
+  Available oauth commands are:
+    a, authorize  Obtain an access token and secret for a user
+    q, query      Query a protected resource
+    s, sign       Generate an OAuth signature
+
+  In addition to those, there are:
+    v, version    Displays the current version of the library (or --version, -v)
+    h, help       Displays this help (or --help, -h)
+
+  Tip: All commands can be run without args for specific help.
+
+
+      EOT
+    end
+  end
+end
diff --git a/lib/oauth/cli/query_command.rb b/lib/oauth/cli/query_command.rb
new file mode 100644
index 0000000..cb0fb64
--- /dev/null
+++ b/lib/oauth/cli/query_command.rb
@@ -0,0 +1,25 @@
+class OAuth::CLI
+  class QueryCommand < BaseCommand
+    extend OAuth::Helper
+
+    def required_options
+      [:oauth_consumer_key, :oauth_consumer_secret, :oauth_token, :oauth_token_secret]
+    end
+
+    def _run
+      consumer = OAuth::Consumer.new(options[:oauth_consumer_key], options[:oauth_consumer_secret], scheme: options[:scheme])
+
+      access_token = OAuth::AccessToken.new(consumer, options[:oauth_token], options[:oauth_token_secret])
+
+      # append params to the URL
+      uri = URI.parse(options[:uri])
+      params = parameters.map { |k,v| Array(v).map { |v2| "#{OAuth::Helper.escape(k)}=#{OAuth::Helper.escape(v2)}" } * "&" }
+      uri.query = [uri.query, *params].reject { |x| x.nil? } * "&"
+      puts uri.to_s
+
+      response = access_token.request(options[:method].to_s.downcase.to_sym, uri.to_s)
+      puts "#{response.code} #{response.message}"
+      puts response.body
+    end
+  end
+end
diff --git a/lib/oauth/cli/sign_command.rb b/lib/oauth/cli/sign_command.rb
new file mode 100644
index 0000000..67399d0
--- /dev/null
+++ b/lib/oauth/cli/sign_command.rb
@@ -0,0 +1,81 @@
+class OAuth::CLI
+  class SignCommand < BaseCommand
+
+    def required_options
+      [:oauth_consumer_key, :oauth_consumer_secret, :oauth_token, :oauth_token_secret]
+    end
+
+    def _run
+      request = OAuth::RequestProxy.proxy \
+         "method"     => options[:method],
+         "uri"        => options[:uri],
+         "parameters" => parameters
+
+      if verbose?
+        puts_verbose_parameters(request)
+      end
+
+      request.sign! \
+        :consumer_secret => options[:oauth_consumer_secret],
+        :token_secret    => options[:oauth_token_secret]
+
+      if verbose?
+        puts_verbose_request(request)
+      else
+        puts request.oauth_signature
+      end
+    end
+
+    def puts_verbose_parameters(request)
+      puts "OAuth parameters:"
+      request.oauth_parameters.each do |k,v|
+        puts "  " + [k, v] * ": "
+      end
+      puts
+
+      if request.non_oauth_parameters.any?
+        puts "Parameters:"
+        request.non_oauth_parameters.each do |k,v|
+          puts "  " + [k, v] * ": "
+        end
+        puts
+      end
+    end
+
+    def puts_verbose_request(request)
+      puts "Method: #{request.method}"
+      puts "URI: #{request.uri}"
+      puts "Normalized params: #{request.normalized_parameters}" unless options[:xmpp]
+      puts "Signature base string: #{request.signature_base_string}"
+
+      if xmpp?
+        puts
+        puts "XMPP Stanza:"
+        puts xmpp_output(request)
+        puts
+        puts "Note: You may want to use bare JIDs in your URI."
+        puts
+      else
+        puts "OAuth Request URI: #{request.signed_uri}"
+        puts "Request URI: #{request.signed_uri(false)}"
+        puts "Authorization header: #{request.oauth_header(:realm => options[:realm])}"
+      end
+      puts "Signature:         #{request.oauth_signature}"
+      puts "Escaped signature: #{OAuth::Helper.escape(request.oauth_signature)}"
+    end
+
+    def xmpp_output(request)
+      <<-EOS
+  <oauth xmlns='urn:xmpp:oauth:0'>
+    <oauth_consumer_key>#{request.oauth_consumer_key}</oauth_consumer_key>
+    <oauth_token>#{request.oauth_token}</oauth_token>
+    <oauth_signature_method>#{request.oauth_signature_method}</oauth_signature_method>
+    <oauth_signature>#{request.oauth_signature}</oauth_signature>
+    <oauth_timestamp>#{request.oauth_timestamp}</oauth_timestamp>
+    <oauth_nonce>#{request.oauth_nonce}</oauth_nonce>
+    <oauth_version>#{request.oauth_version}</oauth_version>
+  </oauth>
+      EOS
+    end
+  end
+end
diff --git a/lib/oauth/cli/version_command.rb b/lib/oauth/cli/version_command.rb
new file mode 100644
index 0000000..d2b876f
--- /dev/null
+++ b/lib/oauth/cli/version_command.rb
@@ -0,0 +1,7 @@
+class OAuth::CLI
+  class VersionCommand < BaseCommand
+    def run
+      puts "OAuth Gem #{OAuth::VERSION}"
+    end
+  end
+end
diff --git a/lib/oauth/client/action_controller_request.rb b/lib/oauth/client/action_controller_request.rb
index f4b6a77..a6a43a0 100644
--- a/lib/oauth/client/action_controller_request.rb
+++ b/lib/oauth/client/action_controller_request.rb
@@ -1,4 +1,3 @@
-require 'oauth/client/helper'
 if defined? ActionDispatch
   require 'oauth/request_proxy/rack_request'
   require 'action_dispatch/testing/test_process'
diff --git a/lib/oauth/client/em_http.rb b/lib/oauth/client/em_http.rb
index c59e550..f10c19e 100644
--- a/lib/oauth/client/em_http.rb
+++ b/lib/oauth/client/em_http.rb
@@ -1,6 +1,5 @@
 require 'em-http'
 require 'oauth/helper'
-require 'oauth/client/helper'
 require 'oauth/request_proxy/em_http_request'
 
 # Extensions for em-http so that we can use consumer.sign! with an EventMachine::HttpClient
diff --git a/lib/oauth/client/helper.rb b/lib/oauth/client/helper.rb
index 97241d3..6c8b19b 100644
--- a/lib/oauth/client/helper.rb
+++ b/lib/oauth/client/helper.rb
@@ -56,6 +56,10 @@ module OAuth::Client
                                                          :parameters => oauth_parameters}.merge(extra_options) )
     end
 
+    def token_request?
+      @options[:token_request].eql?(true)
+    end
+
     def hash_body
       @options[:body_hash] = OAuth::Signature.body_hash(@request, :parameters => oauth_parameters)
     end
diff --git a/lib/oauth/client/net_http.rb b/lib/oauth/client/net_http.rb
index 998320e..0e752de 100644
--- a/lib/oauth/client/net_http.rb
+++ b/lib/oauth/client/net_http.rb
@@ -1,5 +1,4 @@
 require 'oauth/helper'
-require 'oauth/client/helper'
 require 'oauth/request_proxy/net_http'
 
 class Net::HTTPGenericRequest
@@ -21,7 +20,8 @@ class Net::HTTPGenericRequest
   # This method also modifies the <tt>User-Agent</tt> header to add the OAuth gem version.
   #
   # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1],
-  #           {OAuth Request Body Hash 1.0 Draft 4}[http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html]
+  #           {OAuth Request Body Hash 1.0 Draft 4}[http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html,
+  #                                                 http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html#when_to_include]
   def oauth!(http, consumer = nil, token = nil, options = {})
     helper_options = oauth_helper_options(http, consumer, token, options)
     @oauth_helper = OAuth::Client::Helper.new(self, helper_options)
@@ -42,13 +42,14 @@ class Net::HTTPGenericRequest
   # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
   #   +signature_method+, +nonce+, +timestamp+)
   #
-  # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1],
-  #           {OAuth Request Body Hash 1.0 Draft 4}[http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html]
+  # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1],
+  #           {OAuth Request Body Hash 1.0 Draft 4}[http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html,
+  #                                                 http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html#when_to_include]
   def signature_base_string(http, consumer = nil, token = nil, options = {})
     helper_options = oauth_helper_options(http, consumer, token, options)
-    oauth_helper = OAuth::Client::Helper.new(self, helper_options)
-    oauth_helper.hash_body if oauth_body_hash_required?
-    oauth_helper.signature_base_string
+    @oauth_helper = OAuth::Client::Helper.new(self, helper_options)
+    @oauth_helper.hash_body if oauth_body_hash_required?
+    @oauth_helper.signature_base_string
   end
 
 private
@@ -84,7 +85,7 @@ private
   end
 
   def oauth_body_hash_required?
-    request_body_permitted? && !content_type.to_s.downcase.start_with?("application/x-www-form-urlencoded")
+    !@oauth_helper.token_request? && request_body_permitted? && !content_type.to_s.downcase.start_with?("application/x-www-form-urlencoded")
   end
 
   def set_oauth_header
diff --git a/lib/oauth/consumer.rb b/lib/oauth/consumer.rb
index d4dd012..09eedd3 100644
--- a/lib/oauth/consumer.rb
+++ b/lib/oauth/consumer.rb
@@ -8,9 +8,9 @@ require 'cgi'
 module OAuth
   class Consumer
     # determine the certificate authority path to verify SSL certs
-    CA_FILES = %w(/etc/ssl/certs/ca-certificates.crt /usr/share/curl/curl-ca-bundle.crt)
+    CA_FILES = %W(#{ENV['SSL_CERT_FILE']} /etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt /usr/share/curl/curl-ca-bundle.crt)
     CA_FILES.each do |ca_file|
-      if File.exists?(ca_file)
+      if File.exist?(ca_file)
         CA_FILE = ca_file
         break
       end
@@ -43,6 +43,13 @@ module OAuth
       # Add a custom ca_file for consumer
       # :ca_file       => '/etc/certs.pem'
 
+      # Possible values:
+      #
+      # nil, false - no debug output
+      # true - uses $stdout
+      # some_value - uses some_value
+      :debug_output => nil,
+
       :oauth_version => "1.0"
     }
 
@@ -87,6 +94,18 @@ module OAuth
       @http_method ||= @options[:http_method] || :post
     end
 
+    def debug_output
+      @debug_output ||= begin
+        case @options[:debug_output]
+        when nil, false
+        when true
+          $stdout
+        else
+          @options[:debug_output]
+        end
+      end
+    end
+
     # The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new
     def http
       @http ||= create_http
@@ -191,6 +210,7 @@ module OAuth
 
     # Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.
     def token_request(http_method, path, token = nil, request_options = {}, *arguments)
+      request_options[:token_request] ||= true
       response = request(http_method, path, token, request_options, *arguments)
       case response.code.to_i
 
@@ -209,7 +229,7 @@ module OAuth
         end
       when (300..399)
         # this is a redirect
-        uri = URI.parse(response.header['location'])
+        uri = URI.parse(response['location'])
         response.error! if uri.path == path # careful of those infinite redirects
         self.token_request(http_method, uri.path, token, request_options, arguments)
       when (400..499)
@@ -234,8 +254,8 @@ module OAuth
     end
 
     def request_endpoint
-  return nil if @options[:request_endpoint].nil?
-  @options[:request_endpoint].to_s
+      return nil if @options[:request_endpoint].nil?
+      @options[:request_endpoint].to_s
     end
 
     def scheme
@@ -320,6 +340,8 @@ module OAuth
 
       http_object.read_timeout = http_object.open_timeout = @options[:timeout] || 30
       http_object.open_timeout = @options[:open_timeout] if @options[:open_timeout]
+      http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
+      http_object.set_debug_output(debug_output) if debug_output
 
       http_object
     end
@@ -328,13 +350,15 @@ module OAuth
     def create_http_request(http_method, path, *arguments)
       http_method = http_method.to_sym
 
-      if [:post, :put].include?(http_method)
+      if [:post, :put, :patch].include?(http_method)
         data = arguments.shift
       end
 
       # if the base site contains a path, add it now
-      uri = URI.parse(site)
-      path = uri.path + path if uri.path && uri.path != '/'
+      # only add if the site host matches the current http object's host
+      # (in case we've specified a full url for token requests)
+      uri  = URI.parse(site)
+      path = uri.path + path if uri.path && uri.path != '/' && uri.host == http.address
 
       headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
 
@@ -345,6 +369,9 @@ module OAuth
       when :put
         request = Net::HTTP::Put.new(path,headers)
         request["Content-Length"] = '0' # Default to 0
+      when :patch
+        request = Net::HTTP::Patch.new(path,headers)
+        request["Content-Length"] = '0' # Default to 0
       when :get
         request = Net::HTTP::Get.new(path,headers)
       when :delete
diff --git a/lib/oauth/core_ext.rb b/lib/oauth/core_ext.rb
index 64bc80a..d0bc436 100644
--- a/lib/oauth/core_ext.rb
+++ b/lib/oauth/core_ext.rb
@@ -13,8 +13,6 @@ end
 
 class String
 
-
-
   unless method_defined?(:bytesize)
     def bytesize
       self.size
@@ -29,3 +27,27 @@ class String
   end
 
 end
+
+# TODO: Work around URI.escape obsolete method
+#
+# 21/May/2016 - We are silencing a warning introduced in 2009
+# https://github.com/ruby/ruby/commit/238b979f1789f95262a267d8df6239806f2859cc
+#
+# The only clear alternative to this problem is to invoke CGI.escape instead
+# but that one does not take a secondary argument so we can pass OAuth::RESERVED_CHARACTERS
+# As of today, ignoring this secondary argument would introduce 44 errors on our tests
+# 181 runs, 511 assertions, 44 failures, 0 errors, 0 skips
+#
+# If you have a proper way to work around this so we don't need to override ruby core code
+# Please send us a Pull Request
+module URI
+  module Escape
+    def escape(*arg)
+      DEFAULT_PARSER.escape(*arg)
+    end
+
+    def unescape(*arg)
+      DEFAULT_PARSER.unescape(*arg)
+    end
+  end
+end
diff --git a/lib/oauth/helper.rb b/lib/oauth/helper.rb
index 2abec6a..40be4e1 100644
--- a/lib/oauth/helper.rb
+++ b/lib/oauth/helper.rb
@@ -9,9 +9,17 @@ module OAuth
     #
     # See Also: {OAuth core spec version 1.0, section 5.1}[http://oauth.net/core/1.0#rfc.section.5.1]
     def escape(value)
-      URI::escape(value.to_s, OAuth::RESERVED_CHARACTERS)
+      _escape(value.to_s.to_str)
     rescue ArgumentError
-      URI::escape(value.to_s.force_encoding(Encoding::UTF_8), OAuth::RESERVED_CHARACTERS)
+      _escape(value.to_s.to_str.force_encoding(Encoding::UTF_8))
+    end
+
+    def _escape(string)
+      URI.escape(string, OAuth::RESERVED_CHARACTERS)
+    end
+
+    def unescape(value)
+      URI.unescape(value.gsub('+', '%2B'))
     end
 
     # Generate a random key of up to +size+ bytes. The value returned is Base64 encoded with non-word
@@ -49,7 +57,7 @@ module OAuth
         end
       end * "&"
     end
-    
+
     #Returns a string representation of the Hash like in URL query string
     # build_nested_query({:level_1 => {:level_2 => ['value_1','value_2']}}, 'prefix'))
     #   #=> ["prefix%5Blevel_1%5D%5Blevel_2%5D%5B%5D=value_1", "prefix%5Blevel_1%5D%5Blevel_2%5D%5B%5D=value_2"]
@@ -94,10 +102,6 @@ module OAuth
       Hash[*params.flatten]
     end
 
-    def unescape(value)
-      URI.unescape(value.gsub('+', '%2B'))
-    end
-
     def stringify_keys(hash)
       new_h = {}
       hash.each do |k, v|
diff --git a/lib/oauth/request_proxy/action_controller_request.rb b/lib/oauth/request_proxy/action_controller_request.rb
index 39ecd5b..dadfea4 100644
--- a/lib/oauth/request_proxy/action_controller_request.rb
+++ b/lib/oauth/request_proxy/action_controller_request.rb
@@ -1,11 +1,35 @@
 require 'active_support'
+require "active_support/version"
 require 'action_controller'
-require 'action_controller/request'
 require 'uri'
 
+if
+  Gem::Version.new(ActiveSupport::VERSION::STRING) < Gem::Version.new("3")
+then # rails 2.x
+  require 'action_controller/request'
+  unless ActionController::Request::HTTP_METHODS.include?("patch")
+    ActionController::Request::HTTP_METHODS << "patch"
+    ActionController::Request::HTTP_METHOD_LOOKUP["PATCH"] = :patch
+    ActionController::Request::HTTP_METHOD_LOOKUP["patch"] = :patch
+  end
+
+elsif
+  Gem::Version.new(ActiveSupport::VERSION::STRING) < Gem::Version.new("4")
+then # rails 3.x
+  require 'action_dispatch/http/request'
+  unless ActionDispatch::Request::HTTP_METHODS.include?("patch")
+    ActionDispatch::Request::HTTP_METHODS << "patch"
+    ActionDispatch::Request::HTTP_METHOD_LOOKUP["PATCH"] = :patch
+    ActionDispatch::Request::HTTP_METHOD_LOOKUP["patch"] = :patch
+  end
+
+else # rails 4.x - already has patch
+  require 'action_dispatch/http/request'
+end
+
 module OAuth::RequestProxy
   class ActionControllerRequest < OAuth::RequestProxy::Base
-    proxies(defined?(ActionController::AbstractRequest) ? ActionController::AbstractRequest : ActionController::Request)
+    proxies(defined?(ActionDispatch::AbstractRequest) ? ActionDispatch::AbstractRequest : ActionDispatch::Request)
 
     def method
       request.method.to_s.upcase
@@ -43,7 +67,7 @@ module OAuth::RequestProxy
 
       params.
         join('&').split('&').
-        reject(&:blank?).
+        reject { |s| s.match(/\A\s*\z/) }.
         map { |p| p.split('=').map{|esc| CGI.unescape(esc)} }.
         reject { |kv| kv[0] == 'oauth_signature'}
     end
diff --git a/lib/oauth/request_proxy/base.rb b/lib/oauth/request_proxy/base.rb
index 039ef5e..c1a8c57 100644
--- a/lib/oauth/request_proxy/base.rb
+++ b/lib/oauth/request_proxy/base.rb
@@ -76,7 +76,7 @@ module OAuth::RequestProxy
     end
 
     def parameters_for_signature
-      parameters.reject { |k,v| k == "oauth_signature" || unsigned_parameters.include?(k)}
+      parameters.select { |k,v| not signature_and_unsigned_parameters.include?(k) }
     end
 
     def oauth_parameters
@@ -87,6 +87,10 @@ module OAuth::RequestProxy
       parameters.reject { |k,v| OAuth::PARAMETERS.include?(k) }
     end
 
+    def signature_and_unsigned_parameters
+      unsigned_parameters+["oauth_signature"]
+    end
+
     # See 9.1.2 in specs
     def normalized_uri
       u = URI.parse(uri)
@@ -143,10 +147,10 @@ module OAuth::RequestProxy
     end
 
     def query_string_blank?
-      if uri = request.request_uri
+      if uri = request.env['REQUEST_URI']
         uri.split('?', 2)[1].nil?
       else
-        request.query_string.blank?
+        request.query_string.match(/\A\s*\z/)
       end
     end
 
diff --git a/lib/oauth/request_proxy/net_http.rb b/lib/oauth/request_proxy/net_http.rb
index 23c5c06..59d0dbc 100644
--- a/lib/oauth/request_proxy/net_http.rb
+++ b/lib/oauth/request_proxy/net_http.rb
@@ -66,7 +66,7 @@ module OAuth::RequestProxy::Net
 
       def auth_header_params
         return nil unless request['Authorization'] && request['Authorization'][0,5] == 'OAuth'
-        auth_params = request['Authorization']
+        request['Authorization']
       end
     end
   end
diff --git a/lib/oauth/request_proxy/rest_client_request.rb b/lib/oauth/request_proxy/rest_client_request.rb
new file mode 100644
index 0000000..b49e24a
--- /dev/null
+++ b/lib/oauth/request_proxy/rest_client_request.rb
@@ -0,0 +1,62 @@
+require 'oauth/request_proxy/base'
+require 'rest-client'
+require 'uri'
+require 'cgi'
+
+module OAuth::RequestProxy::RestClient
+  class Request < OAuth::RequestProxy::Base
+    proxies RestClient::Request
+    
+      def method
+        request.method.to_s.upcase
+      end
+
+      def uri
+        request.url
+      end
+
+      def parameters
+        if options[:clobber_request]
+          options[:parameters] || {}
+        else
+          post_parameters.merge(query_params).merge(options[:parameters] || {})
+        end
+      end
+
+    protected
+
+      def query_params
+        query = URI.parse(request.url).query
+        query ? CGI.parse(query) : {}
+      end
+
+      def request_params
+      end
+      
+      def post_parameters
+        # Post params are only used if posting form data
+        if method == 'POST' || method == 'PUT'
+          OAuth::Helper.stringify_keys(query_string_to_hash(request.payload.to_s) || {})
+        else
+          {}
+        end
+      end
+      
+   private
+      
+      def query_string_to_hash(query)
+        keyvals = query.split('&').inject({}) do |result, q| 
+          k,v = q.split('=')
+          if !v.nil?
+             result.merge({k => v})
+          elsif !result.key?(k)
+            result.merge({k => true})
+          else
+            result
+          end
+        end
+        keyvals
+      end
+      
+  end
+end
\ No newline at end of file
diff --git a/lib/oauth/request_proxy/typhoeus_request.rb b/lib/oauth/request_proxy/typhoeus_request.rb
index d72a5e9..ebcb354 100644
--- a/lib/oauth/request_proxy/typhoeus_request.rb
+++ b/lib/oauth/request_proxy/typhoeus_request.rb
@@ -11,7 +11,7 @@ module OAuth::RequestProxy::Typhoeus
     # oauth_params = {:consumer => oauth_consumer, :token => access_token}
     # req = Typhoeus::Request.new(uri, options)
     # oauth_helper = OAuth::Client::Helper.new(req, oauth_params.merge(:request_uri => uri))
-    # req.headers.merge!({"Authorization" => oauth_helper.header})
+    # req.options[:headers].merge!({"Authorization" => oauth_helper.header})
     # hydra = Typhoeus::Hydra.new()
     # hydra.queue(req)
     # hydra.run
@@ -19,7 +19,8 @@ module OAuth::RequestProxy::Typhoeus
     proxies Typhoeus::Request
 
     def method
-      request.method.to_s.upcase
+      request_method = request.options[:method].to_s.upcase
+      request_method.empty? ? 'GET' : request_method
     end
 
     def uri
@@ -44,7 +45,7 @@ module OAuth::RequestProxy::Typhoeus
     def post_parameters
       # Post params are only used if posting form data
       if method == 'POST'
-        OAuth::Helper.stringify_keys(request.params || {})
+        OAuth::Helper.stringify_keys(request.options[:params] || {})
       else
         {}
       end
diff --git a/lib/oauth/signature/base.rb b/lib/oauth/signature/base.rb
index 8d1f5cb..b8ab8fe 100644
--- a/lib/oauth/signature/base.rb
+++ b/lib/oauth/signature/base.rb
@@ -16,21 +16,6 @@ module OAuth::Signature
       OAuth::Signature.available_methods[@implements] = self
     end
 
-    def self.digest_class(digest_class = nil)
-      return @digest_class if digest_class.nil?
-      @digest_class = digest_class
-    end
-
-    def self.digest_klass(digest_klass = nil)
-      return @digest_klass if digest_klass.nil?
-      @digest_klass = digest_klass
-    end
-
-    def self.hash_class(hash_class = nil)
-      return @hash_class if hash_class.nil?
-      @hash_class = hash_class
-    end
-
     def initialize(request, options = {}, &block)
       raise TypeError unless request.kind_of?(OAuth::RequestProxy::Base)
       @request = request
@@ -66,7 +51,7 @@ module OAuth::Signature
     end
 
     def ==(cmp_signature)
-      Base64.decode64(signature) == Base64.decode64(cmp_signature)
+      signature == cmp_signature
     end
 
     def verify
@@ -78,14 +63,10 @@ module OAuth::Signature
     end
 
     def body_hash
-      if self.class.hash_class
-        Base64.encode64(self.class.hash_class.digest(request.body || '')).chomp.gsub(/\n/,'')
-      else
-        nil # no body hash algorithm defined, so don't generate one
-      end
+      raise_instantiation_error
     end
 
-  private
+    private
 
     def token
       request.token
@@ -104,7 +85,12 @@ module OAuth::Signature
     end
 
     def digest
-      self.class.digest_class.digest(signature_base_string)
+      raise_instantiation_error
     end
+
+    def raise_instantiation_error
+      raise NotImplementedError, "Cannot instantiate #{self.class.name} class directly."
+    end
+
   end
 end
diff --git a/lib/oauth/signature/hmac/base.rb b/lib/oauth/signature/hmac/base.rb
deleted file mode 100644
index 18eb1f2..0000000
--- a/lib/oauth/signature/hmac/base.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- encoding: utf-8 -*-
-
-require 'oauth/signature/base'
-require 'digest/hmac'
-
-module OAuth::Signature::HMAC
-  class Base < OAuth::Signature::Base
-
-  private
-    def digest
-      self.class.digest_class Object.module_eval("::Digest::#{self.class.digest_klass}")
-      Digest::HMAC.digest(signature_base_string, secret, self.class.digest_class)
-    end
-  end
-end
diff --git a/lib/oauth/signature/hmac/md5.rb b/lib/oauth/signature/hmac/md5.rb
deleted file mode 100644
index 15d6db4..0000000
--- a/lib/oauth/signature/hmac/md5.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-require 'oauth/signature/hmac/base'
-
-module OAuth::Signature::HMAC
-  class MD5 < Base
-    implements 'hmac-md5'
-    digest_class 'MD5'
-  end
-end
diff --git a/lib/oauth/signature/hmac/rmd160.rb b/lib/oauth/signature/hmac/rmd160.rb
deleted file mode 100644
index b8dc3c3..0000000
--- a/lib/oauth/signature/hmac/rmd160.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-require 'oauth/signature/hmac/base'
-
-module OAuth::Signature::HMAC
-  class RMD160 < Base
-    implements 'hmac-rmd160'
-    digest_klass 'RMD160'
-  end
-end
diff --git a/lib/oauth/signature/hmac/sha1.rb b/lib/oauth/signature/hmac/sha1.rb
index dd0b2af..ccddf41 100644
--- a/lib/oauth/signature/hmac/sha1.rb
+++ b/lib/oauth/signature/hmac/sha1.rb
@@ -1,9 +1,17 @@
-require 'oauth/signature/hmac/base'
+require 'oauth/signature/base'
 
 module OAuth::Signature::HMAC
-  class SHA1 < Base
+  class SHA1 < OAuth::Signature::Base
     implements 'hmac-sha1'
-    digest_klass 'SHA1'
-    hash_class ::Digest::SHA1
+
+    def body_hash
+      Base64.encode64(OpenSSL::Digest::SHA1.digest(request.body || '')).chomp.gsub(/\n/,'')
+    end
+
+    private
+
+    def digest
+      OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), secret, signature_base_string)
+    end
   end
 end
diff --git a/lib/oauth/signature/hmac/sha2.rb b/lib/oauth/signature/hmac/sha2.rb
deleted file mode 100644
index 4954136..0000000
--- a/lib/oauth/signature/hmac/sha2.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-require 'oauth/signature/hmac/base'
-
-module OAuth::Signature::HMAC
-  class SHA2 < Base
-    implements 'hmac-sha2'
-    digest_klass 'SHA2'
-  end
-end
diff --git a/lib/oauth/signature/md5.rb b/lib/oauth/signature/md5.rb
deleted file mode 100644
index 620f6f7..0000000
--- a/lib/oauth/signature/md5.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'oauth/signature/base'
-require 'digest/md5'
-
-module OAuth::Signature
-  class MD5 < Base
-    implements 'md5'
-    digest_class Digest::MD5
-
-    def signature_base_string
-      secret + super
-    end
-  end
-end
diff --git a/lib/oauth/signature/plaintext.rb b/lib/oauth/signature/plaintext.rb
index 71c445c..43c1028 100644
--- a/lib/oauth/signature/plaintext.rb
+++ b/lib/oauth/signature/plaintext.rb
@@ -16,6 +16,12 @@ module OAuth::Signature
       secret
     end
 
+    def body_hash
+      nil
+    end
+
+    private
+
     def secret
       super
     end
diff --git a/lib/oauth/signature/rsa/sha1.rb b/lib/oauth/signature/rsa/sha1.rb
index 018852a..276e2e4 100644
--- a/lib/oauth/signature/rsa/sha1.rb
+++ b/lib/oauth/signature/rsa/sha1.rb
@@ -1,10 +1,8 @@
 require 'oauth/signature/base'
-require 'openssl'
 
 module OAuth::Signature::RSA
   class SHA1 < OAuth::Signature::Base
     implements 'rsa-sha1'
-    hash_class ::Digest::SHA1
 
     def ==(cmp_signature)
       public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(cmp_signature.is_a?(Array) ? cmp_signature.first : cmp_signature), signature_base_string)
@@ -20,7 +18,11 @@ module OAuth::Signature::RSA
       end
     end
 
-  private
+    def body_hash
+      Base64.encode64(OpenSSL::Digest::SHA1.digest(request.body || '')).chomp.gsub(/\n/,'')
+    end
+
+    private
 
     def decode_public_key
       case consumer_secret
@@ -35,6 +37,8 @@ module OAuth::Signature::RSA
       private_key = OpenSSL::PKey::RSA.new(
         if options[:private_key_file]
           IO.read(options[:private_key_file])
+        elsif options[:private_key]
+          options[:private_key]
         else
           consumer_secret
         end
diff --git a/lib/oauth/signature/sha1.rb b/lib/oauth/signature/sha1.rb
deleted file mode 100644
index 40493e2..0000000
--- a/lib/oauth/signature/sha1.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'oauth/signature/base'
-require 'digest/sha1'
-
-module OAuth::Signature
-  class SHA1 < Base
-    implements 'sha1'
-    digest_class Digest::SHA1
-
-    def signature_base_string
-      secret + super
-    end
-  end
-end
diff --git a/lib/oauth/tokens/access_token.rb b/lib/oauth/tokens/access_token.rb
index 8d3f01b..35a2ef7 100644
--- a/lib/oauth/tokens/access_token.rb
+++ b/lib/oauth/tokens/access_token.rb
@@ -59,6 +59,18 @@ module OAuth
       request(:put, path, body, headers)
     end
 
+    # Make a regular PATCH request using AccessToken
+    #
+    #   @response = @token.patch('/people/123')
+    #   @response = @token.patch('/people/123', { :name => 'Bob', :email => 'bob at mailinator.com' })
+    #   @response = @token.patch('/people/123', { :name => 'Bob', :email => 'bob at mailinator.com' }, { 'Accept' => 'application/xml' })
+    #   @response = @token.patch('/people/123', nil, { 'Accept' => 'application/xml' })
+    #   @response = @token.patch('/people/123', @person.to_xml, { 'Accept' => 'application/xml', 'Content-Type' => 'application/xml' })
+    #
+    def patch(path, body = '', headers = {})
+      request(:patch, path, body, headers)
+    end
+
     # Make a regular DELETE request using AccessToken
     #
     #   @response = @token.delete('/people/123')
diff --git a/lib/oauth/tokens/request_token.rb b/lib/oauth/tokens/request_token.rb
index f2ee654..39187cd 100644
--- a/lib/oauth/tokens/request_token.rb
+++ b/lib/oauth/tokens/request_token.rb
@@ -5,6 +5,8 @@ module OAuth
 
     # Generate an authorization URL for user authorization
     def authorize_url(params = nil)
+      return nil if self.token.nil?
+
       params = (params || {}).merge(:oauth_token => self.token)
       build_authorize_url(consumer.authorize_url, params)
     end
@@ -24,8 +26,11 @@ module OAuth
     # construct an authorization url
     def build_authorize_url(base_url, params)
       uri = URI.parse(base_url.to_s)
+      queries = {}
+      queries = Hash[URI.decode_www_form(uri.query)] if uri.query
       # TODO doesn't handle array values correctly
-      uri.query = params.map { |k,v| [k, CGI.escape(v)] * "=" } * "&"
+      queries.merge!(params) if params
+      uri.query = URI.encode_www_form(queries) if !queries.empty?
       uri.to_s
     end
   end
diff --git a/lib/oauth/tokens/token.rb b/lib/oauth/tokens/token.rb
index ff9b5dd..0757396 100644
--- a/lib/oauth/tokens/token.rb
+++ b/lib/oauth/tokens/token.rb
@@ -11,7 +11,7 @@ module OAuth
     end
 
     def to_query
-      "oauth_token=#{escape(token)}&oauth_secret=#{escape(secret)}"
+      "oauth_token=#{escape(token)}&oauth_token_secret=#{escape(secret)}"
     end
   end
 end
diff --git a/lib/oauth/version.rb b/lib/oauth/version.rb
new file mode 100644
index 0000000..ef41e04
--- /dev/null
+++ b/lib/oauth/version.rb
@@ -0,0 +1,3 @@
+module OAuth
+  VERSION = "0.5.3"
+end
diff --git a/metadata.yml b/metadata.yml
deleted file mode 100644
index 604b470..0000000
--- a/metadata.yml
+++ /dev/null
@@ -1,270 +0,0 @@
---- !ruby/object:Gem::Specification
-name: oauth
-version: !ruby/object:Gem::Version
-  version: 0.4.7
-  prerelease: 
-platform: ruby
-authors:
-- Pelle Braendgaard
-- Blaine Cook
-- Larry Halff
-- Jesse Clark
-- Jon Crosby
-- Seth Fitzsimmons
-- Matt Sanford
-- Aaron Quint
-autorequire: 
-bindir: bin
-cert_chain: []
-date: 2012-09-04 00:00:00.000000000 Z
-dependencies:
-- !ruby/object:Gem::Dependency
-  name: rake
-  requirement: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: jeweler
-  requirement: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: actionpack
-  requirement: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 2.3.5
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 2.3.5
-- !ruby/object:Gem::Dependency
-  name: rack
-  requirement: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 1.0.0
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 1.0.0
-- !ruby/object:Gem::Dependency
-  name: mocha
-  requirement: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 0.9.8
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 0.9.8
-- !ruby/object:Gem::Dependency
-  name: typhoeus
-  requirement: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 0.1.13
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 0.1.13
-- !ruby/object:Gem::Dependency
-  name: em-http-request
-  requirement: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 0.2.10
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 0.2.10
-- !ruby/object:Gem::Dependency
-  name: curb
-  requirement: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 0.6.6.0
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    none: false
-    requirements:
-    - - ! '>='
-      - !ruby/object:Gem::Version
-        version: 0.6.6.0
-description: OAuth Core Ruby implementation
-email: oauth-ruby at googlegroups.com
-executables:
-- oauth
-extensions: []
-extra_rdoc_files:
-- LICENSE
-- README.rdoc
-- TODO
-files:
-- .gemtest
-- Gemfile
-- Gemfile.lock
-- HISTORY
-- LICENSE
-- README.rdoc
-- Rakefile
-- TODO
-- bin/oauth
-- examples/yql.rb
-- lib/digest/hmac.rb
-- lib/oauth.rb
-- lib/oauth/cli.rb
-- lib/oauth/client.rb
-- lib/oauth/client/action_controller_request.rb
-- lib/oauth/client/em_http.rb
-- lib/oauth/client/helper.rb
-- lib/oauth/client/net_http.rb
-- lib/oauth/consumer.rb
-- lib/oauth/core_ext.rb
-- lib/oauth/errors.rb
-- lib/oauth/errors/error.rb
-- lib/oauth/errors/problem.rb
-- lib/oauth/errors/unauthorized.rb
-- lib/oauth/helper.rb
-- lib/oauth/oauth.rb
-- lib/oauth/oauth_test_helper.rb
-- lib/oauth/request_proxy.rb
-- lib/oauth/request_proxy/action_controller_request.rb
-- lib/oauth/request_proxy/base.rb
-- lib/oauth/request_proxy/curb_request.rb
-- lib/oauth/request_proxy/em_http_request.rb
-- lib/oauth/request_proxy/jabber_request.rb
-- lib/oauth/request_proxy/mock_request.rb
-- lib/oauth/request_proxy/net_http.rb
-- lib/oauth/request_proxy/rack_request.rb
-- lib/oauth/request_proxy/typhoeus_request.rb
-- lib/oauth/server.rb
-- lib/oauth/signature.rb
-- lib/oauth/signature/base.rb
-- lib/oauth/signature/hmac/base.rb
-- lib/oauth/signature/hmac/md5.rb
-- lib/oauth/signature/hmac/rmd160.rb
-- lib/oauth/signature/hmac/sha1.rb
-- lib/oauth/signature/hmac/sha2.rb
-- lib/oauth/signature/md5.rb
-- lib/oauth/signature/plaintext.rb
-- lib/oauth/signature/rsa/sha1.rb
-- lib/oauth/signature/sha1.rb
-- lib/oauth/token.rb
-- lib/oauth/tokens/access_token.rb
-- lib/oauth/tokens/consumer_token.rb
-- lib/oauth/tokens/request_token.rb
-- lib/oauth/tokens/server_token.rb
-- lib/oauth/tokens/token.rb
-- oauth.gemspec
-- tasks/deployment.rake
-- tasks/environment.rake
-- tasks/website.rake
-- test/cases/oauth_case.rb
-- test/cases/spec/1_0-final/test_construct_request_url.rb
-- test/cases/spec/1_0-final/test_normalize_request_parameters.rb
-- test/cases/spec/1_0-final/test_parameter_encodings.rb
-- test/cases/spec/1_0-final/test_signature_base_strings.rb
-- test/integration/consumer_test.rb
-- test/keys/rsa.cert
-- test/keys/rsa.pem
-- test/test_access_token.rb
-- test/test_action_controller_request_proxy.rb
-- test/test_consumer.rb
-- test/test_curb_request_proxy.rb
-- test/test_em_http_client.rb
-- test/test_em_http_request_proxy.rb
-- test/test_helper.rb
-- test/test_hmac_sha1.rb
-- test/test_net_http_client.rb
-- test/test_net_http_request_proxy.rb
-- test/test_oauth_helper.rb
-- test/test_rack_request_proxy.rb
-- test/test_request_token.rb
-- test/test_rsa_sha1.rb
-- test/test_server.rb
-- test/test_signature.rb
-- test/test_signature_base.rb
-- test/test_signature_plain_text.rb
-- test/test_token.rb
-- test/test_typhoeus_request_proxy.rb
-homepage: 
-licenses: []
-post_install_message: 
-rdoc_options: []
-require_paths:
-- lib
-required_ruby_version: !ruby/object:Gem::Requirement
-  none: false
-  requirements:
-  - - ! '>='
-    - !ruby/object:Gem::Version
-      version: '0'
-required_rubygems_version: !ruby/object:Gem::Requirement
-  none: false
-  requirements:
-  - - ! '>='
-    - !ruby/object:Gem::Version
-      version: '0'
-requirements: []
-rubyforge_project: oauth
-rubygems_version: 1.8.23
-signing_key: 
-specification_version: 3
-summary: OAuth Core Ruby implementation
-test_files: []
diff --git a/oauth.gemspec b/oauth.gemspec
index e46ab4a..c4c4f31 100644
--- a/oauth.gemspec
+++ b/oauth.gemspec
@@ -1,148 +1,43 @@
-# Generated by jeweler
-# DO NOT EDIT THIS FILE DIRECTLY
-# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
 # -*- encoding: utf-8 -*-
 
-Gem::Specification.new do |s|
-  s.name = "oauth"
-  s.version = "0.4.7"
+lib = File.expand_path("../lib/", __FILE__)
+$:.unshift lib unless $:.include?(lib)
 
-  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
-  s.authors = ["Pelle Braendgaard", "Blaine Cook", "Larry Halff", "Jesse Clark", "Jon Crosby", "Seth Fitzsimmons", "Matt Sanford", "Aaron Quint"]
-  s.date = "2012-09-04"
-  s.description = "OAuth Core Ruby implementation"
-  s.email = "oauth-ruby at googlegroups.com"
-  s.executables = ["oauth"]
-  s.extra_rdoc_files = [
-    "LICENSE",
-    "README.rdoc",
-    "TODO"
-  ]
-  s.files = [
-    ".gemtest",
-    "Gemfile",
-    "Gemfile.lock",
-    "HISTORY",
-    "LICENSE",
-    "README.rdoc",
-    "Rakefile",
-    "TODO",
-    "bin/oauth",
-    "examples/yql.rb",
-    "lib/digest/hmac.rb",
-    "lib/oauth.rb",
-    "lib/oauth/cli.rb",
-    "lib/oauth/client.rb",
-    "lib/oauth/client/action_controller_request.rb",
-    "lib/oauth/client/em_http.rb",
-    "lib/oauth/client/helper.rb",
-    "lib/oauth/client/net_http.rb",
-    "lib/oauth/consumer.rb",
-    "lib/oauth/core_ext.rb",
-    "lib/oauth/errors.rb",
-    "lib/oauth/errors/error.rb",
-    "lib/oauth/errors/problem.rb",
-    "lib/oauth/errors/unauthorized.rb",
-    "lib/oauth/helper.rb",
-    "lib/oauth/oauth.rb",
-    "lib/oauth/oauth_test_helper.rb",
-    "lib/oauth/request_proxy.rb",
-    "lib/oauth/request_proxy/action_controller_request.rb",
-    "lib/oauth/request_proxy/base.rb",
-    "lib/oauth/request_proxy/curb_request.rb",
-    "lib/oauth/request_proxy/em_http_request.rb",
-    "lib/oauth/request_proxy/jabber_request.rb",
-    "lib/oauth/request_proxy/mock_request.rb",
-    "lib/oauth/request_proxy/net_http.rb",
-    "lib/oauth/request_proxy/rack_request.rb",
-    "lib/oauth/request_proxy/typhoeus_request.rb",
-    "lib/oauth/server.rb",
-    "lib/oauth/signature.rb",
-    "lib/oauth/signature/base.rb",
-    "lib/oauth/signature/hmac/base.rb",
-    "lib/oauth/signature/hmac/md5.rb",
-    "lib/oauth/signature/hmac/rmd160.rb",
-    "lib/oauth/signature/hmac/sha1.rb",
-    "lib/oauth/signature/hmac/sha2.rb",
-    "lib/oauth/signature/md5.rb",
-    "lib/oauth/signature/plaintext.rb",
-    "lib/oauth/signature/rsa/sha1.rb",
-    "lib/oauth/signature/sha1.rb",
-    "lib/oauth/token.rb",
-    "lib/oauth/tokens/access_token.rb",
-    "lib/oauth/tokens/consumer_token.rb",
-    "lib/oauth/tokens/request_token.rb",
-    "lib/oauth/tokens/server_token.rb",
-    "lib/oauth/tokens/token.rb",
-    "oauth.gemspec",
-    "tasks/deployment.rake",
-    "tasks/environment.rake",
-    "tasks/website.rake",
-    "test/cases/oauth_case.rb",
-    "test/cases/spec/1_0-final/test_construct_request_url.rb",
-    "test/cases/spec/1_0-final/test_normalize_request_parameters.rb",
-    "test/cases/spec/1_0-final/test_parameter_encodings.rb",
-    "test/cases/spec/1_0-final/test_signature_base_strings.rb",
-    "test/integration/consumer_test.rb",
-    "test/keys/rsa.cert",
-    "test/keys/rsa.pem",
-    "test/test_access_token.rb",
-    "test/test_action_controller_request_proxy.rb",
-    "test/test_consumer.rb",
-    "test/test_curb_request_proxy.rb",
-    "test/test_em_http_client.rb",
-    "test/test_em_http_request_proxy.rb",
-    "test/test_helper.rb",
-    "test/test_hmac_sha1.rb",
-    "test/test_net_http_client.rb",
-    "test/test_net_http_request_proxy.rb",
-    "test/test_oauth_helper.rb",
-    "test/test_rack_request_proxy.rb",
-    "test/test_request_token.rb",
-    "test/test_rsa_sha1.rb",
-    "test/test_server.rb",
-    "test/test_signature.rb",
-    "test/test_signature_base.rb",
-    "test/test_signature_plain_text.rb",
-    "test/test_token.rb",
-    "test/test_typhoeus_request_proxy.rb"
-  ]
-  s.require_paths = ["lib"]
-  s.rubyforge_project = "oauth"
-  s.rubygems_version = "1.8.23"
-  s.summary = "OAuth Core Ruby implementation"
+require "oauth/version"
 
-  if s.respond_to? :specification_version then
-    s.specification_version = 3
+Gem::Specification.new do |spec|
+  spec.name    = "oauth"
+  spec.version = OAuth::VERSION
+  spec.license = "MIT"
 
-    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
-      s.add_development_dependency(%q<rake>, [">= 0"])
-      s.add_development_dependency(%q<jeweler>, [">= 0"])
-      s.add_development_dependency(%q<actionpack>, [">= 2.3.5"])
-      s.add_development_dependency(%q<rack>, [">= 1.0.0"])
-      s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
-      s.add_development_dependency(%q<typhoeus>, [">= 0.1.13"])
-      s.add_development_dependency(%q<em-http-request>, [">= 0.2.10"])
-      s.add_development_dependency(%q<curb>, [">= 0.6.6.0"])
-    else
-      s.add_dependency(%q<rake>, [">= 0"])
-      s.add_dependency(%q<jeweler>, [">= 0"])
-      s.add_dependency(%q<actionpack>, [">= 2.3.5"])
-      s.add_dependency(%q<rack>, [">= 1.0.0"])
-      s.add_dependency(%q<mocha>, [">= 0.9.8"])
-      s.add_dependency(%q<typhoeus>, [">= 0.1.13"])
-      s.add_dependency(%q<em-http-request>, [">= 0.2.10"])
-      s.add_dependency(%q<curb>, [">= 0.6.6.0"])
-    end
-  else
-    s.add_dependency(%q<rake>, [">= 0"])
-    s.add_dependency(%q<jeweler>, [">= 0"])
-    s.add_dependency(%q<actionpack>, [">= 2.3.5"])
-    s.add_dependency(%q<rack>, [">= 1.0.0"])
-    s.add_dependency(%q<mocha>, [">= 0.9.8"])
-    s.add_dependency(%q<typhoeus>, [">= 0.1.13"])
-    s.add_dependency(%q<em-http-request>, [">= 0.2.10"])
-    s.add_dependency(%q<curb>, [">= 0.6.6.0"])
-  end
-end
+  spec.authors     = ["Pelle Braendgaard", "Blaine Cook", "Larry Halff", "Jesse Clark", "Jon Crosby", "Seth Fitzsimmons", "Matt Sanford", "Aaron Quint"]
+  spec.email       = "oauth-ruby at googlegroupspec.com"
+  spec.summary     = "OAuth Core Ruby implementation"
+
+  spec.executables = ["oauth"]
+  spec.files       = Dir.glob("lib/**/*.rb")
+  #spec.test_files  = Dir.glob("test/**/*.rb") + Dir.glob('test/keys/*')
+  spec.extra_rdoc_files = [ "LICENSE", "README.rdoc", "TODO" ]
+
+  # This gem will work with 2.0 or greater...
+  spec.required_ruby_version = '>= 2.0'
 
+  # Nokogiri 1.7 does not accept Ruby 2.0
+  spec.add_development_dependency("nokogiri", "~> 1.6.8") if RUBY_VERSION < "2.1"
+
+  spec.add_development_dependency("rake")
+  spec.add_development_dependency("minitest")
+  spec.add_development_dependency("byebug")
+  spec.add_development_dependency("actionpack", "~> 4.0")
+  spec.add_development_dependency("iconv")
+  spec.add_development_dependency("rack", "~> 1.0")
+  spec.add_development_dependency("rack-test")
+  spec.add_development_dependency("mocha", ">= 0.9.12")
+  spec.add_development_dependency("typhoeus", ">= 0.1.13")
+  spec.add_development_dependency("em-http-request", "0.2.11")
+  spec.add_development_dependency("curb")
+  spec.add_development_dependency("webmock", "< 2.0")
+  spec.add_development_dependency("codeclimate-test-reporter")
+  spec.add_development_dependency("simplecov")
+  spec.add_development_dependency("rest-client")
+end
diff --git a/tasks/deployment.rake b/tasks/deployment.rake
deleted file mode 100644
index 430dad3..0000000
--- a/tasks/deployment.rake
+++ /dev/null
@@ -1,34 +0,0 @@
-desc 'Release the website and new gem version'
-task :deploy => [:check_version, :website, :release] do
-  puts "Remember to create SVN tag:"
-  puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
-    "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
-  puts "Suggested comment:"
-  puts "Tagging release #{CHANGES}"
-end
-
-desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
-task :local_deploy => [:website_generate, :install_gem]
-
-task :check_version do
-  unless ENV['VERSION']
-    puts 'Must pass a VERSION=x.y.z release version'
-    exit
-  end
-  unless ENV['VERSION'] == VERS
-    puts "Please update your version.rb to match the release version, currently #{VERS}"
-    exit
-  end
-end
-
-desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
-task :install_gem_no_doc => [:clean, :package] do
-  sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
-end
-
-namespace :manifest do
-  desc 'Recreate Manifest.txt to include ALL files'
-  task :refresh do
-    `rake check_manifest | patch -p0 > Manifest.txt`
-  end
-end
diff --git a/tasks/environment.rake b/tasks/environment.rake
deleted file mode 100644
index 691ed3b..0000000
--- a/tasks/environment.rake
+++ /dev/null
@@ -1,7 +0,0 @@
-task :ruby_env do
-  RUBY_APP = if RUBY_PLATFORM =~ /java/
-    "jruby"
-  else
-    "ruby"
-  end unless defined? RUBY_APP
-end
diff --git a/tasks/website.rake b/tasks/website.rake
deleted file mode 100644
index 93e03fa..0000000
--- a/tasks/website.rake
+++ /dev/null
@@ -1,17 +0,0 @@
-desc 'Generate website files'
-task :website_generate => :ruby_env do
-  (Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt|
-    sh %{ #{RUBY_APP} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
-  end
-end
-
-desc 'Upload website files to rubyforge'
-task :website_upload do
-  host = "#{rubyforge_username}@rubyforge.org"
-  remote_dir = "/var/www/gforge-projects/#{PATH}/"
-  local_dir = 'website'
-  sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
-end
-
-desc 'Generate and upload website files'
-task :website => [:website_generate, :website_upload, :publish_docs]
diff --git a/test/cases/oauth_case.rb b/test/cases/oauth_case.rb
index 8b37dcf..8c4d425 100644
--- a/test/cases/oauth_case.rb
+++ b/test/cases/oauth_case.rb
@@ -1,11 +1,12 @@
-require 'test/unit'
+require 'minitest/autorun'
 require 'oauth/signature'
 require 'oauth/request_proxy/mock_request'
 
 
-class OAuthCase < Test::Unit::TestCase
+class OAuthCase < Minitest::Test
   # avoid whining about a lack of tests
   def run(*args)
+    @method_name ||= nil
     return if @method_name.to_s == "default_test"
     super
   end
diff --git a/test/cases/spec/1_0-final/test_normalize_request_parameters.rb b/test/cases/spec/1_0-final/test_normalize_request_parameters.rb
index 58b2d63..91c9383 100644
--- a/test/cases/spec/1_0-final/test_normalize_request_parameters.rb
+++ b/test/cases/spec/1_0-final/test_normalize_request_parameters.rb
@@ -27,13 +27,13 @@ require File.expand_path('../../../oauth_case', __FILE__)
 class NormalizeRequestParametersTest < OAuthCase
 
   def test_parameters_for_signature
-    params={'a'=>1, 'c'=>'hi there', 'f'=>'25', 'f'=>'50', 'f'=>'a', 'z'=>'p', 'z'=>'t'}
+    params={"a"=>1, "c"=>"hi there", "f"=>"a", "z"=>"t"}
     assert_equal params,request(params).parameters_for_signature
   end
 
 
   def test_parameters_for_signature_removes_oauth_signature
-    params={'a'=>1, 'c'=>'hi there', 'f'=>'25', 'f'=>'50', 'f'=>'a', 'z'=>'p', 'z'=>'t'}
+    params={"a"=>1, "c"=>"hi there", "f"=>"a", "z"=>"t"}
     assert_equal params,request(params.merge({'oauth_signature'=>'blalbla'})).parameters_for_signature
   end
 
diff --git a/test/integration/consumer_test.rb b/test/integration/consumer_test.rb
index 2a8be70..0aea36a 100644
--- a/test/integration/consumer_test.rb
+++ b/test/integration/consumer_test.rb
@@ -1,7 +1,7 @@
 require File.expand_path('../../test_helper', __FILE__)
 
 module Integration
-  class ConsumerTest < Test::Unit::TestCase
+  class ConsumerTest < Minitest::Test
     def setup
       @consumer=OAuth::Consumer.new(
           'consumer_key_86cad9', '5888bf0345e5d237',
@@ -39,7 +39,7 @@ module Integration
       token = OAuth::ConsumerToken.new(consumer, 'token_411a7f', '3196ffd991c8ebdb')
       token.sign!(request, {:nonce => @nonce, :timestamp => @timestamp})
 
-      assert_no_match( /oauth_signature_method="HMAC-SHA1"/, request['authorization'])
+      refute_match( /oauth_signature_method="HMAC-SHA1"/, request['authorization'])
       assert_match(    /oauth_signature_method="PLAINTEXT"/, request['authorization'])
     end
 
@@ -52,7 +52,7 @@ module Integration
       request = Net::HTTP::Get.new('/')
       signature_base_string = consumer.signature_base_string(request)
 
-      assert_no_match( /HMAC-SHA1/, signature_base_string)
+      refute_match( /HMAC-SHA1/, signature_base_string)
       assert_equal( "#{consumer.secret}&", signature_base_string)
     end
 
@@ -86,8 +86,8 @@ module Integration
 
       assert_equal 'POST', request.method
       assert_equal '/test', request.path
-      assert_match /key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=26g7wHTtNO6ZWJaLltcueppHYiI%3[Dd]&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0/, request.body.split("&").sort.join("&")
-      assert_equal nil, request['authorization']
+      assert_match(/key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=26g7wHTtNO6ZWJaLltcueppHYiI%3[Dd]&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0/, request.body.split("&").sort.join("&"))
+      assert_nil request['authorization']
     end
 
     def test_that_using_auth_headers_on_get_on_create_signed_requests_works
@@ -111,8 +111,8 @@ module Integration
 
       assert_equal 'POST', request.method
       assert_equal '/test', request.path
-      assert_match /key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=26g7wHTtNO6ZWJaLltcueppHYiI%3[Dd]&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0/, request.body.split("&").sort.join("&")
-      assert_equal nil, request['authorization']
+      assert_match(/key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=26g7wHTtNO6ZWJaLltcueppHYiI%3[Dd]&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0/, request.body.split("&").sort.join("&"))
+      assert_nil request['authorization']
     end
 
     def test_step_by_step_token_request
@@ -136,7 +136,7 @@ module Integration
       @consumer.sign!(request, nil,options)
 
       assert_equal 'GET', request.method
-      assert_equal nil, request.body
+      assert_nil request.body
       response=@consumer.http.request(request)
       assert_equal "200",response.code
       assert_equal "oauth_token=requestkey&oauth_token_secret=requestsecret",response.body
@@ -162,23 +162,23 @@ module Integration
       assert !@consumer.authorize_url?, "Should not use fully qualified url"
 
       @request_token=@consumer.get_request_token
-      assert_not_nil @request_token
+      assert @request_token
       assert_equal "requestkey", at request_token.token
       assert_equal "requestsecret", at request_token.secret
       assert_equal "http://term.ie/oauth/example/authorize.php?oauth_token=requestkey", at request_token.authorize_url
 
       @access_token=@request_token.get_access_token
-      assert_not_nil @access_token
+      assert @access_token
       assert_equal "accesskey", at access_token.token
       assert_equal "accesssecret", at access_token.secret
 
       @response=@access_token.get("/oauth/example/echo_api.php?ok=hello&test=this")
-      assert_not_nil @response
+      assert @response
       assert_equal "200", at response.code
       assert_equal( "ok=hello&test=this", at response.body)
 
       @response=@access_token.post("/oauth/example/echo_api.php",{'ok'=>'hello','test'=>'this'})
-      assert_not_nil @response
+      assert @response
       assert_equal "200", at response.code
       assert_equal( "ok=hello&test=this", at response.body)
     end
@@ -203,23 +203,23 @@ module Integration
       assert @consumer.authorize_url?, "Should use fully qualified url"
 
       @request_token=@consumer.get_request_token
-      assert_not_nil @request_token
+      assert @request_token
       assert_equal "requestkey", at request_token.token
       assert_equal "requestsecret", at request_token.secret
       assert_equal "http://term.ie/oauth/example/authorize.php?oauth_token=requestkey", at request_token.authorize_url
 
       @access_token=@request_token.get_access_token
-      assert_not_nil @access_token
+      assert @access_token
       assert_equal "accesskey", at access_token.token
       assert_equal "accesssecret", at access_token.secret
 
       @response=@access_token.get("/oauth/example/echo_api.php?ok=hello&test=this")
-      assert_not_nil @response
+      assert @response
       assert_equal "200", at response.code
       assert_equal( "ok=hello&test=this", at response.body)
 
       @response=@access_token.post("/oauth/example/echo_api.php",{'ok'=>'hello','test'=>'this'})
-      assert_not_nil @response
+      assert @response
       assert_equal "200", at response.code
       assert_equal( "ok=hello&test=this", at response.body)
     end
@@ -283,13 +283,13 @@ module Integration
       request_body_stream = StringIO.new( request_body_string )
 
       @response=@access_token.post("/oauth/example/echo_api.php",request_body_stream)
-      assert_not_nil @response
+      assert @response
       assert_equal "200", at response.code
 
       request_body_file = File.open(__FILE__)
 
       @response=@access_token.post("/oauth/example/echo_api.php",request_body_file)
-      assert_not_nil @response
+      assert @response
       assert_equal "200", at response.code
 
       # unfortunately I don't know of a way to test that the body data was received correctly since the test server at http://term.ie
diff --git a/test/support/minitest_helpers.rb b/test/support/minitest_helpers.rb
new file mode 100644
index 0000000..d3ad41d
--- /dev/null
+++ b/test/support/minitest_helpers.rb
@@ -0,0 +1,22 @@
+module OAuth
+  module MinitestHelpers
+    def assert_matching_headers(expected, actual)
+      # transform into sorted arrays
+      auth_intro, auth_params = actual.split(' ', 2)
+      assert_equal auth_intro, 'OAuth'
+      expected    = expected.split(/(,|\s)/).reject {|v| v == '' || v =~ /^[\,\s]+/}.sort
+      auth_params = auth_params.split(/(,|\s)/).reject {|v| v == '' || v =~ /^[\,\s]+/}.sort
+      assert_equal expected, auth_params
+    end
+
+    def stub_test_ie
+      stub_request(:any, "http://term.ie/oauth/example/request_token.php").to_return(:body => "oauth_token=requestkey&oauth_token_secret=requestsecret")
+      stub_request(:post, "http://term.ie/oauth/example/access_token.php").to_return(:body => "oauth_token=accesskey&oauth_token_secret=accesssecret")
+      stub_request(:get, %r{http://term\.ie/oauth/example/echo_api\.php\?.+}).to_return(lambda {|request| {:body => request.uri.query}})
+      stub_request(:post, "http://term.ie/oauth/example/echo_api.php").to_return(lambda {|request| {:body => request.body}})
+    end
+  end
+end
+
+# TODO: When dropping support to Ruby 2.0, stop using send
+Minitest::Test.send(:include, OAuth::MinitestHelpers)
diff --git a/test/test_helper.rb b/test/test_helper.rb
index c3caaf1..fe77743 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -1,28 +1,26 @@
-require 'test/unit'
-require 'rubygems'
+# ensure test env
+
+ENV['RACK_ENV'] = 'test'
+
+# simplecov, Travis will call codeclimate
+
+require 'simplecov'
+SimpleCov.start
+
+# require third-party code
+
+require 'byebug'
+require 'stringio'
+require 'minitest/autorun'
+require 'mocha/mini_test'
+require 'rack/test'
+require 'webmock/minitest'
+
+# require our lib
 
 $LOAD_PATH << File.dirname(__FILE__) + '/../lib/'
 require 'oauth'
-require 'mocha'
-require 'stringio'
-require 'webmock'
-
-class Test::Unit::TestCase
-  include WebMock::API
-
-  def assert_matching_headers(expected, actual)
-    # transform into sorted arrays
-    auth_intro, auth_params = actual.split(' ', 2)
-    assert_equal auth_intro, 'OAuth'
-    expected    = expected.split(/(,|\s)/).reject {|v| v == '' || v =~ /^[\,\s]+/}.sort
-    auth_params = auth_params.split(/(,|\s)/).reject {|v| v == '' || v =~ /^[\,\s]+/}.sort
-    assert_equal expected, auth_params
-  end
-
-  def stub_test_ie
-    stub_request(:any, "http://term.ie/oauth/example/request_token.php").to_return(:body => "oauth_token=requestkey&oauth_token_secret=requestsecret")
-    stub_request(:post, "http://term.ie/oauth/example/access_token.php").to_return(:body => "oauth_token=accesskey&oauth_token_secret=accesssecret")
-    stub_request(:get, %r{http://term\.ie/oauth/example/echo_api\.php\?.+}).to_return(lambda {|request| {:body => request.uri.query}})
-    stub_request(:post, "http://term.ie/oauth/example/echo_api.php").to_return(lambda {|request| {:body => request.body}})
-  end
-end
+
+# require our support code
+
+require 'support/minitest_helpers'
diff --git a/test/test_signature.rb b/test/test_signature.rb
deleted file mode 100644
index 4fb7041..0000000
--- a/test/test_signature.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- encoding: utf-8 -*-
-
-require File.expand_path('../test_helper', __FILE__)
-
-class TestOauth < Test::Unit::TestCase
-
-  def test_parameter_escaping_kcode_invariant
-    ruby19 = RUBY_VERSION =~ /^1\.9/
-    old = $KCODE if !ruby19
-    begin
-      %w(n N e E s S u U).each do |kcode|
-        $KCODE = kcode if !ruby19
-        assert_equal '%E3%81%82', OAuth::Helper.escape('あ'),
-                      "Failed to correctly escape Japanese under $KCODE = #{kcode}"
-        assert_equal '%C3%A9', OAuth::Helper.escape('é'),
-                      "Failed to correctly escape e+acute under $KCODE = #{kcode}"
-      end
-    ensure
-      $KCODE = old if !ruby19
-    end
-  end
-end
diff --git a/test/test_access_token.rb b/test/units/test_access_token.rb
similarity index 80%
rename from test/test_access_token.rb
rename to test/units/test_access_token.rb
index 591a1c9..ecd9a14 100644
--- a/test/test_access_token.rb
+++ b/test/units/test_access_token.rb
@@ -1,6 +1,6 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 
-class TestAccessToken < Test::Unit::TestCase
+class TestAccessToken < Minitest::Test
   def setup
     @fake_response = {
       :user_id => 5734758743895,
@@ -20,7 +20,7 @@ class TestAccessToken < Test::Unit::TestCase
   end
 
   def test_access_token_makes_non_oauth_response_params_available
-    assert_not_nil @access_token.params[:user_id]
+    assert @access_token.params[:user_id]
     assert_equal 5734758743895, @access_token.params[:user_id]
   end
 end
diff --git a/test/test_action_controller_request_proxy.rb b/test/units/test_action_controller_request_proxy.rb
similarity index 79%
rename from test/test_action_controller_request_proxy.rb
rename to test/units/test_action_controller_request_proxy.rb
index c7c6090..67ea64d 100644
--- a/test/test_action_controller_request_proxy.rb
+++ b/test/units/test_action_controller_request_proxy.rb
@@ -1,20 +1,20 @@
-gem 'actionpack', '~> 2.3.8'
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 
 require 'oauth/request_proxy/action_controller_request'
-require 'action_controller/test_process'
 
-class ActionControllerRequestProxyTest < Test::Unit::TestCase
+class ActionControllerRequestProxyTest < Minitest::Test
 
   def request_proxy(request_method = :get, uri_params = {}, body_params = {})
-    request = ActionController::TestRequest.new
-    request.set_REQUEST_URI('/')
+    request = ActionDispatch::TestRequest.new
+    request.request_uri = '/'
 
     case request_method
     when :post
       request.env['REQUEST_METHOD'] = 'POST'
     when :put
       request.env['REQUEST_METHOD'] = 'PUT'
+    when :patch
+      request.env['REQUEST_METHOD'] = 'PATCH'
     end
 
     request.env['REQUEST_URI'] = '/'
@@ -50,6 +50,14 @@ class ActionControllerRequestProxyTest < Test::Unit::TestCase
     assert_equal 'PUT', request_proxy.method
   end
 
+  def test_that_proxy_simple_patch_request_works_with_query_params
+    request_proxy = request_proxy(:patch, {'key'=>'value'})
+
+    expected_parameters = [["key", "value"]]
+    assert_equal expected_parameters, request_proxy.parameters_for_signature
+    assert_equal 'PATCH', request_proxy.method
+  end
+
   def test_that_proxy_simple_get_request_works_with_post_params
     request_proxy = request_proxy(:get, {}, {'key'=>'value'})
 
@@ -74,6 +82,14 @@ class ActionControllerRequestProxyTest < Test::Unit::TestCase
     assert_equal 'PUT', request_proxy.method
   end
 
+  def test_that_proxy_simple_patch_request_works_with_post_params
+    request_proxy = request_proxy(:patch, {}, {'key'=>'value'})
+
+    expected_parameters = []
+    assert_equal expected_parameters, request_proxy.parameters_for_signature
+    assert_equal 'PATCH', request_proxy.method
+  end
+
   def test_that_proxy_simple_get_request_works_with_mixed_params
     request_proxy = request_proxy(:get, {'key'=>'value'}, {'key2'=>'value2'})
 
@@ -98,6 +114,14 @@ class ActionControllerRequestProxyTest < Test::Unit::TestCase
     assert_equal 'PUT', request_proxy.method
   end
 
+  def test_that_proxy_simple_patch_request_works_with_mixed_params
+    request_proxy = request_proxy(:patch, {'key'=>'value'}, {'key2'=>'value2'})
+
+    expected_parameters = [["key", "value"]]
+    assert_equal expected_parameters, request_proxy.parameters_for_signature
+    assert_equal 'PATCH', request_proxy.method
+  end
+
   def test_parameter_keys_should_preserve_brackets_from_hash
     assert_equal(
       [["message[body]", "This is a test"]],
diff --git a/test/units/test_cli.rb b/test/units/test_cli.rb
new file mode 100644
index 0000000..170c7bc
--- /dev/null
+++ b/test/units/test_cli.rb
@@ -0,0 +1,304 @@
+require File.expand_path('../../test_helper', __FILE__)
+
+require 'oauth/cli'
+
+class TestCLI < Minitest::Test
+
+  def test_parse
+    assert_equal 'version', parse('-v')
+    assert_equal 'version', parse('--version')
+
+    assert_equal 'help', parse('-h')
+    assert_equal 'help', parse('--help')
+    assert_equal 'help', parse('-H')
+    assert_equal 'help', parse('--HELP')
+
+    assert_equal 'help', parse('')
+    assert_equal 'help', parse(nil)
+
+    assert_equal 'help', parse('NotACommand')
+
+    assert_equal 'help'      , parse('h')
+    assert_equal 'version'   , parse('v')
+    assert_equal 'query'     , parse('q')
+    assert_equal 'authorize' , parse('a')
+    assert_equal 'sign'      , parse('s')
+
+    assert_equal 'help'      , parse('help')
+    assert_equal 'version'   , parse('version')
+    assert_equal 'query'     , parse('query')
+    assert_equal 'authorize' , parse('authorize')
+    assert_equal 'sign'      , parse('sign')
+
+    assert_equal 'help'      , parse('H')
+    assert_equal 'version'   , parse('V')
+    assert_equal 'query'     , parse('Q')
+    assert_equal 'authorize' , parse('A')
+    assert_equal 'sign'      , parse('S')
+
+    assert_equal 'help'      , parse('HELP')
+    assert_equal 'version'   , parse('VERSION')
+    assert_equal 'query'     , parse('QUERY')
+    assert_equal 'authorize' , parse('AUTHORIZE')
+    assert_equal 'sign'      , parse('SIGN')
+  end
+
+  def test_help_empty
+    out = run_command
+
+    assert_match(/Usage: /, out)
+  end
+
+  def test_help
+    out = run_command(%w[help])
+
+    assert_match(/Usage: /, out)
+  end
+
+  def test_version
+    out = run_command(%w[version])
+
+    assert_equal "OAuth Gem #{OAuth::VERSION}\n", out
+  end
+
+  def test_query_empty
+    out = run_command(%w[query])
+
+    assert_equal help_output, out
+  end
+
+  def test_sign_empty
+    out = run_command(%w[sign])
+
+    assert_equal help_output, out
+  end
+
+  def test_authorize_empty
+    out = run_command(%w[authorize])
+
+    assert_equal help_output, out
+  end
+
+  def test_query
+    consumer     = Minitest::Mock.new
+    access_token = MiniTest::Mock.new
+    response     = MiniTest::Mock.new
+
+    consumer_new = lambda { |oauth_consumer_key, oauth_consumer_secret, options|
+      expected_options = {:scheme=>:header}
+      assert_equal 'oauth_consumer_key', oauth_consumer_key
+      assert_equal 'oauth_consumer_secret', oauth_consumer_secret
+      assert_equal expected_options, options
+      consumer
+    }
+    access_token_new = lambda { |consumer1, token, secret|
+      assert_equal consumer1.object_id, consumer.object_id
+      assert_equal 'TOKEN', token
+      assert_equal 'SECRET', secret
+      access_token
+    }
+
+    # mock expects:
+    #                    method      return    arguments
+    #-------------------------------------------------------------
+    response.expect(    :code    , '!code!')
+    response.expect(    :message , '!message!')
+    response.expect(    :body    , '!body!')
+    access_token.expect(:request , response     , [:post, "http://example.com/oauth/url?oauth_consumer_key=oauth_consumer_key&oauth_nonce=GENERATE_KEY&oauth_timestamp=GENERATE_TIMESTAMP&oauth_token=TOKEN&oauth_signature_method=HMAC-SHA1&oauth_version=1.0"])
+
+    OAuth::Helper.stub(:generate_key, 'GENERATE_KEY') do
+      OAuth::Helper.stub(:generate_timestamp, 'GENERATE_TIMESTAMP') do
+        OAuth::AccessToken.stub(:new, access_token_new) do
+          OAuth::Consumer.stub(:new, consumer_new) do
+            out = run_command %w[query
+              --consumer-key oauth_consumer_key
+              --consumer-secret oauth_consumer_secret
+              --token TOKEN
+              --secret SECRET
+              --uri http://example.com/oauth/url
+            ]
+
+            assert_equal out, <<-EXPECTED
+http://example.com/oauth/url?oauth_consumer_key=oauth_consumer_key&oauth_nonce=GENERATE_KEY&oauth_timestamp=GENERATE_TIMESTAMP&oauth_token=TOKEN&oauth_signature_method=HMAC-SHA1&oauth_version=1.0
+!code! !message!
+!body!
+EXPECTED
+          end
+        end
+      end
+    end
+  end
+
+  def test_authorize
+    access_token  = MiniTest::Mock.new
+    consumer      = MiniTest::Mock.new
+    request_token = MiniTest::Mock.new
+
+    consumer_new = lambda { |oauth_consumer_key, oauth_consumer_secret, options|
+      expected_options = {:access_token_url=>nil, :authorize_url=>nil, :request_token_url=>nil, :scheme=>:header, :http_method=>:get}
+      assert_equal 'oauth_consumer_key', oauth_consumer_key
+      assert_equal 'oauth_consumer_secret', oauth_consumer_secret
+      assert_equal expected_options, options
+      consumer
+    }
+
+    # mock expects:
+    #                      method                return           arguments
+    #----------------------------------------------------------------------
+    access_token.expect(  :params              , {})
+    consumer.expect(      :get_request_token   , request_token , [{:oauth_callback=>nil} , {}])
+    request_token.expect( :callback_confirmed? , false)
+    request_token.expect( :authorize_url       , "!url1!")
+    request_token.expect( :get_access_token    , access_token,   [{:oauth_verifier=>nil}])
+
+    OAuth::Helper.stub(:generate_key, 'GENERATE_KEY') do
+      OAuth::Helper.stub(:generate_timestamp, 'GENERATE_TIMESTAMP') do
+        OAuth::Consumer.stub(:new, consumer_new) do
+
+          out = run_command %w[authorize
+            --consumer-key oauth_consumer_key
+            --consumer-secret oauth_consumer_secret
+            --method GET
+            --uri http://example.com/oauth/url
+            ]
+
+          assert_equal out, <<-EXPECTED
+Please visit this url to authorize:
+!url1!
+Press return to continue...
+Response:
+EXPECTED
+        end
+      end
+    end
+  end
+
+  def test_sign
+    access_token  = MiniTest::Mock.new
+    consumer      = MiniTest::Mock.new
+    request_token = MiniTest::Mock.new
+
+    consumer_new = lambda { |oauth_consumer_key, oauth_consumer_secret, options|
+      expected_options = {:access_token_url=>nil, :authorize_url=>nil, :request_token_url=>nil, :scheme=>:header, :http_method=>:get}
+      assert_equal 'oauth_consumer_key', oauth_consumer_key
+      assert_equal 'oauth_consumer_secret', oauth_consumer_secret
+      assert_equal expected_options, options
+      consumer
+    }
+
+    # mock expects:
+    #                      method                return           arguments
+    #----------------------------------------------------------------------
+    access_token.expect(  :params              , {})
+    consumer.expect(      :get_request_token   , request_token , [{:oauth_callback=>nil} , {}])
+    request_token.expect( :callback_confirmed? , false)
+    request_token.expect( :authorize_url       , "!url1!")
+    request_token.expect( :get_access_token    , access_token,   [{:oauth_verifier=>nil}])
+
+    out = []
+
+    OAuth::Helper.stub(:generate_key, 'GENERATE_KEY') do
+      OAuth::Helper.stub(:generate_timestamp, 'GENERATE_TIMESTAMP') do
+        OAuth::Consumer.stub(:new, consumer_new) do
+
+          out.push run_command %w[sign
+            --consumer-key oauth_consumer_key
+            --consumer-secret oauth_consumer_secret
+            --method GET
+            --token TOKEN
+            --secret SECRET
+            --uri http://example.com/oauth/url
+            -v
+            ]
+
+          out.push run_command %w[sign
+            --consumer-key oauth_consumer_key
+            --consumer-secret oauth_consumer_secret
+            --method GET
+            --token TOKEN
+            --secret SECRET
+            --uri http://example.com/oauth/url
+            ]
+        end
+      end
+    end
+
+    assert_equal out.pop, <<-EXPECTED
+MujZyJYT5ix2s388yF8sExvPIgA=
+EXPECTED
+
+    assert_equal out.pop, <<-EXPECTED
+OAuth parameters:
+  oauth_consumer_key: oauth_consumer_key
+  oauth_nonce: GENERATE_KEY
+  oauth_timestamp: GENERATE_TIMESTAMP
+  oauth_token: TOKEN
+  oauth_signature_method: HMAC-SHA1
+  oauth_version: 1.0
+
+Method: GET
+URI: http://example.com/oauth/url
+Normalized params: oauth_consumer_key=oauth_consumer_key&oauth_nonce=GENERATE_KEY&oauth_signature_method=HMAC-SHA1&oauth_timestamp=GENERATE_TIMESTAMP&oauth_token=TOKEN&oauth_version=1.0
+Signature base string: GET&http%3A%2F%2Fexample.com%2Foauth%2Furl&oauth_consumer_key%3Doauth_consumer_key%26oauth_nonce%3DGENERATE_KEY%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3DGENERATE_TIMESTAMP%26oauth_token%3DTOKEN%26oauth_version%3D1.0
+OAuth Request URI: http://example.com/oauth/url?oauth_consumer_key=oauth_consumer_key&oauth_nonce=GENERATE_KEY&oauth_signature=MujZyJYT5ix2s388yF8sExvPIgA%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=GENERATE_TIMESTAMP&oauth_token=TOKEN&oauth_version=1.0
+Request URI: http://example.com/oauth/url?
+Authorization header: OAuth oauth_consumer_key=\"oauth_consumer_key\", oauth_nonce=\"GENERATE_KEY\", oauth_timestamp=\"GENERATE_TIMESTAMP\", oauth_token=\"TOKEN\", oauth_signature_method=\"HMAC-SHA1\", oauth_version=\"1.0\", oauth_signature=\"MujZyJYT5ix2s388yF8sExvPIgA%3D\"
+Signature:         MujZyJYT5ix2s388yF8sExvPIgA=
+Escaped signature: MujZyJYT5ix2s388yF8sExvPIgA%3D
+EXPECTED
+
+  end
+
+
+
+
+  private
+
+  def run_command(arguments=[])
+    s = StringIO.new
+    command = arguments.shift
+    OAuth::CLI.new(s, StringIO.new, StringIO.new, command, arguments).run
+
+    s.rewind
+    s.read
+  end
+
+  def parse(command)
+    cli = OAuth::CLI.new(StringIO.new, StringIO.new, StringIO.new, command, [])
+    cli.send(:parse_command, command)
+  end
+
+  def help_output
+    <<-EXPECTED
+Usage: oauth <command> [ARGS]
+    -B, --body                       Use the request body for OAuth parameters.
+        --consumer-key KEY           Specifies the consumer key to use.
+        --consumer-secret SECRET     Specifies the consumer secret to use.
+    -H, --header                     Use the 'Authorization' header for OAuth parameters (default).
+    -Q, --query-string               Use the query string for OAuth parameters.
+    -O, --options FILE               Read options from a file
+
+  options for signing and querying
+        --method METHOD              Specifies the method (e.g. GET) to use when signing.
+        --nonce NONCE                Specifies the none to use.
+        --parameters PARAMS          Specifies the parameters to use when signing.
+        --signature-method METHOD    Specifies the signature method to use; defaults to HMAC-SHA1.
+        --token TOKEN                Specifies the token to use.
+        --secret SECRET              Specifies the token secret to use.
+        --timestamp TIMESTAMP        Specifies the timestamp to use.
+        --realm REALM                Specifies the realm to use.
+        --uri URI                    Specifies the URI to use when signing.
+        --version [VERSION]          Specifies the OAuth version to use.
+        --no-version                 Omit oauth_version.
+        --xmpp                       Generate XMPP stanzas.
+    -v, --verbose                    Be verbose.
+
+  options for authorization
+        --access-token-url URL       Specifies the access token URL.
+        --authorize-url URL          Specifies the authorization URL.
+        --callback-url URL           Specifies a callback URL.
+        --request-token-url URL      Specifies the request token URL.
+        --scope SCOPE                Specifies the scope (Google-specific).
+EXPECTED
+  end
+end
diff --git a/test/test_consumer.rb b/test/units/test_consumer.rb
similarity index 83%
rename from test/test_consumer.rb
rename to test/units/test_consumer.rb
index 136aeea..af97bd1 100644
--- a/test/test_consumer.rb
+++ b/test/units/test_consumer.rb
@@ -1,12 +1,9 @@
-require File.expand_path('../test_helper', __FILE__)
-require 'mocha'
-
-require 'stringio'
+require File.expand_path('../../test_helper', __FILE__)
 
 # This performs testing against Andy Smith's test server http://term.ie/oauth/example/
 # Thanks Andy.
 # This also means you have to be online to be able to run these.
-class ConsumerTest < Test::Unit::TestCase
+class ConsumerTest < Minitest::Test
   def setup
     @consumer=OAuth::Consumer.new(
         'consumer_key_86cad9', '5888bf0345e5d237',
@@ -39,9 +36,10 @@ class ConsumerTest < Test::Unit::TestCase
     assert_equal "http://blabla.bla/oauth/example/authorize.php", at consumer.authorize_url
     assert_equal :header, at consumer.scheme
     assert_equal :get, at consumer.http_method
+    assert_nil   @consumer.debug_output
   end
 
-   def test_defaults
+  def test_defaults
     @consumer=OAuth::Consumer.new(
       "key",
       "secret",
@@ -59,6 +57,28 @@ class ConsumerTest < Test::Unit::TestCase
     assert_equal "http://twitter.com/oauth/authorize", at consumer.authorize_url
     assert_equal :header, at consumer.scheme
     assert_equal :post, at consumer.http_method
+    assert_nil   @consumer.debug_output
+  end
+
+  def test_debug_output_true
+    @consumer=OAuth::Consumer.new(
+      "key",
+      "secret",
+      {
+          :debug_output=>true
+      })
+    assert_equal $stdout, at consumer.debug_output
+  end
+
+  def test_debug_output
+    stringio = StringIO.new
+    @consumer=OAuth::Consumer.new(
+      "key",
+      "secret",
+      {
+          :debug_output=>stringio
+      })
+    assert_equal stringio, at consumer.debug_output
   end
 
   def test_site_without_path
@@ -69,7 +89,7 @@ class ConsumerTest < Test::Unit::TestCase
           :site=>"http://twitter.com"
       })
     request = stub(:oauth! => nil)
-    http = stub(:request => stub(:to_hash => {}))
+    http = stub(:request => stub(:to_hash => {}), :address => "identi.ca")
     Net::HTTP::Get.expects(:new).with('/people', {}).returns(request)
     @consumer.expects(:create_http).returns(http)
     @consumer.request(:get, '/people', nil, {})
@@ -83,7 +103,7 @@ class ConsumerTest < Test::Unit::TestCase
           :site=>"http://identi.ca/api"
       })
     request = stub(:oauth! => nil)
-    http = stub(:request => stub(:to_hash => {}))
+    http = stub(:request => stub(:to_hash => {}), :address => "identi.ca")
     Net::HTTP::Get.expects(:new).with('/api/people', {}).returns(request)
     @consumer.expects(:create_http).returns(http)
     @consumer.request(:get, '/people', nil, {})
@@ -132,7 +152,27 @@ class ConsumerTest < Test::Unit::TestCase
     assert_equal :post, at consumer.http_method
   end
 
- def test_that_token_response_should_be_uri_parameter_format_as_default
+  def test_getting_tokens_doesnt_add_paths_if_full_url_is_specified
+   @consumer = OAuth::Consumer.new(
+     "key",
+     "secret",
+     {
+         :site              => "https://api.mysite.co.nz/v1",
+         :request_token_url => "https://authentication.mysite.co.nz/Oauth/RequestToken"
+     })
+
+   stub_request(:post, "https://authentication.mysite.co.nz/Oauth/RequestToken").to_return(:body => "success", :status => 200)
+   @consumer.get_request_token
+  end
+
+  def test_token_request_identifies_itself_as_a_token_request
+    request_options = {}
+    @consumer.stubs(:request).returns(create_stub_http_response)
+    @consumer.token_request(:post, '/', 'token', request_options) {}
+    assert_equal true, request_options[:token_request]
+  end
+
+  def test_that_token_response_should_be_uri_parameter_format_as_default
     @consumer.expects(:request).returns(create_stub_http_response("oauth_token=token&oauth_token_secret=secret"))
 
     hash = @consumer.token_request(:get, "")
diff --git a/test/test_curb_request_proxy.rb b/test/units/test_curb_request_proxy.rb
similarity index 96%
rename from test/test_curb_request_proxy.rb
rename to test/units/test_curb_request_proxy.rb
index 8abf245..4f34b77 100644
--- a/test/test_curb_request_proxy.rb
+++ b/test/units/test_curb_request_proxy.rb
@@ -1,4 +1,4 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 
 begin
 
@@ -6,7 +6,7 @@ require 'oauth/request_proxy/curb_request'
 require 'curb'
 
 
-class CurbRequestProxyTest < Test::Unit::TestCase
+class CurbRequestProxyTest < Minitest::Test
 
   def test_that_proxy_simple_get_request_works
     request = Curl::Easy.new('/test?key=value')
diff --git a/test/test_em_http_client.rb b/test/units/test_em_http_client.rb
similarity index 97%
rename from test/test_em_http_client.rb
rename to test/units/test_em_http_client.rb
index 603fd8b..4d99ad9 100644
--- a/test/test_em_http_client.rb
+++ b/test/units/test_em_http_client.rb
@@ -1,9 +1,9 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 begin
 
 require 'oauth/client/em_http'
 
-class EmHttpClientTest < Test::Unit::TestCase
+class EmHttpClientTest < Minitest::Test
 
   def setup
     @consumer = OAuth::Consumer.new('consumer_key_86cad9', '5888bf0345e5d237')
diff --git a/test/test_em_http_request_proxy.rb b/test/units/test_em_http_request_proxy.rb
similarity index 98%
rename from test/test_em_http_request_proxy.rb
rename to test/units/test_em_http_request_proxy.rb
index 6bcab2d..959ddff 100644
--- a/test/test_em_http_request_proxy.rb
+++ b/test/units/test_em_http_request_proxy.rb
@@ -1,4 +1,4 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 
 begin
 
@@ -6,7 +6,7 @@ require 'em-http'
 require 'oauth/request_proxy/em_http_request'
 
 
-class EmHttpRequestProxyTest < Test::Unit::TestCase
+class EmHttpRequestProxyTest < Minitest::Test
 
   def test_request_proxy_works_with_simple_request
     proxy = create_request_proxy
diff --git a/test/test_hmac_sha1.rb b/test/units/test_hmac_sha1.rb
similarity index 89%
rename from test/test_hmac_sha1.rb
rename to test/units/test_hmac_sha1.rb
index ef0360b..e71904b 100644
--- a/test/test_hmac_sha1.rb
+++ b/test/units/test_hmac_sha1.rb
@@ -1,6 +1,6 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 
-class TestSignatureHmacSha1 < Test::Unit::TestCase
+class TestSignatureHmacSha1 < Minitest::Test
   def test_that_hmac_sha1_implements_hmac_sha1
     assert OAuth::Signature.available_methods.include?('hmac-sha1')
   end
diff --git a/test/test_net_http_client.rb b/test/units/test_net_http_client.rb
similarity index 93%
rename from test/test_net_http_client.rb
rename to test/units/test_net_http_client.rb
index 3ceacf1..aa32792 100644
--- a/test/test_net_http_client.rb
+++ b/test/units/test_net_http_client.rb
@@ -1,6 +1,6 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 
-class NetHTTPClientTest < Test::Unit::TestCase
+class NetHTTPClientTest < Minitest::Test
 
   def setup
     @consumer = OAuth::Consumer.new('consumer_key_86cad9', '5888bf0345e5d237')
@@ -19,7 +19,7 @@ class NetHTTPClientTest < Test::Unit::TestCase
     assert_equal 'GET', request.method
     assert_equal '/test?key=value', request.path
     correct_sorted_params = "oauth_nonce=\"225579211881198842005988698334675835446\", oauth_signature_method=\"HMAC-SHA1\", oauth_token=\"token_411a7f\", oauth_timestamp=\"1199645624\", oauth_consumer_key=\"consumer_key_86cad9\", oauth_signature=\"1oO2izFav1GP4kEH2EskwXkCRFg%3D\", oauth_version=\"1.0\""
-    auth_intro, auth_params = request['authorization'].split(' ', 2)
+    auth_intro = request['authorization'].split(' ', 2).first
     assert_equal auth_intro, 'OAuth'
     assert_matching_headers correct_sorted_params, request['authorization']
   end
@@ -62,6 +62,12 @@ class NetHTTPClientTest < Test::Unit::TestCase
     assert_matching_headers "oauth_nonce=\"225579211881198842005988698334675835446\", oauth_body_hash=\"oXyaqmHoChv3HQ2FCvTluqmAC70%3D\", oauth_signature_method=\"HMAC-SHA1\", oauth_token=\"token_411a7f\", oauth_timestamp=\"1199645624\", oauth_consumer_key=\"consumer_key_86cad9\", oauth_signature=\"0DA6pGTapdHSqC15RZelY5rNLDw%3D\", oauth_version=\"1.0\"", request['authorization']
   end
 
+  def test_that_body_hash_is_obmitted_when_token_request
+    request = Net::HTTP::Post.new(@request_uri.path)
+    request.oauth!(@http, @consumer, @token, {:nonce => @nonce, :timestamp => @timestamp, :token_request => true})
+    assert_no_match(/oauth_body_hash/, request['authorization'])
+  end
+
   def test_that_body_hash_is_obmitted_when_no_algorithm_is_defined
     request = Net::HTTP::Post.new(@request_uri.path)
     request.body = "data"
@@ -99,9 +105,9 @@ class NetHTTPClientTest < Test::Unit::TestCase
     assert_equal 'GET', request.method
     uri = URI.parse(request.path)
     assert_equal '/test', uri.path
-    assert_equal nil, uri.fragment
+    assert_nil uri.fragment
     assert_equal "key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=1oO2izFav1GP4kEH2EskwXkCRFg%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0", uri.query.split("&").sort.join("&")
-    assert_equal nil, request['authorization']
+    assert_nil request['authorization']
   end
 
   def test_that_using_get_params_works_with_plaintext
@@ -111,9 +117,9 @@ class NetHTTPClientTest < Test::Unit::TestCase
     assert_equal 'GET', request.method
     uri = URI.parse(request.path)
     assert_equal '/test', uri.path
-    assert_equal nil, uri.fragment
+    assert_nil uri.fragment
     assert_equal "key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=5888bf0345e5d237%263196ffd991c8ebdb&oauth_signature_method=PLAINTEXT&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0", uri.query.split("&").sort.join("&")
-    assert_equal nil, request['authorization']
+    assert_nil request['authorization']
   end
 
   def test_that_using_post_params_works
@@ -123,8 +129,8 @@ class NetHTTPClientTest < Test::Unit::TestCase
 
     assert_equal 'POST', request.method
     assert_equal '/test', request.path
-    assert_match /key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=26g7wHTtNO6ZWJaLltcueppHYiI%3[Dd]&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0/, request.body.split("&").sort.join("&")
-    assert_equal nil, request['authorization']
+    assert_match(/key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=26g7wHTtNO6ZWJaLltcueppHYiI%3[Dd]&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0/, request.body.split("&").sort.join("&"))
+    assert_nil request['authorization']
   end
 
   def test_that_using_post_params_works_with_plaintext
@@ -135,7 +141,7 @@ class NetHTTPClientTest < Test::Unit::TestCase
     assert_equal 'POST', request.method
     assert_equal '/test', request.path
     assert_equal "key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=5888bf0345e5d237%263196ffd991c8ebdb&oauth_signature_method=PLAINTEXT&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0", request.body.split("&").sort.join("&")
-    assert_equal nil, request['authorization']
+    assert_nil request['authorization']
   end
 
   def test_that_using_post_body_works
@@ -146,8 +152,8 @@ class NetHTTPClientTest < Test::Unit::TestCase
 
     assert_equal 'POST', request.method
     assert_equal '/test', request.path
-    assert_match /OAuth oauth_consumer_key="consumer_key_86cad9", oauth_nonce="225579211881198842005988698334675835446", oauth_signature="%2[fF]DMMBOJzQ6JmEaXlAXDLGtD1z2I%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1199645624", oauth_token="token_411a7f", oauth_version="1.0"/, request['authorization'].split("&").sort.join("&")
-    # assert_equal nil, request['authorization']
+    assert_match(/OAuth oauth_consumer_key="consumer_key_86cad9", oauth_nonce="225579211881198842005988698334675835446", oauth_signature="%2[fF]DMMBOJzQ6JmEaXlAXDLGtD1z2I%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1199645624", oauth_token="token_411a7f", oauth_version="1.0"/, request['authorization'].split("&").sort.join("&"))
+    # assert_nil request['authorization']
   end
 
   def test_that_using_post_with_uri_params_works
@@ -158,10 +164,10 @@ class NetHTTPClientTest < Test::Unit::TestCase
     assert_equal 'POST', request.method
     uri = URI.parse(request.path)
     assert_equal '/test', uri.path
-    assert_equal nil, uri.fragment
+    assert_nil uri.fragment
     assert_equal "key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=26g7wHTtNO6ZWJaLltcueppHYiI%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0", uri.query.split("&").sort.join('&')
     assert_equal "", request.body
-    assert_equal nil, request['authorization']
+    assert_nil request['authorization']
   end
 
   def test_that_using_post_with_uri_and_form_params_works
@@ -172,10 +178,10 @@ class NetHTTPClientTest < Test::Unit::TestCase
     assert_equal 'POST', request.method
     uri = URI.parse(request.path)
     assert_equal '/test', uri.path
-    assert_equal nil, uri.fragment
+    assert_nil uri.fragment
     assert_equal "key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=4kSU8Zd1blWo3W6qJH7eaRTMkg0%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0", uri.query.split("&").sort.join('&')
     assert_equal "key2=value2", request.body
-    assert_equal nil, request['authorization']
+    assert_nil request['authorization']
   end
 
   def test_that_using_post_with_uri_and_data_works
@@ -187,11 +193,11 @@ class NetHTTPClientTest < Test::Unit::TestCase
     assert_equal 'POST', request.method
     uri = URI.parse(request.path)
     assert_equal '/test', uri.path
-    assert_equal nil, uri.fragment
+    assert_nil uri.fragment
     assert_equal "data", request.body
     assert_equal 'text/ascii', request.content_type
     assert_equal "key=value&oauth_body_hash=oXyaqmHoChv3HQ2FCvTluqmAC70%3D&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=MHRKU42iVHU4Ke9kBUDa9Zw6IAM%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0", uri.query.split("&").sort.join('&')
-    assert_equal nil, request['authorization']
+    assert_nil request['authorization']
   end
 
 
@@ -285,6 +291,10 @@ class NetHTTPClientTest < Test::Unit::TestCase
 
   protected
 
+  def assert_no_match exp, act, msg = "Expected #{act.inspect} to not match #{exp.inspect}"
+    assert act !~ exp, msg
+  end
+
     def request_parameters_to_s
       @request_parameters.map { |k,v| "#{k}=#{v}" }.join("&")
     end
diff --git a/test/test_net_http_request_proxy.rb b/test/units/test_net_http_request_proxy.rb
similarity index 96%
rename from test/test_net_http_request_proxy.rb
rename to test/units/test_net_http_request_proxy.rb
index ac2a327..76e07e1 100644
--- a/test/test_net_http_request_proxy.rb
+++ b/test/units/test_net_http_request_proxy.rb
@@ -1,6 +1,6 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 
-class NetHTTPRequestProxyTest < Test::Unit::TestCase
+class NetHTTPRequestProxyTest < Minitest::Test
 
   def test_that_proxy_simple_get_request_works
     request = Net::HTTP::Get.new('/test?key=value')
diff --git a/test/test_oauth_helper.rb b/test/units/test_oauth_helper.rb
similarity index 95%
rename from test/test_oauth_helper.rb
rename to test/units/test_oauth_helper.rb
index a489ca2..0ad1342 100644
--- a/test/test_oauth_helper.rb
+++ b/test/units/test_oauth_helper.rb
@@ -1,6 +1,6 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 
-class TestOAuthHelper < Test::Unit::TestCase
+class TestOAuthHelper < Minitest::Test
 
   def test_parse_valid_header
     header = 'OAuth ' \
@@ -27,7 +27,7 @@ class TestOAuthHelper < Test::Unit::TestCase
   def test_parse_header_ill_formed
     header = "OAuth garbage"
 
-    assert_raise OAuth::Problem do
+    assert_raises OAuth::Problem do
       OAuth::Helper.parse_header(header)
     end
   end
@@ -42,7 +42,7 @@ class TestOAuthHelper < Test::Unit::TestCase
              'oauth_timestamp="1240004133", oauth_nonce="nonce", ' \
              'oauth_version="1.0" '
 
-    assert_raise OAuth::Problem do
+    assert_raises OAuth::Problem do
       OAuth::Helper.parse_header(header)
     end
   end
@@ -68,7 +68,7 @@ class TestOAuthHelper < Test::Unit::TestCase
     assert_equal "nonce", params['oauth_nonce']
     assert_equal "1.0", params['oauth_version']
   end
-  
+
   def test_normalize
     params = {
       'oauth_nonce' => 'nonce',
@@ -81,7 +81,7 @@ class TestOAuthHelper < Test::Unit::TestCase
     }
     assert_equal("oauth_consumer_key=vince_clortho&oauth_nonce=nonce&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1240004133&oauth_token=token_value&oauth_version=1.0&weight%5Bvalue%5D=65", OAuth::Helper.normalize(params))
   end
-  
+
   def test_normalize_nested_query
     assert_equal([], OAuth::Helper.normalize_nested_query({}))
     assert_equal(["foo=bar"], OAuth::Helper.normalize_nested_query({:foo => 'bar'}))
diff --git a/test/test_rack_request_proxy.rb b/test/units/test_rack_request_proxy.rb
similarity index 91%
rename from test/test_rack_request_proxy.rb
rename to test/units/test_rack_request_proxy.rb
index 8b22afc..99a3aa6 100644
--- a/test/test_rack_request_proxy.rb
+++ b/test/units/test_rack_request_proxy.rb
@@ -1,9 +1,8 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
+
 require 'oauth/request_proxy/rack_request'
-require 'rack/request'
-require 'rack/mock'
 
-class RackRequestProxyTest < Test::Unit::TestCase
+class RackRequestProxyTest < Minitest::Test
 
   def test_that_proxy_simple_get_request_works
     request = Rack::Request.new(Rack::MockRequest.env_for('http://example.com/test?key=value'))
diff --git a/test/test_request_token.rb b/test/units/test_request_token.rb
similarity index 83%
rename from test/test_request_token.rb
rename to test/units/test_request_token.rb
index 632e927..db52a2f 100644
--- a/test/test_request_token.rb
+++ b/test/units/test_request_token.rb
@@ -1,4 +1,4 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 
 class StubbedToken < OAuth::RequestToken
   define_method :build_authorize_url_promoted do |root_domain, params|
@@ -6,7 +6,7 @@ class StubbedToken < OAuth::RequestToken
   end
 end
 
-class TestRequestToken < Test::Unit::TestCase
+class TestRequestToken < Minitest::Test
   def setup
     # setup a fake req. token. mocking Consumer would be more appropriate...
     @request_token = OAuth::RequestToken.new(
@@ -18,7 +18,7 @@ class TestRequestToken < Test::Unit::TestCase
 
   def test_request_token_builds_authorize_url_connectly_with_additional_params
     auth_url = @request_token.authorize_url({:oauth_callback => "github.com"})
-    assert_not_nil auth_url
+    assert auth_url
     assert_match(/oauth_token/, auth_url)
     assert_match(/oauth_callback/, auth_url)
   end
@@ -27,14 +27,19 @@ class TestRequestToken < Test::Unit::TestCase
     # we should only have 1 key in the url returned if we didn't pass anything.
     # this is the only required param to authenticate the client.
     auth_url = @request_token.authorize_url(nil)
-    assert_not_nil auth_url
+    assert auth_url
     assert_match(/\?oauth_token=/, auth_url)
 
     auth_url = @request_token.authorize_url
-    assert_not_nil auth_url
+    assert auth_url
     assert_match(/\?oauth_token=/, auth_url)
   end
 
+  def test_request_token_returns_nil_authorize_url_when_token_is_nil
+    @request_token.token = nil
+    assert_nil @request_token.authorize_url
+  end
+
   #TODO: mock out the Consumer to test the Consumer/AccessToken interaction.
   def test_get_access_token
   end
diff --git a/test/units/test_rest_client_request_proxy.rb b/test/units/test_rest_client_request_proxy.rb
new file mode 100644
index 0000000..45115ba
--- /dev/null
+++ b/test/units/test_rest_client_request_proxy.rb
@@ -0,0 +1,81 @@
+require File.expand_path('../../test_helper', __FILE__)
+
+begin
+  require 'oauth/request_proxy/rest_client_request'
+  require 'rest-client'
+
+  class RestlClientRequestProxyTest < Minitest::Test
+
+    def test_that_proxy_simple_get_request_works
+      request = ::RestClient::Request.new(method: :get, url: "http://example.com/test?key=value")
+      request_proxy = OAuth::RequestProxy.proxy(request, {:uri => 'http://example.com/test?key=value'})
+
+      expected_parameters = {'key' => ['value']}
+      assert_equal expected_parameters, request_proxy.parameters_for_signature
+      assert_equal 'http://example.com/test', request_proxy.normalized_uri
+      assert_equal 'GET', request_proxy.method
+    end
+
+    def test_that_proxy_simple_post_request_works_with_arguments
+      request = ::RestClient::Request.new(method: :post, url: "http://example.com/test")
+      params = {'key' => 'value'}
+      request_proxy = OAuth::RequestProxy.proxy(request, {:uri => 'http://example.com/test', :parameters => params})
+
+      expected_parameters = {'key' => 'value'}
+      assert_equal expected_parameters, request_proxy.parameters_for_signature
+      assert_equal 'http://example.com/test', request_proxy.normalized_uri
+      assert_equal 'POST', request_proxy.method
+    end
+
+    def test_that_proxy_simple_post_request_works_with_form_data
+      request = ::RestClient::Request.new(method: :post, url: "http://example.com/test",
+        payload: {'key' => 'value'},
+        headers: {'Content-Type' => 'application/x-www-form-urlencoded'})
+      request_proxy = OAuth::RequestProxy.proxy(request, {:uri => 'http://example.com/test'})
+
+      expected_parameters = {'key' => 'value'}
+      assert_equal expected_parameters, request_proxy.parameters_for_signature
+      assert_equal 'http://example.com/test', request_proxy.normalized_uri
+      assert_equal 'POST', request_proxy.method
+    end
+
+    def test_that_proxy_simple_put_request_works_with_arguments
+      request = ::RestClient::Request.new(method: :put, url: "http://example.com/test")
+      params = {'key' => 'value'}
+      request_proxy = OAuth::RequestProxy.proxy(request, {:uri => 'http://example.com/test', :parameters => params})
+
+      expected_parameters = {'key' => 'value'}
+      assert_equal expected_parameters, request_proxy.parameters_for_signature
+      assert_equal 'http://example.com/test', request_proxy.normalized_uri
+      assert_equal 'PUT', request_proxy.method
+    end
+
+    def test_that_proxy_simple_put_request_works_with_form_data
+      request = ::RestClient::Request.new(method: :put, url: "http://example.com/test",
+        payload: {'key' => 'value'},
+        headers: {'Content-Type' => 'application/x-www-form-urlencoded'})
+      request_proxy = OAuth::RequestProxy.proxy(request, {:uri => 'http://example.com/test'})
+
+      expected_parameters = {'key' => 'value'}
+      assert_equal expected_parameters, request_proxy.parameters_for_signature
+      assert_equal 'http://example.com/test', request_proxy.normalized_uri
+      assert_equal 'PUT', request_proxy.method
+    end
+
+    def test_that_proxy_post_request_works_with_mixed_parameter_sources
+      request = ::RestClient::Request.new(url: 'http://example.com/test?key=value',
+        method: :post,
+        payload: {'key2' => 'value2'},
+        headers: {'Content-Type' => 'application/x-www-form-urlencoded'})
+      request_proxy = OAuth::RequestProxy.proxy(request, {:uri => 'http://example.com/test?key=value', :parameters => {'key3' => 'value3'}})
+
+      expected_parameters = {'key' => ['value'], 'key2' => 'value2', 'key3' => 'value3'}
+      assert_equal expected_parameters, request_proxy.parameters_for_signature
+      assert_equal 'http://example.com/test', request_proxy.normalized_uri
+      assert_equal 'POST', request_proxy.method
+    end
+
+  end
+rescue LoadError => e
+    warn "! problem loading rest-client, skipping these tests: #{e}"
+end
diff --git a/test/test_rsa_sha1.rb b/test/units/test_rsa_sha1.rb
similarity index 56%
rename from test/test_rsa_sha1.rb
rename to test/units/test_rsa_sha1.rb
index f057869..dc4483d 100644
--- a/test/test_rsa_sha1.rb
+++ b/test/units/test_rsa_sha1.rb
@@ -1,14 +1,14 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
+
 require 'oauth/consumer'
 require 'oauth/signature/rsa/sha1'
 
-class TestSignatureRsaSha1 < Test::Unit::TestCase
+class TestSignatureRsaSha1 < Minitest::Test
 
   def setup
-    @request = Net::HTTP::Get.new('/photos?file=vacaction.jpg&size=original&oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_timestamp=1196666512&oauth_nonce=13917289812797014437&oauth_signature_method=RSA-SHA1')
-
-    @consumer = OAuth::Consumer.new('dpf43f3p2l4k3l03', OpenSSL::PKey::RSA.new(IO.read(File.dirname(__FILE__) + "/keys/rsa.pem")))
+    @request = Net::HTTP::Get.new("/photos?file=vacaction.jpg&size=original&oauth_version=1.0&oauth_consumer_key=#{consumer_key}&oauth_timestamp=1196666512&oauth_nonce=13917289812797014437&oauth_signature_method=RSA-SHA1")
 
+    @consumer = OAuth::Consumer.new(consumer_key, pkey_rsa)
   end
 
   def test_that_rsa_sha1_implements_rsa_sha1
@@ -27,22 +27,21 @@ class TestSignatureRsaSha1 < Test::Unit::TestCase
                                                  :uri => 'http://photos.example.net/photos' } )
 
     assert_equal 'jvTp/wX1TYtByB1m+Pbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2/9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW//e+RinhejgCuzoH26dyF8iY2ZZ/5D1ilgeijhV/vBka5twt399mXwaYdCwFYE=', signature
-
   end
 
   def test_that_get_request_from_oauth_test_cases_produces_matching_signature_using_private_key_file
-    @consumer = OAuth::Consumer.new('dpf43f3p2l4k3l03',nil)
+    @consumer = OAuth::Consumer.new(consumer_key,nil)
 
     signature = OAuth::Signature.sign(@request, { :consumer => @consumer,
-                                                  :private_key_file=>File.dirname(__FILE__) + "/keys/rsa.pem",
+                                                  :private_key_file=>pem_path,
                                                  :uri => 'http://photos.example.net/photos' } )
 
     assert_equal 'jvTp/wX1TYtByB1m+Pbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2/9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW//e+RinhejgCuzoH26dyF8iY2ZZ/5D1ilgeijhV/vBka5twt399mXwaYdCwFYE=', signature
   end
 
   def test_that_get_request_from_oauth_test_cases_verifies_signature
-    @request = Net::HTTP::Get.new('/photos?oauth_signature_method=RSA-SHA1&oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_timestamp=1196666512&oauth_nonce=13917289812797014437&file=vacaction.jpg&size=original&oauth_signature=jvTp%2FwX1TYtByB1m%2BPbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2%2F9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW%2F%2Fe%2BRinhejgCuzoH26dyF8iY2ZZ%2F5D1ilgeijhV%2FvBka5twt399mXwaYdCwFYE%3D')
-    @consumer = OAuth::Consumer.new('dpf43f3p2l4k3l03',OpenSSL::X509::Certificate.new(IO.read(File.dirname(__FILE__) + "/keys/rsa.cert")))
+    @request = Net::HTTP::Get.new("/photos?oauth_signature_method=RSA-SHA1&oauth_version=1.0&oauth_consumer_key=#{consumer_key}&oauth_timestamp=1196666512&oauth_nonce=13917289812797014437&file=vacaction.jpg&size=original&oauth_signature=jvTp%2FwX1TYtByB1m%2BPbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2%2F9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW%2F%2Fe%2BRinhejgCuzoH26dyF8iY2ZZ%2F5D1ilgeijhV%2FvBka5twt399mXwaYdCwFYE%3D")
+    @consumer = OAuth::Consumer.new(consumer_key, x509_certificate)
 
     assert OAuth::Signature.verify(@request, { :consumer => @consumer,
                                                  :uri => 'http://photos.example.net/photos' } )
@@ -50,10 +49,31 @@ class TestSignatureRsaSha1 < Test::Unit::TestCase
   end
 
   def test_that_get_request_from_oauth_test_cases_verifies_signature_with_pem
-    @request = Net::HTTP::Get.new('/photos?oauth_signature_method=RSA-SHA1&oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_timestamp=1196666512&oauth_nonce=13917289812797014437&file=vacaction.jpg&size=original&oauth_signature=jvTp%2FwX1TYtByB1m%2BPbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2%2F9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW%2F%2Fe%2BRinhejgCuzoH26dyF8iY2ZZ%2F5D1ilgeijhV%2FvBka5twt399mXwaYdCwFYE%3D')
+    @request = Net::HTTP::Get.new("/photos?oauth_signature_method=RSA-SHA1&oauth_version=1.0&oauth_consumer_key=#{consumer_key}&oauth_timestamp=1196666512&oauth_nonce=13917289812797014437&file=vacaction.jpg&size=original&oauth_signature=jvTp%2FwX1TYtByB1m%2BPbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2%2F9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW%2F%2Fe%2BRinhejgCuzoH26dyF8iY2ZZ%2F5D1ilgeijhV%2FvBka5twt399mXwaYdCwFYE%3D")
     assert OAuth::Signature.verify(@request, { :consumer => @consumer,
                                                  :uri => 'http://photos.example.net/photos' } )
+  end
+
+  private
+
+  def consumer_key
+    'dpf43f3p2l4k3l03'
+  end
+
+  def x509_certificate
+    OpenSSL::X509::Certificate.new(IO.read(cert_path))
+  end
+
+  def pkey_rsa
+    OpenSSL::PKey::RSA.new(IO.read(pem_path))
+  end
+
+  def cert_path
+    File.dirname(__FILE__) + "/../keys/rsa.cert"
+  end
 
+  def pem_path
+    File.dirname(__FILE__) + "/../keys/rsa.pem"
   end
 
 end
diff --git a/test/test_server.rb b/test/units/test_server.rb
similarity index 82%
rename from test/test_server.rb
rename to test/units/test_server.rb
index 15947c7..7af2816 100644
--- a/test/test_server.rb
+++ b/test/units/test_server.rb
@@ -1,6 +1,8 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
+
 require 'oauth/server'
-class ServerTest < Test::Unit::TestCase
+
+class ServerTest < Minitest::Test
   def setup
     @server=OAuth::Server.new "http://test.com"
   end
@@ -19,15 +21,15 @@ class ServerTest < Test::Unit::TestCase
 
   def test_generate_consumer_credentials
     consumer=@server.generate_consumer_credentials
-    assert_not_nil consumer.key
-    assert_not_nil consumer.secret
+    assert consumer.key
+    assert consumer.secret
   end
 
   def test_create_consumer
     @consumer=@server.create_consumer
-    assert_not_nil @consumer
-    assert_not_nil @consumer.key
-    assert_not_nil @consumer.secret
+    assert @consumer
+    assert @consumer.key
+    assert @consumer.secret
     assert_equal "http://test.com", at consumer.site
     assert_equal "/oauth/request_token", at consumer.request_token_path
     assert_equal "/oauth/authorize", at consumer.authorize_path
diff --git a/test/units/test_signature.rb b/test/units/test_signature.rb
new file mode 100644
index 0000000..c1a3235
--- /dev/null
+++ b/test/units/test_signature.rb
@@ -0,0 +1,15 @@
+# -*- encoding: utf-8 -*-
+
+require File.expand_path('../../test_helper', __FILE__)
+
+class TestOauth < Minitest::Test
+
+  def test_parameter_escaping_kcode_invariant
+    %w(n N e E s S u U).each do |kcode|
+      assert_equal '%E3%81%82', OAuth::Helper.escape('あ'),
+                    "Failed to correctly escape Japanese under $KCODE = #{kcode}"
+      assert_equal '%C3%A9', OAuth::Helper.escape('é'),
+                    "Failed to correctly escape e+acute under $KCODE = #{kcode}"
+    end
+  end
+end
diff --git a/test/test_signature_base.rb b/test/units/test_signature_base.rb
similarity index 74%
rename from test/test_signature_base.rb
rename to test/units/test_signature_base.rb
index c31f606..cbfb732 100644
--- a/test/test_signature_base.rb
+++ b/test/units/test_signature_base.rb
@@ -1,7 +1,9 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
+
 require 'oauth/signature/base'
 require 'net/http'
-class SignatureBaseTest < Test::Unit::TestCase
+
+class SignatureBaseTest < Minitest::Test
 
   def test_that_initialize_requires_one_request_argument
     assert_raises ArgumentError do
@@ -22,11 +24,10 @@ class SignatureBaseTest < Test::Unit::TestCase
     # this isn't quite valid, but it will do.
     raw_request = Net::HTTP::Get.new('/test')
     request = OAuth::RequestProxy.proxy(raw_request)
-    assert_nothing_raised do
-      OAuth::Signature::Base.new(request) { |token|
-        # just a stub
-      }
-    end
+
+    OAuth::Signature::Base.new(request) { |token|
+      # just a stub
+    }
   end
 
 end
diff --git a/test/units/test_signature_hmac_sha1.rb b/test/units/test_signature_hmac_sha1.rb
new file mode 100644
index 0000000..a9c3766
--- /dev/null
+++ b/test/units/test_signature_hmac_sha1.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../test_helper', __FILE__)
+
+require 'oauth/signature/hmac/sha1'
+
+class SignatureHMACSHA1Test < Minitest::Test
+  def test_that_verify_returns_true_when_the_request_signature_is_right
+    request = OAuth::RequestProxy::MockRequest.new(
+      'method' => 'POST',
+      'uri' => 'https://photos.example.net/initialize',
+      'parameters' => {
+        'oauth_consumer_key' => 'dpf43f3p2l4k3l03',
+        'oauth_signature_method' => 'HMAC-SHA1',
+        'oauth_timestamp' => '137131200',
+        'oauth_nonce' => 'wIjqoS',
+        'oauth_callback' => 'http://printer.example.com/ready',
+        'oauth_version' => '1.0',
+        'oauth_signature' => 'xcHYBV3AbyoDz7L4dV10P3oLCjY='
+      }
+    )
+    assert OAuth::Signature::HMAC::SHA1.new(request, :consumer_secret => 'kd94hf93k423kf44').verify
+  end
+
+  def test_that_verify_returns_false_when_the_request_signature_is_wrong
+    # Test a bug in the OAuth::Signature::Base#== method: when the Base64.decode64 method is
+    # used on the "self" and "other" signature (as in version 0.4.7), the result may be incorrectly "true".
+    request = OAuth::RequestProxy::MockRequest.new(
+      'method' => 'POST',
+      'uri' => 'https://photos.example.net/initialize',
+      'parameters' => {
+        'oauth_consumer_key' => 'dpf43f3p2l4k3l03',
+        'oauth_signature_method' => 'HMAC-SHA1',
+        'oauth_timestamp' => '137131200',
+        'oauth_nonce' => 'wIjqoS',
+        'oauth_callback' => 'http://printer.example.com/ready',
+        'oauth_version' => '1.0',
+        'oauth_signature' => 'xcHYBV3AbyoDz7L4dV10P3oLCjZ='
+      }
+    )
+    assert !OAuth::Signature::HMAC::SHA1.new(request, :consumer_secret => 'kd94hf93k423kf44').verify
+  end
+end
diff --git a/test/test_signature_plain_text.rb b/test/units/test_signature_plain_text.rb
similarity index 94%
rename from test/test_signature_plain_text.rb
rename to test/units/test_signature_plain_text.rb
index eb644b1..37db853 100644
--- a/test/test_signature_plain_text.rb
+++ b/test/units/test_signature_plain_text.rb
@@ -1,7 +1,8 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
+
 require 'oauth/signature/plaintext'
 
-class TestSignaturePlaintext < Test::Unit::TestCase
+class TestSignaturePlaintext < Minitest::Test
   def test_that_plaintext_implements_plaintext
     assert OAuth::Signature.available_methods.include?('plaintext')
   end
diff --git a/test/test_token.rb b/test/units/test_token.rb
similarity index 70%
rename from test/test_token.rb
rename to test/units/test_token.rb
index d4f9a82..d373f77 100644
--- a/test/test_token.rb
+++ b/test/units/test_token.rb
@@ -1,7 +1,8 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
+
 require 'oauth/token'
 
-class TestToken < Test::Unit::TestCase
+class TestToken < Minitest::Test
 
   def setup
   end
diff --git a/test/test_typhoeus_request_proxy.rb b/test/units/test_typhoeus_request_proxy.rb
similarity index 73%
rename from test/test_typhoeus_request_proxy.rb
rename to test/units/test_typhoeus_request_proxy.rb
index 9c11857..3cf4ae3 100644
--- a/test/test_typhoeus_request_proxy.rb
+++ b/test/units/test_typhoeus_request_proxy.rb
@@ -1,11 +1,11 @@
-require File.expand_path('../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
 
 begin
 
 require 'oauth/request_proxy/typhoeus_request'
 require 'typhoeus'
 
-class TyphoeusRequestProxyTest < Test::Unit::TestCase
+class TyphoeusRequestProxyTest < Minitest::Test
 
   def test_that_proxy_simple_get_request_works
     request = ::Typhoeus::Request.new('/test?key=value')
@@ -34,7 +34,7 @@ class TyphoeusRequestProxyTest < Test::Unit::TestCase
       :headers => {'Content-Type' => 'application/x-www-form-urlencoded'})
     request_proxy = OAuth::RequestProxy.proxy(request, {:uri => 'http://example.com/test'})
 
-    expected_parameters = {'key' => 'value'}
+    expected_parameters = {'key' => ['value']}
     assert_equal expected_parameters, request_proxy.parameters_for_signature
     assert_equal 'http://example.com/test', request_proxy.normalized_uri
     assert_equal 'POST', request_proxy.method
@@ -61,6 +61,27 @@ class TyphoeusRequestProxyTest < Test::Unit::TestCase
     assert_equal 'PUT', request_proxy.method
   end
 
+  def test_that_proxy_simple_patch_request_works_with_arguments
+    request = Typhoeus::Request.new('/test', :method => :patch)
+    params = {'key' => 'value'}
+    request_proxy = OAuth::RequestProxy.proxy(request, {:uri => 'http://example.com/test', :parameters => params})
+
+    expected_parameters = {'key' => 'value'}
+    assert_equal expected_parameters, request_proxy.parameters_for_signature
+    assert_equal 'http://example.com/test', request_proxy.normalized_uri
+    assert_equal 'PATCH', request_proxy.method
+  end
+
+  def test_that_proxy_simple_patch_request_works_with_form_data
+    request = Typhoeus::Request.new('/test', :method => :patch, :params => {'key' => 'value'})
+    request_proxy = OAuth::RequestProxy.proxy(request, {:uri => 'http://example.com/test'})
+
+    expected_parameters = {'key' => ['value']}
+    assert_equal expected_parameters, request_proxy.parameters_for_signature
+    assert_equal 'http://example.com/test', request_proxy.normalized_uri
+    assert_equal 'PATCH', request_proxy.method
+  end
+
   def test_that_proxy_post_request_works_with_mixed_parameter_sources
     request = Typhoeus::Request.new('/test?key=value',
       :method => :post,
@@ -68,7 +89,7 @@ class TyphoeusRequestProxyTest < Test::Unit::TestCase
       :headers => {'Content-Type' => 'application/x-www-form-urlencoded'})
     request_proxy = OAuth::RequestProxy.proxy(request, {:uri => 'http://example.com/test?key=value', :parameters => {'key3' => 'value3'}})
 
-    expected_parameters = {'key' => ['value'], 'key2' => 'value2', 'key3' => 'value3'}
+    expected_parameters = {'key' => ['value'], 'key2' => ['value2'], 'key3' => 'value3'}
     assert_equal expected_parameters, request_proxy.parameters_for_signature
     assert_equal 'http://example.com/test', request_proxy.normalized_uri
     assert_equal 'POST', request_proxy.method

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-oauth.git



More information about the Pkg-ruby-extras-commits mailing list