-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use (relaxed) ISO8601 durations and add more tests
- Loading branch information
Showing
7 changed files
with
202 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# frozen_string_literal: true | ||
|
||
module KubernetesDeploy | ||
## | ||
# This class is a less strict extension of ActiveSupport::Duration::ISO8601Parser. | ||
# In addition to full ISO8601 durations, it can parse unprefixed ISO8601 time components (e.g. '1H'). | ||
# It is also case-insensitive. | ||
# For example, this class considers the values "1H", "1h" and "PT1H" to be valid and equivalent. | ||
|
||
class DurationParser | ||
class ParsingError < ArgumentError; end | ||
|
||
def initialize(value) | ||
@iso8601_str = value.to_s.strip.upcase | ||
end | ||
|
||
def parse! | ||
if @iso8601_str.blank? | ||
raise ParsingError, "Cannot parse blank value" | ||
end | ||
|
||
parser = ActiveSupport::Duration::ISO8601Parser.new(@iso8601_str) | ||
parser.mode = :time unless @iso8601_str.start_with?("P") | ||
parts = parser.parse! | ||
ActiveSupport::Duration.new(calculate_total_seconds(parts), parts) | ||
rescue ActiveSupport::Duration::ISO8601Parser::ParsingError => e | ||
raise ParsingError, e.message | ||
end | ||
|
||
private | ||
|
||
# https://github.com/rails/rails/blob/19c450d5d99275924254b2041b6ad470fdaa1f93/activesupport/lib/active_support/duration.rb#L79-L83 | ||
def calculate_total_seconds(parts) | ||
parts.inject(0) do |total, (part, value)| | ||
total + value * ActiveSupport::Duration::PARTS_IN_SECONDS[part] | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# frozen_string_literal: true | ||
require 'test_helper' | ||
|
||
class DurationParserTest < KubernetesDeploy::TestCase | ||
def test_parses_correct_iso_durations_with_prefixes | ||
assert_equal 300, new_parser("PT300S").parse! | ||
assert_equal 300, new_parser("PT5M").parse! | ||
assert_equal 900, new_parser("PT0.25H").parse! | ||
assert_equal 110839937, new_parser("P3Y6M4DT12H30M5S").parse! | ||
end | ||
|
||
def test_parses_correct_iso_durations_without_prefixes | ||
assert_equal 300, new_parser("300S").parse! | ||
assert_equal 300, new_parser("5M").parse! | ||
assert_equal 900, new_parser("0.25H").parse! | ||
assert_equal(-60, new_parser("-1M").parse!) | ||
end | ||
|
||
def test_parse_is_case_insensitive | ||
assert_equal 30, new_parser("30S").parse! | ||
assert_equal 30, new_parser("30s").parse! | ||
end | ||
|
||
def test_parse_raises_expected_error_for_blank_values | ||
["", " ", nil].each do |blank_value| | ||
assert_raises_message(KubernetesDeploy::DurationParser::ParsingError, "Cannot parse blank value") do | ||
new_parser(blank_value).parse! | ||
end | ||
end | ||
end | ||
|
||
def test_extra_whitespace_is_stripped_from_values | ||
assert_equal 30, new_parser(" 30S ").parse! | ||
end | ||
|
||
def test_parse_raises_expected_error_when_value_is_invalid | ||
assert_raises_message(KubernetesDeploy::DurationParser::ParsingError, 'Invalid ISO 8601 duration: "FOO"') do | ||
new_parser("foo").parse! | ||
end | ||
end | ||
|
||
private | ||
|
||
def new_parser(value) | ||
KubernetesDeploy::DurationParser.new(value) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters