puppet 4.7.1-universal-darwin → 4.8.0-universal-darwin
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/Gemfile +0 -3
- data/MAINTAINERS +76 -0
- data/README.md +0 -6
- data/Rakefile +2 -2
- data/lib/puppet/agent.rb +3 -3
- data/lib/puppet/application/apply.rb +1 -1
- data/lib/puppet/configurer.rb +2 -2
- data/lib/puppet/data_providers.rb +1 -0
- data/lib/puppet/data_providers/data_adapter.rb +1 -0
- data/lib/puppet/data_providers/data_function_support.rb +1 -0
- data/lib/puppet/data_providers/function_env_data_provider.rb +1 -0
- data/lib/puppet/data_providers/function_module_data_provider.rb +1 -0
- data/lib/puppet/data_providers/hiera_config.rb +1 -0
- data/lib/puppet/data_providers/hiera_env_data_provider.rb +1 -0
- data/lib/puppet/data_providers/hiera_interpolate.rb +1 -0
- data/lib/puppet/data_providers/hiera_module_data_provider.rb +1 -0
- data/lib/puppet/data_providers/hiera_support.rb +1 -2
- data/lib/puppet/data_providers/json_data_provider_factory.rb +2 -0
- data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -0
- data/lib/puppet/defaults.rb +20 -1
- data/lib/puppet/environments.rb +5 -2
- data/lib/puppet/face/catalog.rb +1 -1
- data/lib/puppet/face/epp.rb +57 -11
- data/lib/puppet/face/module/install.rb +6 -6
- data/lib/puppet/functions.rb +23 -24
- data/lib/puppet/functions/alert.rb +14 -0
- data/lib/puppet/functions/binary_file.rb +25 -0
- data/lib/puppet/functions/break.rb +22 -0
- data/lib/puppet/functions/contain.rb +33 -0
- data/lib/puppet/functions/crit.rb +14 -0
- data/lib/puppet/functions/debug.rb +14 -0
- data/lib/puppet/functions/emerg.rb +14 -0
- data/lib/puppet/functions/epp.rb +1 -1
- data/lib/puppet/functions/err.rb +14 -0
- data/lib/puppet/functions/find_file.rb +31 -0
- data/lib/puppet/functions/include.rb +21 -0
- data/lib/puppet/functions/info.rb +14 -0
- data/lib/puppet/functions/new.rb +1 -1
- data/lib/puppet/functions/next.rb +23 -0
- data/lib/puppet/functions/notice.rb +14 -0
- data/lib/puppet/functions/regsubst.rb +12 -16
- data/lib/puppet/functions/require.rb +37 -0
- data/lib/puppet/functions/return.rb +22 -0
- data/lib/puppet/functions/strftime.rb +35 -0
- data/lib/puppet/functions/warning.rb +14 -0
- data/lib/puppet/generate/models/type/type.rb +4 -0
- data/lib/puppet/generate/templates/type/pcore.erb +2 -1
- data/lib/puppet/indirector/face.rb +6 -1
- data/lib/puppet/network/http/error.rb +2 -2
- data/lib/puppet/network/http/handler.rb +2 -2
- data/lib/puppet/node/environment.rb +11 -0
- data/lib/puppet/parser/ast.rb +5 -0
- data/lib/puppet/parser/ast/pops_bridge.rb +17 -4
- data/lib/puppet/parser/compiler.rb +29 -1
- data/lib/puppet/parser/functions.rb +6 -0
- data/lib/puppet/parser/functions/assert_type.rb +1 -1
- data/lib/puppet/parser/functions/binary_file.rb +24 -0
- data/lib/puppet/parser/functions/break.rb +39 -0
- data/lib/puppet/parser/functions/contain.rb +7 -15
- data/lib/puppet/parser/functions/defined.rb +2 -2
- data/lib/puppet/parser/functions/dig.rb +1 -1
- data/lib/puppet/parser/functions/each.rb +1 -1
- data/lib/puppet/parser/functions/epp.rb +2 -2
- data/lib/puppet/parser/functions/filter.rb +1 -1
- data/lib/puppet/parser/functions/find_file.rb +28 -0
- data/lib/puppet/parser/functions/hiera.rb +4 -4
- data/lib/puppet/parser/functions/hiera_array.rb +1 -1
- data/lib/puppet/parser/functions/hiera_hash.rb +1 -1
- data/lib/puppet/parser/functions/hiera_include.rb +1 -1
- data/lib/puppet/parser/functions/include.rb +4 -8
- data/lib/puppet/parser/functions/inline_epp.rb +1 -1
- data/lib/puppet/parser/functions/lest.rb +1 -1
- data/lib/puppet/parser/functions/lookup.rb +4 -2
- data/lib/puppet/parser/functions/map.rb +1 -1
- data/lib/puppet/parser/functions/match.rb +1 -1
- data/lib/puppet/parser/functions/new.rb +414 -18
- data/lib/puppet/parser/functions/next.rb +38 -0
- data/lib/puppet/parser/functions/reduce.rb +1 -1
- data/lib/puppet/parser/functions/regsubst.rb +4 -2
- data/lib/puppet/parser/functions/require.rb +4 -27
- data/lib/puppet/parser/functions/return.rb +71 -0
- data/lib/puppet/parser/functions/reverse_each.rb +1 -1
- data/lib/puppet/parser/functions/scanf.rb +13 -8
- data/lib/puppet/parser/functions/slice.rb +1 -1
- data/lib/puppet/parser/functions/split.rb +1 -1
- data/lib/puppet/parser/functions/step.rb +1 -1
- data/lib/puppet/parser/functions/strftime.rb +185 -0
- data/lib/puppet/parser/functions/then.rb +1 -1
- data/lib/puppet/parser/functions/type.rb +1 -1
- data/lib/puppet/parser/functions/with.rb +3 -3
- data/lib/puppet/parser/resource.rb +8 -5
- data/lib/puppet/parser/scope.rb +1 -1
- data/lib/puppet/plugins/configuration.rb +8 -0
- data/lib/puppet/plugins/data_providers.rb +1 -0
- data/lib/puppet/plugins/data_providers/data_provider.rb +7 -28
- data/lib/puppet/plugins/data_providers/registry.rb +1 -0
- data/lib/puppet/pops.rb +4 -0
- data/lib/puppet/pops/evaluator/access_operator.rb +36 -5
- data/lib/puppet/pops/evaluator/closure.rb +81 -12
- data/lib/puppet/pops/evaluator/compare_operator.rb +24 -1
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +29 -5
- data/lib/puppet/pops/evaluator/json_strict_literal_evaluator.rb +1 -1
- data/lib/puppet/pops/evaluator/runtime3_converter.rb +53 -62
- data/lib/puppet/pops/evaluator/runtime3_support.rb +15 -6
- data/lib/puppet/pops/functions/dispatch.rb +9 -2
- data/lib/puppet/pops/functions/dispatcher.rb +3 -1
- data/lib/puppet/pops/functions/function.rb +19 -2
- data/lib/puppet/pops/issues.rb +9 -0
- data/lib/puppet/pops/label_provider.rb +2 -2
- data/lib/puppet/pops/loader/loader.rb +17 -0
- data/lib/puppet/pops/loader/static_loader.rb +0 -41
- data/lib/puppet/pops/lookup.rb +12 -0
- data/lib/puppet/pops/lookup/context.rb +86 -0
- data/lib/puppet/pops/lookup/explainer.rb +46 -6
- data/lib/puppet/pops/lookup/invocation.rb +19 -0
- data/lib/puppet/pops/lookup/sub_lookup.rb +1 -1
- data/lib/puppet/pops/model/factory.rb +20 -8
- data/lib/puppet/pops/model/model_label_provider.rb +3 -0
- data/lib/puppet/pops/model/model_meta.rb +2 -0
- data/lib/puppet/pops/model/model_tree_dumper.rb +14 -0
- data/lib/puppet/pops/parser/egrammar.ra +11 -6
- data/lib/puppet/pops/parser/eparser.rb +1112 -1086
- data/lib/puppet/pops/parser/heredoc_support.rb +1 -2
- data/lib/puppet/pops/pcore.rb +1 -0
- data/lib/puppet/pops/puppet_stack.rb +3 -3
- data/lib/puppet/pops/resource/param.rb +5 -1
- data/lib/puppet/pops/resource/resource_type_impl.rb +8 -4
- data/lib/puppet/pops/resource/resource_type_set.pcore +1 -0
- data/lib/puppet/pops/serialization/abstract_reader.rb +19 -2
- data/lib/puppet/pops/serialization/abstract_writer.rb +16 -3
- data/lib/puppet/pops/serialization/deserializer.rb +5 -1
- data/lib/puppet/pops/serialization/extension.rb +2 -0
- data/lib/puppet/pops/serialization/json.rb +76 -26
- data/lib/puppet/pops/serialization/serializer.rb +5 -1
- data/lib/puppet/pops/serialization/time_factory.rb +2 -1
- data/lib/puppet/pops/time/timespan.rb +718 -0
- data/lib/puppet/pops/time/timestamp.rb +148 -0
- data/lib/puppet/pops/types/p_binary_type.rb +220 -0
- data/lib/puppet/pops/types/p_object_type.rb +12 -6
- data/lib/puppet/pops/types/p_sensitive_type.rb +5 -1
- data/lib/puppet/pops/types/p_timespan_type.rb +141 -0
- data/lib/puppet/pops/types/p_timestamp_type.rb +69 -0
- data/lib/puppet/pops/types/string_converter.rb +62 -0
- data/lib/puppet/pops/types/type_asserter.rb +1 -1
- data/lib/puppet/pops/types/type_calculator.rb +17 -3
- data/lib/puppet/pops/types/type_factory.rb +35 -1
- data/lib/puppet/pops/types/type_formatter.rb +64 -11
- data/lib/puppet/pops/types/type_mismatch_describer.rb +110 -61
- data/lib/puppet/pops/types/type_parser.rb +18 -4
- data/lib/puppet/pops/types/types.rb +98 -63
- data/lib/puppet/pops/validation.rb +9 -1
- data/lib/puppet/pops/validation/checker4_0.rb +7 -0
- data/lib/puppet/property.rb +1 -1
- data/lib/puppet/provider.rb +3 -6
- data/lib/puppet/provider/mcx/mcxcontent.rb +1 -1
- data/lib/puppet/provider/mount/parsed.rb +18 -4
- data/lib/puppet/provider/nameservice/directoryservice.rb +15 -7
- data/lib/puppet/provider/package/gem.rb +6 -1
- data/lib/puppet/provider/package/pip.rb +0 -1
- data/lib/puppet/provider/package/pkg.rb +5 -1
- data/lib/puppet/provider/package/pkgng.rb +1 -1
- data/lib/puppet/provider/package/yum.rb +10 -0
- data/lib/puppet/provider/service/launchd.rb +1 -0
- data/lib/puppet/provider/user/directoryservice.rb +6 -6
- data/lib/puppet/provider/yumrepo/inifile.rb +1 -1
- data/lib/puppet/provider/zpool/zpool.rb +1 -1
- data/lib/puppet/resource.rb +54 -12
- data/lib/puppet/resource/capability_finder.rb +15 -9
- data/lib/puppet/resource/catalog.rb +25 -6
- data/lib/puppet/resource/type.rb +3 -1
- data/lib/puppet/settings.rb +1 -1
- data/lib/puppet/settings/environment_conf.rb +12 -4
- data/lib/puppet/syntax_checkers/base64.rb +41 -0
- data/lib/puppet/syntax_checkers/json.rb +0 -2
- data/lib/puppet/transaction.rb +6 -0
- data/lib/puppet/transaction/additional_resource_generator.rb +5 -0
- data/lib/puppet/transaction/report.rb +7 -2
- data/lib/puppet/type.rb +2 -1
- data/lib/puppet/type/file/checksum.rb +1 -0
- data/lib/puppet/type/file/content.rb +4 -4
- data/lib/puppet/type/mount.rb +44 -0
- data/lib/puppet/type/ssh_authorized_key.rb +1 -1
- data/lib/puppet/type/tidy.rb +3 -0
- data/lib/puppet/type/user.rb +12 -6
- data/lib/puppet/util/log.rb +25 -0
- data/lib/puppet/util/plist.rb +8 -3
- data/lib/puppet/version.rb +1 -1
- data/lib/puppet_x.rb +7 -1
- data/spec/integration/application/apply_spec.rb +118 -0
- data/spec/integration/parser/compiler_spec.rb +28 -0
- data/spec/integration/parser/pcore_resource_spec.rb +40 -3
- data/spec/integration/provider/mount_spec.rb +2 -1
- data/spec/integration/util/windows/principal_spec.rb +2 -2
- data/spec/integration/util/windows/registry_spec.rb +4 -4
- data/spec/lib/puppet_spec/compiler.rb +5 -1
- data/spec/lib/puppet_spec/unindent.rb +5 -0
- data/spec/shared_contexts/types_setup.rb +6 -0
- data/spec/shared_examples/rhel_package_provider.rb +16 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/agent_spec.rb +11 -0
- data/spec/unit/application/lookup_spec.rb +94 -3
- data/spec/unit/capability_spec.rb +22 -0
- data/spec/unit/configurer_spec.rb +8 -0
- data/spec/unit/face/epp_face_spec.rb +22 -3
- data/spec/unit/functions/assert_type_spec.rb +3 -3
- data/spec/unit/functions/binary_file_spec.rb +46 -0
- data/spec/unit/functions/break_spec.rb +89 -0
- data/spec/unit/{parser/functions → functions}/contain_spec.rb +68 -3
- data/spec/unit/functions/find_file_spec.rb +69 -0
- data/spec/unit/functions/include_spec.rb +175 -0
- data/spec/unit/functions/logging_spec.rb +54 -0
- data/spec/unit/functions/lookup_spec.rb +3 -3
- data/spec/unit/functions/new_spec.rb +105 -5
- data/spec/unit/functions/next_spec.rb +93 -0
- data/spec/unit/functions/require_spec.rb +83 -0
- data/spec/unit/functions/return_spec.rb +105 -0
- data/spec/unit/{parser/functions → functions}/shared.rb +14 -11
- data/spec/unit/functions/strftime_spec.rb +152 -0
- data/spec/unit/functions4_spec.rb +22 -0
- data/spec/unit/indirector/face_spec.rb +10 -2
- data/spec/unit/network/http/error_spec.rb +1 -2
- data/spec/unit/network/http/handler_spec.rb +6 -5
- data/spec/unit/parser/functions/hiera_array_spec.rb +1 -1
- data/spec/unit/parser/functions/hiera_hash_spec.rb +1 -1
- data/spec/unit/parser/functions/hiera_include_spec.rb +1 -1
- data/spec/unit/parser/functions/hiera_spec.rb +1 -1
- data/spec/unit/parser/functions/lookup_spec.rb +1 -1
- data/spec/unit/parser/functions/regsubst_spec.rb +1 -1
- data/spec/unit/parser/functions/split_spec.rb +1 -1
- data/spec/unit/pops/evaluator/access_ops_spec.rb +81 -1
- data/spec/unit/pops/evaluator/arithmetic_ops_spec.rb +170 -0
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +29 -4
- data/spec/unit/pops/evaluator/runtime3_converter_spec.rb +112 -4
- data/spec/unit/pops/loaders/dependency_loader_spec.rb +12 -0
- data/spec/unit/pops/loaders/static_loader_spec.rb +0 -26
- data/spec/unit/pops/lookup/context_spec.rb +149 -0
- data/spec/unit/pops/parser/parse_functions_spec.rb +19 -0
- data/spec/unit/pops/parser/parse_lambda_spec.rb +19 -0
- data/spec/unit/pops/puppet_stack_spec.rb +1 -1
- data/spec/unit/pops/resource/resource_type_impl_spec.rb +74 -0
- data/spec/unit/pops/serialization/packer_spec.rb +34 -14
- data/spec/unit/pops/serialization/serialization_spec.rb +67 -5
- data/spec/unit/pops/time/timespan_spec.rb +121 -0
- data/spec/unit/pops/types/p_binary_type_spec.rb +243 -0
- data/spec/unit/pops/types/p_object_type_spec.rb +7 -7
- data/spec/unit/pops/types/p_sensitive_type_spec.rb +1 -1
- data/spec/unit/pops/types/p_timespan_type_spec.rb +273 -0
- data/spec/unit/pops/types/p_timestamp_type_spec.rb +311 -0
- data/spec/unit/pops/types/p_type_set_type_spec.rb +13 -13
- data/spec/unit/pops/types/ruby_generator_spec.rb +12 -12
- data/spec/unit/pops/types/string_converter_spec.rb +89 -0
- data/spec/unit/pops/types/type_asserter_spec.rb +3 -3
- data/spec/unit/pops/types/type_calculator_spec.rb +113 -5
- data/spec/unit/pops/types/type_formatter_spec.rb +40 -0
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +49 -38
- data/spec/unit/pops/types/type_parser_spec.rb +87 -4
- data/spec/unit/pops/types/types_spec.rb +1 -1
- data/spec/unit/pops/validator/validator_spec.rb +23 -0
- data/spec/unit/provider/mount/parsed_spec.rb +47 -29
- data/spec/unit/provider/package/pkg_spec.rb +109 -99
- data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +1 -0
- data/spec/unit/provider/user/aix_spec.rb +1 -1
- data/spec/unit/provider/user/directoryservice_spec.rb +101 -30
- data/spec/unit/resource/capability_finder_spec.rb +29 -7
- data/spec/unit/resource/catalog_spec.rb +127 -0
- data/spec/unit/ssl/certificate_request_spec.rb +1 -1
- data/spec/unit/transaction/additional_resource_generator_spec.rb +30 -0
- data/spec/unit/transaction/persistence_spec.rb +1 -6
- data/spec/unit/transaction/report_spec.rb +23 -0
- data/spec/unit/transaction_spec.rb +38 -0
- data/spec/unit/type/mount_spec.rb +5 -0
- data/spec/unit/util/plist_spec.rb +14 -2
- metadata +71 -12
- data/spec/integration/parser/functions/require_spec.rb +0 -43
- data/spec/unit/parser/functions/include_spec.rb +0 -55
- data/spec/unit/parser/functions/require_spec.rb +0 -68
@@ -0,0 +1,243 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'puppet/pops'
|
3
|
+
require 'puppet_spec/compiler'
|
4
|
+
|
5
|
+
module Puppet::Pops
|
6
|
+
module Types
|
7
|
+
describe 'Binary Type' do
|
8
|
+
include PuppetSpec::Compiler
|
9
|
+
|
10
|
+
context 'as a type' do
|
11
|
+
it 'can be created with the type factory' do
|
12
|
+
t = TypeFactory.binary()
|
13
|
+
expect(t).to be_a(PBinaryType)
|
14
|
+
expect(t).to eql(PBinaryType::DEFAULT)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'a Binary instance' do
|
19
|
+
it 'can be created from a raw String using %r, raw string mode' do
|
20
|
+
str = [0xF1].pack("C*")
|
21
|
+
code = <<-CODE
|
22
|
+
$x = Binary($testing, '%r')
|
23
|
+
notice(assert_type(Binary, $x))
|
24
|
+
CODE
|
25
|
+
expect(eval_and_collect_notices(code, Puppet::Node.new('foonode'), { 'testing' => str })).to eql(['8Q=='])
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'can be created from a String using %s, string mode' do
|
29
|
+
# the text 'binar' needs padding with '='
|
30
|
+
code = <<-CODE
|
31
|
+
$x = Binary('binary', '%s')
|
32
|
+
notice(assert_type(Binary, $x))
|
33
|
+
CODE
|
34
|
+
expect(eval_and_collect_notices(code)).to eql(['YmluYXJ5'])
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'format %s errors if encoding is bad in given string when using format %s and a broken UTF-8 string' do
|
38
|
+
str = [0xF1].pack("C*")
|
39
|
+
str.force_encoding('UTF-8')
|
40
|
+
code = <<-CODE
|
41
|
+
$x = Binary($testing, '%s')
|
42
|
+
notice(assert_type(Binary, $x))
|
43
|
+
CODE
|
44
|
+
expect {
|
45
|
+
eval_and_collect_notices(code, Puppet::Node.new('foonode'), { 'testing' => str })
|
46
|
+
}.to raise_error(/.*The given string in encoding 'UTF-8' is invalid\. Cannot create a Binary UTF-8 representation.*/)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'format %s errors if encoding is correct but string cannot be transcoded to UTF-8' do
|
50
|
+
str = [0xF1].pack("C*")
|
51
|
+
code = <<-CODE
|
52
|
+
$x = Binary($testing, '%s')
|
53
|
+
notice(assert_type(Binary, $x))
|
54
|
+
CODE
|
55
|
+
expect {
|
56
|
+
eval_and_collect_notices(code, Puppet::Node.new('foonode'), { 'testing' => str })
|
57
|
+
}.to raise_error(/.*"\\xF1" from ASCII-8BIT to UTF-8.*/)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'can be created from a strict Base64 encoded String using default format' do
|
61
|
+
code = <<-CODE
|
62
|
+
$x = Binary('YmluYXI=')
|
63
|
+
notice(assert_type(Binary, $x))
|
64
|
+
CODE
|
65
|
+
expect(eval_and_collect_notices(code)).to eql(['YmluYXI='])
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'will error creation in strict mode if padding is missing when using default format' do
|
69
|
+
# the text 'binar' needs padding with '=' (missing here to trigger error
|
70
|
+
code = <<-CODE
|
71
|
+
$x = Binary('YmluYXI')
|
72
|
+
notice(assert_type(Binary, $x))
|
73
|
+
CODE
|
74
|
+
expect{ eval_and_collect_notices(code) }.to raise_error(/invalid base64/)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'can be created from a Base64 encoded String using %B, strict mode' do
|
78
|
+
# the text 'binar' needs padding with '='
|
79
|
+
code = <<-CODE
|
80
|
+
$x = Binary('YmluYXI=', '%B')
|
81
|
+
notice(assert_type(Binary, $x))
|
82
|
+
CODE
|
83
|
+
expect(eval_and_collect_notices(code)).to eql(['YmluYXI='])
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'will error creation in strict mode if padding is missing' do
|
87
|
+
# the text 'binar' needs padding with '=' (missing here to trigger error
|
88
|
+
code = <<-CODE
|
89
|
+
$x = Binary('YmluYXI', '%B')
|
90
|
+
notice(assert_type(Binary, $x))
|
91
|
+
CODE
|
92
|
+
expect{ eval_and_collect_notices(code) }.to raise_error(/invalid base64/)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'will not error creation in base mode if padding is missing' do
|
96
|
+
# the text 'binar' needs padding with '=' (missing here to trigger possible error)
|
97
|
+
code = <<-CODE
|
98
|
+
$x = Binary('YmluYXI', '%b')
|
99
|
+
notice(assert_type(Binary, $x))
|
100
|
+
CODE
|
101
|
+
expect(eval_and_collect_notices(code)).to eql(['YmluYXI='])
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'will not error creation in base mode if padding is not required' do
|
105
|
+
# the text 'binary' does not need padding with '='
|
106
|
+
code = <<-CODE
|
107
|
+
$x = Binary('YmluYXJ5', '%b')
|
108
|
+
notice(assert_type(Binary, $x))
|
109
|
+
CODE
|
110
|
+
expect(eval_and_collect_notices(code)).to eql(['YmluYXJ5'])
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'can be compared to another instance for equality' do
|
114
|
+
code = <<-CODE
|
115
|
+
$x = Binary('YmluYXJ5')
|
116
|
+
$y = Binary('YmluYXJ5')
|
117
|
+
notice($x == $y)
|
118
|
+
notice($x != $y)
|
119
|
+
CODE
|
120
|
+
expect(eval_and_collect_notices(code)).to eql(['true', 'false'])
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'can be created from an array of byte values' do
|
124
|
+
# the text 'binar' needs padding with '='
|
125
|
+
code = <<-CODE
|
126
|
+
$x = Binary([251, 239, 255])
|
127
|
+
notice(assert_type(Binary, $x))
|
128
|
+
CODE
|
129
|
+
expect(eval_and_collect_notices(code)).to eql(['++//'])
|
130
|
+
end
|
131
|
+
|
132
|
+
it "can be created from an hash with value and format" do
|
133
|
+
# the text 'binar' needs padding with '='
|
134
|
+
code = <<-CODE
|
135
|
+
$x = Binary({value => '--__', format => '%u'})
|
136
|
+
notice(assert_type(Binary, $x))
|
137
|
+
CODE
|
138
|
+
expect(eval_and_collect_notices(code)).to eql(['++//'])
|
139
|
+
end
|
140
|
+
|
141
|
+
it "can be created from an hash with value and default format" do
|
142
|
+
code = <<-CODE
|
143
|
+
$x = Binary({value => 'YmluYXI='})
|
144
|
+
notice(assert_type(Binary, $x))
|
145
|
+
CODE
|
146
|
+
expect(eval_and_collect_notices(code)).to eql(['YmluYXI='])
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'can be created from a hash with value being an array' do
|
150
|
+
# the text 'binar' needs padding with '='
|
151
|
+
code = <<-CODE
|
152
|
+
$x = Binary({value => [251, 239, 255]})
|
153
|
+
notice(assert_type(Binary, $x))
|
154
|
+
CODE
|
155
|
+
expect(eval_and_collect_notices(code)).to eql(['++//'])
|
156
|
+
end
|
157
|
+
|
158
|
+
it "can be created from an Base64 using URL safe encoding by specifying '%u' format'" do
|
159
|
+
# the text 'binar' needs padding with '='
|
160
|
+
code = <<-CODE
|
161
|
+
$x = Binary('--__', '%u')
|
162
|
+
notice(assert_type(Binary, $x))
|
163
|
+
CODE
|
164
|
+
expect(eval_and_collect_notices(code)).to eql(['++//'])
|
165
|
+
end
|
166
|
+
|
167
|
+
it "when created with URL safe encoding chars in '%b' format, these are skipped" do
|
168
|
+
code = <<-CODE
|
169
|
+
$x = Binary('--__YmluYXJ5', '%b')
|
170
|
+
notice(assert_type(Binary, $x))
|
171
|
+
CODE
|
172
|
+
expect(eval_and_collect_notices(code)).to eql(['YmluYXJ5'])
|
173
|
+
end
|
174
|
+
|
175
|
+
it "will error in strict format if string contains URL safe encoded chars" do
|
176
|
+
code = <<-CODE
|
177
|
+
$x = Binary('--__YmluYXJ5', '%B')
|
178
|
+
notice(assert_type(Binary, $x))
|
179
|
+
CODE
|
180
|
+
expect { eval_and_collect_notices(code) }.to raise_error(/invalid base64/)
|
181
|
+
end
|
182
|
+
|
183
|
+
[ '<',
|
184
|
+
'<=',
|
185
|
+
'>',
|
186
|
+
'>='
|
187
|
+
].each do |op|
|
188
|
+
it "cannot be compared to another instance for magnitude using #{op}" do
|
189
|
+
code = <<-"CODE"
|
190
|
+
$x = Binary('YmluYXJ5')
|
191
|
+
$y = Binary('YmluYXJ5')
|
192
|
+
$x #{op} $y
|
193
|
+
CODE
|
194
|
+
expect { eval_and_collect_notices(code)}.to raise_error(/Comparison of: Binary #{op} Binary, is not possible/)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'can be matched against a Binary in case expression' do
|
199
|
+
code = <<-CODE
|
200
|
+
case Binary('YmluYXJ5') {
|
201
|
+
Binary('YWxpZW4='): {
|
202
|
+
notice('nope')
|
203
|
+
}
|
204
|
+
Binary('YmluYXJ5'): {
|
205
|
+
notice('yay')
|
206
|
+
}
|
207
|
+
default: {
|
208
|
+
notice('nope')
|
209
|
+
}
|
210
|
+
}
|
211
|
+
CODE
|
212
|
+
expect(eval_and_collect_notices(code)).to eql(['yay'])
|
213
|
+
end
|
214
|
+
|
215
|
+
it "can be matched against a Binary subsequence using 'in' expression" do
|
216
|
+
# finding 'one' in 'one two three'
|
217
|
+
code = <<-CODE
|
218
|
+
notice(Binary("b25l") in Binary("b25lIHR3byB0aHJlZQ=="))
|
219
|
+
notice(Binary("c25l") in Binary("b25lIHR3byB0aHJlZQ=="))
|
220
|
+
CODE
|
221
|
+
expect(eval_and_collect_notices(code)).to eql(['true', 'false'])
|
222
|
+
end
|
223
|
+
|
224
|
+
it "can be matched against a byte value using 'in' expression" do
|
225
|
+
# finding 'e' (ascii 101) in 'one two three'
|
226
|
+
code = <<-CODE
|
227
|
+
notice(101 in Binary("b25lIHR3byB0aHJlZQ=="))
|
228
|
+
notice(101.0 in Binary("b25lIHR3byB0aHJlZQ=="))
|
229
|
+
notice(102 in Binary("b25lIHR3byB0aHJlZQ=="))
|
230
|
+
CODE
|
231
|
+
expect(eval_and_collect_notices(code)).to eql(['true', 'true', 'false'])
|
232
|
+
end
|
233
|
+
|
234
|
+
it "has a length method in ruby returning the length measured in bytes" do
|
235
|
+
# \u{1f452} is "woman's hat emoji - 4 bytes in UTF-8"
|
236
|
+
a_binary = PBinaryType::Binary.new("\u{1f452}")
|
237
|
+
expect(a_binary.length).to be(4)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
@@ -31,7 +31,7 @@ describe 'The Object Type' do
|
|
31
31
|
}
|
32
32
|
OBJECT
|
33
33
|
expect { parse_object('MyObject', obj) }.to raise_error(TypeAssertionError,
|
34
|
-
/attribute MyObject\[a\]
|
34
|
+
/attribute MyObject\[a\] has wrong type, expects a Type value, got Integer/)
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'raises an error if the type is missing' do
|
@@ -41,7 +41,7 @@ describe 'The Object Type' do
|
|
41
41
|
}
|
42
42
|
OBJECT
|
43
43
|
expect { parse_object('MyObject', obj) }.to raise_error(TypeAssertionError,
|
44
|
-
/
|
44
|
+
/expects a value for key 'type'/)
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'raises an error when value is of incompatible type' do
|
@@ -51,7 +51,7 @@ describe 'The Object Type' do
|
|
51
51
|
}
|
52
52
|
OBJECT
|
53
53
|
expect { parse_object('MyObject', obj) }.to raise_error(TypeAssertionError,
|
54
|
-
/attribute MyObject\[a\] value
|
54
|
+
/attribute MyObject\[a\] value has wrong type, expects an Integer value, got String/)
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'raises an error if the kind is invalid' do
|
@@ -61,7 +61,7 @@ describe 'The Object Type' do
|
|
61
61
|
}
|
62
62
|
OBJECT
|
63
63
|
expect { parse_object('MyObject', obj) }.to raise_error(TypeAssertionError,
|
64
|
-
/
|
64
|
+
/expects a match for Enum\['constant', 'derived', 'given_or_derived'\], got 'derivd'/)
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'stores value in attribute' do
|
@@ -155,7 +155,7 @@ describe 'The Object Type' do
|
|
155
155
|
}
|
156
156
|
OBJECT
|
157
157
|
expect { parse_object('MyObject', obj) }.to raise_error(TypeAssertionError,
|
158
|
-
/function MyObject\[a\]
|
158
|
+
/function MyObject\[a\] has wrong type, expects a Type\[Callable\] value, got Type\[String\]/)
|
159
159
|
end
|
160
160
|
|
161
161
|
it 'raises an error when a function has the same name as an attribute' do
|
@@ -494,7 +494,7 @@ describe 'The Object Type' do
|
|
494
494
|
a => Integer
|
495
495
|
}
|
496
496
|
OBJECT
|
497
|
-
expect { parse_object('MyObject', obj) }.to raise_error(TypeAssertionError, /object initializer
|
497
|
+
expect { parse_object('MyObject', obj) }.to raise_error(TypeAssertionError, /object initializer has wrong type, unrecognized key 'attribrutes'/)
|
498
498
|
end
|
499
499
|
|
500
500
|
it 'raises an error when attribute contains invalid keys' do
|
@@ -503,7 +503,7 @@ describe 'The Object Type' do
|
|
503
503
|
a => { type => Integer, knid => constant }
|
504
504
|
}
|
505
505
|
OBJECT
|
506
|
-
expect { parse_object('MyObject', obj) }.to raise_error(TypeAssertionError, /initializer for attribute MyObject\[a\]
|
506
|
+
expect { parse_object('MyObject', obj) }.to raise_error(TypeAssertionError, /initializer for attribute MyObject\[a\] has wrong type, unrecognized key 'knid'/)
|
507
507
|
end
|
508
508
|
|
509
509
|
context 'when inheriting from a another Object type' do
|
@@ -96,7 +96,7 @@ describe 'Sensitive Type' do
|
|
96
96
|
CODE
|
97
97
|
expect {
|
98
98
|
eval_and_collect_notices(code)
|
99
|
-
}.to raise_error(Puppet::Error, /
|
99
|
+
}.to raise_error(Puppet::Error, /expects a Sensitive\[String\[10, 20\]\] value, got Sensitive\[String\[7, 7\]\]/)
|
100
100
|
end
|
101
101
|
|
102
102
|
it 'does not match an inappropriate parameterized type' do
|
@@ -0,0 +1,273 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'puppet/pops'
|
3
|
+
require 'puppet_spec/compiler'
|
4
|
+
|
5
|
+
module Puppet::Pops
|
6
|
+
module Types
|
7
|
+
describe 'Timespan type' do
|
8
|
+
it 'is normalized in a Variant' do
|
9
|
+
t = TypeFactory.variant(TypeFactory.timespan('10:00:00', '15:00:00'), TypeFactory.timespan('14:00:00', '17:00:00')).normalize
|
10
|
+
expect(t).to be_a(PTimespanType)
|
11
|
+
expect(t).to eql(TypeFactory.timespan('10:00:00', '17:00:00'))
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when used in Puppet expressions' do
|
15
|
+
include PuppetSpec::Compiler
|
16
|
+
it 'is equal to itself only' do
|
17
|
+
code = <<-CODE
|
18
|
+
$t = Timespan
|
19
|
+
notice(Timespan =~ Type[Timespan])
|
20
|
+
notice(Timespan == Timespan)
|
21
|
+
notice(Timespan < Timespan)
|
22
|
+
notice(Timespan > Timespan)
|
23
|
+
CODE
|
24
|
+
expect(eval_and_collect_notices(code)).to eq(%w(true true false false))
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when parameterized" do
|
28
|
+
it 'is equal other types with the same parameterization' do
|
29
|
+
code = <<-CODE
|
30
|
+
notice(Timespan['01:00:00', '13:00:00'] == Timespan['01:00:00', '13:00:00'])
|
31
|
+
notice(Timespan['01:00:00', '13:00:00'] != Timespan['01:12:20', '13:00:00'])
|
32
|
+
CODE
|
33
|
+
expect(eval_and_collect_notices(code)).to eq(%w(true true))
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'using just one parameter is the same as using that parameter twice' do
|
37
|
+
code = <<-CODE
|
38
|
+
notice(Timespan['01:00:00'] == Timespan['01:00:00', '01:00:00'])
|
39
|
+
CODE
|
40
|
+
expect(eval_and_collect_notices(code)).to eq(%w(true))
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'orders parameterized types based on range inclusion' do
|
44
|
+
code = <<-CODE
|
45
|
+
notice(Timespan['01:00:00', '13:00:00'] < Timespan['00:00:00', '14:00:00'])
|
46
|
+
notice(Timespan['01:00:00', '13:00:00'] > Timespan['00:00:00', '14:00:00'])
|
47
|
+
CODE
|
48
|
+
expect(eval_and_collect_notices(code)).to eq(%w(true false))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'a Timespan instance' do
|
53
|
+
it 'can be created from a string' do
|
54
|
+
code = <<-CODE
|
55
|
+
$o = Timespan('3-11:00')
|
56
|
+
notice($o)
|
57
|
+
notice(type($o))
|
58
|
+
CODE
|
59
|
+
expect(eval_and_collect_notices(code)).to eq(%w(3-11:00:00.0 Timespan['3-11:00:00.0']))
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'can be created from a string and format' do
|
63
|
+
code = <<-CODE
|
64
|
+
$o = Timespan('1d11h23m', '%Dd%Hh%Mm')
|
65
|
+
notice($o)
|
66
|
+
CODE
|
67
|
+
expect(eval_and_collect_notices(code)).to eq(%w(1-11:23:00.0))
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'can be created from a hash with string and format' do
|
71
|
+
code = <<-CODE
|
72
|
+
$o = Timespan({string => '1d11h23m', format => '%Dd%Hh%Mm'})
|
73
|
+
notice($o)
|
74
|
+
CODE
|
75
|
+
expect(eval_and_collect_notices(code)).to eq(%w(1-11:23:00.0))
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'can be created from a string and array of formats' do
|
79
|
+
code = <<-CODE
|
80
|
+
$fmts = ['%Dd%Hh%Mm%Ss', '%Hh%Mm%Ss', '%Dd%Hh%Mm', '%Dd%Hh', '%Hh%Mm', '%Mm%Ss', '%Dd', '%Hh', '%Mm', '%Ss' ]
|
81
|
+
notice(Timespan('1d11h23m13s', $fmts))
|
82
|
+
notice(Timespan('11h23m13s', $fmts))
|
83
|
+
notice(Timespan('1d11h23m', $fmts))
|
84
|
+
notice(Timespan('1d11h', $fmts))
|
85
|
+
notice(Timespan('11h23m', $fmts))
|
86
|
+
notice(Timespan('23m13s', $fmts))
|
87
|
+
notice(Timespan('1d', $fmts))
|
88
|
+
notice(Timespan('11h', $fmts))
|
89
|
+
notice(Timespan('23m', $fmts))
|
90
|
+
notice(Timespan('13s', $fmts))
|
91
|
+
CODE
|
92
|
+
expect(eval_and_collect_notices(code)).to eq(
|
93
|
+
%w(1-11:23:13.0 0-11:23:13.0 1-11:23:00.0 1-11:00:00.0 0-11:23:00.0 0-00:23:13.0 1-00:00:00.0 0-11:00:00.0 0-00:23:00.0 0-00:00:13.0))
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'can be created from a integer that represents seconds since epoch' do
|
97
|
+
code = <<-CODE
|
98
|
+
$o = Timespan(6800)
|
99
|
+
notice(Integer($o) == 6800)
|
100
|
+
notice($o == Timespan('01:53:20'))
|
101
|
+
CODE
|
102
|
+
expect(eval_and_collect_notices(code)).to eq(%w(true true))
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'can be created from a float that represents seconds with fraction since epoch' do
|
106
|
+
code = <<-CODE
|
107
|
+
$o = Timespan(6800.123456789)
|
108
|
+
notice(Float($o) == 6800.123456789)
|
109
|
+
notice($o == Timespan('01:53:20.123456789', '%H:%M:%S.%N'))
|
110
|
+
CODE
|
111
|
+
expect(eval_and_collect_notices(code)).to eq(%w(true true))
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'matches the appropriate parameterized type' do
|
115
|
+
code = <<-CODE
|
116
|
+
$o = Timespan('3-11:12:13')
|
117
|
+
notice(assert_type(Timespan['3-00:00:00', '4-00:00:00'], $o))
|
118
|
+
CODE
|
119
|
+
expect(eval_and_collect_notices(code)).to eq(['3-11:12:13.0'])
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'does not match an inappropriate parameterized type' do
|
123
|
+
code = <<-CODE
|
124
|
+
$o = Timespan('1-03:04:05')
|
125
|
+
notice(assert_type(Timespan['2-00:00:00', '3-00:00:00'], $o) |$e, $a| { 'nope' })
|
126
|
+
CODE
|
127
|
+
expect(eval_and_collect_notices(code)).to eq(['nope'])
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'can be compared to other instances' do
|
131
|
+
code = <<-CODE
|
132
|
+
$o1 = Timespan('00:00:01')
|
133
|
+
$o2 = Timespan('00:00:02')
|
134
|
+
$o3 = Timespan('00:00:02')
|
135
|
+
notice($o1 > $o3)
|
136
|
+
notice($o1 >= $o3)
|
137
|
+
notice($o1 < $o3)
|
138
|
+
notice($o1 <= $o3)
|
139
|
+
notice($o1 == $o3)
|
140
|
+
notice($o1 != $o3)
|
141
|
+
notice($o2 > $o3)
|
142
|
+
notice($o2 < $o3)
|
143
|
+
notice($o2 >= $o3)
|
144
|
+
notice($o2 <= $o3)
|
145
|
+
notice($o2 == $o3)
|
146
|
+
notice($o2 != $o3)
|
147
|
+
CODE
|
148
|
+
expect(eval_and_collect_notices(code)).to eq(%w(false false true true false true false false true true true false))
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'can be compared to integer that represents seconds' do
|
152
|
+
code = <<-CODE
|
153
|
+
$o1 = Timespan('00:00:01')
|
154
|
+
$o2 = Timespan('00:00:02')
|
155
|
+
$o3 = 2
|
156
|
+
notice($o1 > $o3)
|
157
|
+
notice($o1 >= $o3)
|
158
|
+
notice($o1 < $o3)
|
159
|
+
notice($o1 <= $o3)
|
160
|
+
notice($o2 > $o3)
|
161
|
+
notice($o2 < $o3)
|
162
|
+
notice($o2 >= $o3)
|
163
|
+
notice($o2 <= $o3)
|
164
|
+
CODE
|
165
|
+
expect(eval_and_collect_notices(code)).to eq(%w(false false true true false false true true))
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'integer that represents seconds can be compared to it' do
|
169
|
+
code = <<-CODE
|
170
|
+
$o1 = 1
|
171
|
+
$o2 = 2
|
172
|
+
$o3 = Timespan('00:00:02')
|
173
|
+
notice($o1 > $o3)
|
174
|
+
notice($o1 >= $o3)
|
175
|
+
notice($o1 < $o3)
|
176
|
+
notice($o1 <= $o3)
|
177
|
+
notice($o2 > $o3)
|
178
|
+
notice($o2 < $o3)
|
179
|
+
notice($o2 >= $o3)
|
180
|
+
notice($o2 <= $o3)
|
181
|
+
CODE
|
182
|
+
expect(eval_and_collect_notices(code)).to eq(%w(false false true true false false true true))
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'is equal to integer that represents seconds' do
|
186
|
+
code = <<-CODE
|
187
|
+
$o1 = Timespan('02', '%S')
|
188
|
+
$o2 = 2
|
189
|
+
notice($o1 == $o2)
|
190
|
+
notice($o1 != $o2)
|
191
|
+
notice(Integer($o1) == $o2)
|
192
|
+
CODE
|
193
|
+
expect(eval_and_collect_notices(code)).to eq(%w(true false true))
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'integer that represents seconds is equal to it' do
|
197
|
+
code = <<-CODE
|
198
|
+
$o1 = 2
|
199
|
+
$o2 = Timespan('02', '%S')
|
200
|
+
notice($o1 == $o2)
|
201
|
+
notice($o1 != $o2)
|
202
|
+
notice($o1 == Integer($o2))
|
203
|
+
CODE
|
204
|
+
expect(eval_and_collect_notices(code)).to eq(%w(true false true))
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'can be compared to float that represents seconds with fraction' do
|
208
|
+
code = <<-CODE
|
209
|
+
$o1 = Timespan('01.123456789', '%S.%N')
|
210
|
+
$o2 = Timespan('02.123456789', '%S.%N')
|
211
|
+
$o3 = 2.123456789
|
212
|
+
notice($o1 > $o3)
|
213
|
+
notice($o1 >= $o3)
|
214
|
+
notice($o1 < $o3)
|
215
|
+
notice($o1 <= $o3)
|
216
|
+
notice($o2 > $o3)
|
217
|
+
notice($o2 < $o3)
|
218
|
+
notice($o2 >= $o3)
|
219
|
+
notice($o2 <= $o3)
|
220
|
+
CODE
|
221
|
+
expect(eval_and_collect_notices(code)).to eq(%w(false false true true false false true true))
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'float that represents seconds with fraction can be compared to it' do
|
225
|
+
code = <<-CODE
|
226
|
+
$o1 = 1.123456789
|
227
|
+
$o2 = 2.123456789
|
228
|
+
$o3 = Timespan('02.123456789', '%S.%N')
|
229
|
+
notice($o1 > $o3)
|
230
|
+
notice($o1 >= $o3)
|
231
|
+
notice($o1 < $o3)
|
232
|
+
notice($o1 <= $o3)
|
233
|
+
notice($o2 > $o3)
|
234
|
+
notice($o2 < $o3)
|
235
|
+
notice($o2 >= $o3)
|
236
|
+
notice($o2 <= $o3)
|
237
|
+
CODE
|
238
|
+
expect(eval_and_collect_notices(code)).to eq(%w(false false true true false false true true))
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'is equal to float that represents seconds with fraction' do
|
242
|
+
code = <<-CODE
|
243
|
+
$o1 = Timespan('02.123456789', '%S.%N')
|
244
|
+
$o2 = 2.123456789
|
245
|
+
notice($o1 == $o2)
|
246
|
+
notice($o1 != $o2)
|
247
|
+
notice(Float($o1) == $o2)
|
248
|
+
CODE
|
249
|
+
expect(eval_and_collect_notices(code)).to eq(%w(true false true))
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'float that represents seconds with fraction is equal to it' do
|
253
|
+
code = <<-CODE
|
254
|
+
$o1 = 2.123456789
|
255
|
+
$o2 = Timespan('02.123456789', '%S.%N')
|
256
|
+
notice($o1 == $o2)
|
257
|
+
notice($o1 != $o2)
|
258
|
+
notice($o1 == Float($o2))
|
259
|
+
CODE
|
260
|
+
expect(eval_and_collect_notices(code)).to eq(%w(true false true))
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'it cannot be compared to a Timestamp' do
|
264
|
+
code = <<-CODE
|
265
|
+
notice(Timespan(3) < Timestamp())
|
266
|
+
CODE
|
267
|
+
expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /Timespans are only comparable to Timespans, Integers, and Floats/)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|