diff --git a/doc/language/globals.md b/doc/language/globals.md index b9315f5ff975e4..b22363f1da1b71 100644 --- a/doc/language/globals.md +++ b/doc/language/globals.md @@ -14,70 +14,72 @@ require 'English' ### Exceptions -| Variable | English | Contains | -|-------------|-------------------|----------------------------------------------------| -| `$!` | `$ERROR_INFO` | Exception object; set by Kernel#raise. | -| `$@` | `$ERROR_POSITION` | Array of backtrace positions; set by Kernel#raise. | +| Variable | English | Contains | +|:--------:|:-----------------:|----------------------------------------------------| +| `$!` | `$ERROR_INFO` | Exception object; set by Kernel#raise. | +| `$@` | `$ERROR_POSITION` | Array of backtrace positions; set by Kernel#raise. | ### Pattern Matching -| Variable | English | Contains | -|---------------|---------------------|--------------------------------------------------| -| `$~` | `$LAST_MATCH_INFO` | MatchData object; set by matcher method. | -| `$&` | `$MATCH` | Matched substring; set by matcher method. | -| `` $` `` | `$PRE_MATCH` | Substring left of match; set by matcher method. | -| `$'` | `$POST_MATCH` | Substring right of match; set by matcher method. | -| `$+` | `$LAST_PAREN_MATCH` | Last group matched; set by matcher method. | -| `$1` | | First group matched; set by matcher method. | -| `$2` | | Second group matched; set by matcher method. | +| Variable | English | Contains | +|:-------------:|:-------------------:|--------------------------------------------------| +| `$~` | `$LAST_MATCH_INFO` | MatchData object; set by matcher method. | +| `$&` | `$MATCH` | Matched substring; set by matcher method. | +| `` $` `` | `$PRE_MATCH` | Substring left of match; set by matcher method. | +| `$'` | `$POST_MATCH` | Substring right of match; set by matcher method. | +| `$+` | `$LAST_PAREN_MATCH` | Last group matched; set by matcher method. | +| `$1` | | First group matched; set by matcher method. | +| `$2` | | Second group matched; set by matcher method. | | $_n_ | | nth group matched; set by matcher method. | ### Separators -| Variable | English | Contains | -|----------|----------------------------|--------------------------------------------| -| `$/` | `$INPUT_RECORD_SEPARATOR` | Input record separator; initially newline. | -| `$\` | `$OUTPUT_RECORD_SEPARATOR` | Output record separator; initially `nil`. | +| Variable | English | Contains | +|:-----------:|:--------------------------:|--------------------------------------------| +| `$/`, `$-0` | `$INPUT_RECORD_SEPARATOR` | Input record separator; initially newline. | +| `$\` | `$OUTPUT_RECORD_SEPARATOR` | Output record separator; initially `nil`. | ### Streams -| Variable | English | Contains | -|-----------|-----------------------------|-----------------------------------------------| +| Variable | English | Contains | +|:---------:|:---------------------------:|-----------------------------------------------| | `$stdin` | | Standard input stream; initially `STDIN`. | | `$stdout` | | Standard input stream; initially `STDIOUT`. | | `$stderr` | | Standard input stream; initially `STDERR`. | -| `$<` | `$DEFAULT_INPUT` | Default standard input; `ARGF` or `$stdin`. | -| `$>` | `$DEFAULT_OUTPUT` | Default standard output; initially `$stdout`. | -| `$.` | `$INPUT_LINE_NUMBER`, `$NR` | Input position of most recently read stream. | -| `$_` | `$LAST_READ_LINE` | String from most recently read stream. | +| `$<` | `$DEFAULT_INPUT` | Default standard input; `ARGF` or `$stdin`. | +| `$>` | `$DEFAULT_OUTPUT` | Default standard output; initially `$stdout`. | +| `$.` | `$INPUT_LINE_NUMBER`, `$NR` | Input position of most recently read stream. | +| `$_` | `$LAST_READ_LINE` | String from most recently read stream. | ### Processes -| Variable | English | Contains | -|---------------------------|-----------------------|--------------------------------------------------------| -| `$0` | | Initially, the name of the executing program. | -| `$*` | `$ARGV` | Points to the `ARGV` array. | -| `$$` | `$PROCESS_ID`, `$PID` | Process ID of the current process. | -| `$?` | `$CHILD_STATUS` | Process::Status of most recently exited child process. | +| Variable | English | Contains | +|:-------------------------:|:---------------------:|--------------------------------------------------------| +| `$0` | | Initially, the name of the executing program. | +| `$*` | `$ARGV` | Points to the `ARGV` array. | +| `$$` | `$PROCESS_ID`, `$PID` | Process ID of the current process. | +| `$?` | `$CHILD_STATUS` | Process::Status of most recently exited child process. | | `$LOAD_PATH`, `$:`, `$-I` | | Array of paths to be searched. | | `$LOADED_FEATURES`, `$"` | | Array of paths to loaded files. | ### Debugging -| Variable | English | Contains | -|-------------|---------|--------------------------------------------------------| +| Variable | English | Contains | +|:-----------:|:-------:|--------------------------------------------------------| | `$FILENAME` | | The value returned by method ARGF.filename. | -| `$DEBUG` | | Initially, whether option `-d` or `--debug` was given. | +| `$DEBUG` | | Initially, whether option `-d` or `--debug` was given. | | `$VERBOSE` | | Initially, whether option `-V` or `-W` was given. | ### Other Variables -| Variable | English | Contains | -|----------|---------|------------------------------------------------| -| `$-a` | | Whether option `-a` was given. | -| `$-i` | | Extension given with command-line option `-i`. | -| `$-l` | | Whether option `-l` was given. | -| `$-p` | | Whether option `-p` was given. | +| Variable | English | Contains | +|:-----------:|:-------:|------------------------------------------------| +| `$-F`, `$;` | | Separator given with command-line option `-F`. | +| `$-a` | | Whether option `-a` was given. | +| `$-i` | | Extension given with command-line option `-i`. | +| `$-l` | | Whether option `-l` was given. | +| `$-p` | | Whether option `-p` was given. | +| `$F` | | Array of `$_` split by `$-F`. | ## Exceptions @@ -174,6 +176,10 @@ No \English. ### `$/` (Input Record Separator) An input record separator, initially newline. +Set by the command-line option `-0`. + +Setting to non-nil value by other than the command-line option is +deprecated. English - `$INPUT_RECORD_SEPARATOR`, `$RS`. @@ -182,6 +188,10 @@ Aliased as `$-0`. ### `$\` (Output Record Separator) An output record separator, initially `nil`. +Copied from `$/` when the command-line option `-l` is given. + +Setting to non-nil value by other than the command-line option is +deprecated. English - `$OUTPUT_RECORD_SEPARATOR`, `$ORS`. @@ -340,6 +350,16 @@ Aliased as `$-v` and `$-w`. ## Other Variables +### `$-F` + +The default field separator in String#split; must be a String or a +Regexp, and can be set with command-line option `-F`. + +Setting to non-nil value by other than the command-line option is +deprecated. + +Aliased as `$;`. + ### `$-a` Whether command-line option `-a` was given; read-only. @@ -359,14 +379,18 @@ Whether command-line option `-l` was set; read-only. Whether command-line option `-p` was given; read-only. +### `$F` + +If the command line option `-a` is given, the array obtained by +splitting `$_` by `$-F` is assigned at the start of each `-l`/`-p` +loop. + ## Deprecated ### `$=` ### `$,` -### `$;` - # Pre-Defined Global Constants ## Summary @@ -374,34 +398,34 @@ Whether command-line option `-p` was given; read-only. ### Streams | Constant | Contains | -|----------|-------------------------| +|:--------:|-------------------------| | `STDIN` | Standard input stream. | | `STDOUT` | Standard output stream. | | `STDERR` | Standard error stream. | ### Environment -| Constant | Contains | -|-----------------------|-------------------------------------------------------------------------------| -| `ENV` | Hash of current environment variable names and values. | -| `ARGF` | String concatenation of files given on the command line, or `$stdin` if none. | -| `ARGV` | Array of the given command-line arguments. | -| `TOPLEVEL_BINDING` | Binding of the top level scope. | -| `RUBY_VERSION` | String Ruby version. | -| `RUBY_RELEASE_DATE` | String Ruby release date. | -| `RUBY_PLATFORM` | String Ruby platform. | -| `RUBY_PATCH_LEVEL` | String Ruby patch level. | -| `RUBY_REVISION` | String Ruby revision. | -| `RUBY_COPYRIGHT` | String Ruby copyright. | -| `RUBY_ENGINE` | String Ruby engine. | +| Constant | Contains | +|:---------------------:|-------------------------------------------------------------------------------| +| `ENV` | Hash of current environment variable names and values. | +| `ARGF` | String concatenation of files given on the command line, or `$stdin` if none. | +| `ARGV` | Array of the given command-line arguments. | +| `TOPLEVEL_BINDING` | Binding of the top level scope. | +| `RUBY_VERSION` | String Ruby version. | +| `RUBY_RELEASE_DATE` | String Ruby release date. | +| `RUBY_PLATFORM` | String Ruby platform. | +| `RUBY_PATCH_LEVEL` | String Ruby patch level. | +| `RUBY_REVISION` | String Ruby revision. | +| `RUBY_COPYRIGHT` | String Ruby copyright. | +| `RUBY_ENGINE` | String Ruby engine. | | `RUBY_ENGINE_VERSION` | String Ruby engine version. | -| `RUBY_DESCRIPTION` | String Ruby description. | +| `RUBY_DESCRIPTION` | String Ruby description. | ### Embedded Data | Constant | Contains | -|----------|--------------------------------------------------------------------| -| `DATA` | File containing embedded data (lines following `__END__`, if any). | +|:--------:|--------------------------------------------------------------------| +| `DATA` | File containing embedded data (lines following `__END__`, if any). | ## Streams diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index cb13ac6ecf876d..b21a79484ccc4a 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -9,64 +9,81 @@ */ #include "ossl.h" -static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset, - int depth, int yield, long *num_read); -static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self); +/********/ +/* + * ASN1 module + */ +#define ossl_asn1_get_value(o) rb_attr_get((o),sivVALUE) +#define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG) +#define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING) +#define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS) +#define ossl_asn1_get_indefinite_length(o) rb_attr_get((o),sivINDEFINITE_LENGTH) + +#define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v)) +#define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v)) +#define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v)) +#define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v)) +#define ossl_asn1_set_indefinite_length(o,v) rb_ivar_set((o),sivINDEFINITE_LENGTH,(v)) + +VALUE mASN1; +static VALUE eASN1Error; + +VALUE cASN1Data; +static VALUE cASN1Primitive; +static VALUE cASN1Constructive; + +static VALUE cASN1EndOfContent; +static VALUE cASN1Boolean; /* BOOLEAN */ +static VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */ +static VALUE cASN1BitString; /* BIT STRING */ +static VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */ +static VALUE cASN1NumericString, cASN1PrintableString; +static VALUE cASN1T61String, cASN1VideotexString; +static VALUE cASN1IA5String, cASN1GraphicString; +static VALUE cASN1ISO64String, cASN1GeneralString; +static VALUE cASN1UniversalString, cASN1BMPString; +static VALUE cASN1Null; /* NULL */ +static VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */ +static VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */ +static VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ + +static VALUE sym_IMPLICIT, sym_EXPLICIT; +static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE; +static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINDEFINITE_LENGTH, sivUNUSED_BITS; +static ID id_each; /* * DATE conversion */ +static VALUE +time_utc_new(VALUE args) +{ + return rb_funcallv(rb_cTime, rb_intern("utc"), 6, (VALUE *)args); +} + +static VALUE +time_utc_new_rescue(VALUE args, VALUE exc) +{ + rb_raise(eASN1Error, "invalid time"); +} + VALUE asn1time_to_time(const ASN1_TIME *time) { struct tm tm; - VALUE argv[6]; - int count; - - memset(&tm, 0, sizeof(struct tm)); - - switch (time->type) { - case V_ASN1_UTCTIME: - count = sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, - &tm.tm_sec); - - if (count == 5) { - tm.tm_sec = 0; - } else if (count != 6) { - ossl_raise(rb_eTypeError, "bad UTCTIME format: \"%s\"", - time->data); - } - if (tm.tm_year < 50) { - tm.tm_year += 2000; - } else { - tm.tm_year += 1900; - } - break; - case V_ASN1_GENERALIZEDTIME: - count = sscanf((const char *)time->data, "%4d%2d%2d%2d%2d%2dZ", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, - &tm.tm_sec); - if (count == 5) { - tm.tm_sec = 0; - } - else if (count != 6) { - ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format: \"%s\"", - time->data); - } - break; - default: - rb_warning("unknown time format"); - return Qnil; - } - argv[0] = INT2NUM(tm.tm_year); - argv[1] = INT2NUM(tm.tm_mon); - argv[2] = INT2NUM(tm.tm_mday); - argv[3] = INT2NUM(tm.tm_hour); - argv[4] = INT2NUM(tm.tm_min); - argv[5] = INT2NUM(tm.tm_sec); - - return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv); + if (!ASN1_TIME_to_tm(time, &tm)) + ossl_raise(eASN1Error, "ASN1_TIME_to_tm"); + + VALUE args[] = { + INT2NUM(tm.tm_year + 1900), + INT2NUM(tm.tm_mon + 1), + INT2NUM(tm.tm_mday), + INT2NUM(tm.tm_hour), + INT2NUM(tm.tm_min), + INT2NUM(tm.tm_sec), + }; + return rb_rescue2(time_utc_new, (VALUE)args, time_utc_new_rescue, Qnil, + rb_eArgError, 0); } static VALUE @@ -190,49 +207,6 @@ ossl_asn1obj_to_string_long_name(const ASN1_OBJECT *obj) return ossl_asn1obj_to_string_oid(obj); } -/********/ -/* - * ASN1 module - */ -#define ossl_asn1_get_value(o) rb_attr_get((o),sivVALUE) -#define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG) -#define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING) -#define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS) -#define ossl_asn1_get_indefinite_length(o) rb_attr_get((o),sivINDEFINITE_LENGTH) - -#define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v)) -#define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v)) -#define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v)) -#define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v)) -#define ossl_asn1_set_indefinite_length(o,v) rb_ivar_set((o),sivINDEFINITE_LENGTH,(v)) - -VALUE mASN1; -static VALUE eASN1Error; - -VALUE cASN1Data; -static VALUE cASN1Primitive; -static VALUE cASN1Constructive; - -static VALUE cASN1EndOfContent; -static VALUE cASN1Boolean; /* BOOLEAN */ -static VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */ -static VALUE cASN1BitString; /* BIT STRING */ -static VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */ -static VALUE cASN1NumericString, cASN1PrintableString; -static VALUE cASN1T61String, cASN1VideotexString; -static VALUE cASN1IA5String, cASN1GraphicString; -static VALUE cASN1ISO64String, cASN1GeneralString; -static VALUE cASN1UniversalString, cASN1BMPString; -static VALUE cASN1Null; /* NULL */ -static VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */ -static VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */ -static VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ - -static VALUE sym_IMPLICIT, sym_EXPLICIT; -static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE; -static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINDEFINITE_LENGTH, sivUNUSED_BITS; -static ID id_each; - /* * Ruby to ASN1 converters */ @@ -777,6 +751,10 @@ ossl_asn1data_to_der(VALUE self) } } +static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self); +static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset, + int depth, int yield, long *num_read); + static VALUE int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag, VALUE tc, long *num_read) diff --git a/lib/net/http.rb b/lib/net/http.rb index 4205d414609bf0..8a4ff481872abc 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -1674,30 +1674,7 @@ def connect debug "opening connection to #{conn_addr}:#{conn_port}..." begin - s = - case @tcpsocket_supports_open_timeout - when nil, true - begin - # Use built-in timeout in TCPSocket.open if available - sock = TCPSocket.open(conn_addr, conn_port, @local_host, @local_port, open_timeout: @open_timeout) - @tcpsocket_supports_open_timeout = true - sock - rescue ArgumentError => e - raise if !(e.message.include?('unknown keyword: :open_timeout') || e.message.include?('wrong number of arguments (given 5, expected 2..4)')) - @tcpsocket_supports_open_timeout = false - - # Fallback to Timeout.timeout if TCPSocket.open does not support open_timeout - Timeout.timeout(@open_timeout, Net::OpenTimeout) { - TCPSocket.open(conn_addr, conn_port, @local_host, @local_port) - } - end - when false - # The current Ruby is known to not support TCPSocket(open_timeout:). - # Directly fall back to Timeout.timeout to avoid performance penalty incured by rescue. - Timeout.timeout(@open_timeout, Net::OpenTimeout) { - TCPSocket.open(conn_addr, conn_port, @local_host, @local_port) - } - end + s = timeouted_connect(conn_addr, conn_port) rescue => e e = Net::OpenTimeout.new(e) if e.is_a?(Errno::ETIMEDOUT) # for compatibility with previous versions raise e, "Failed to open TCP connection to " + @@ -1795,6 +1772,29 @@ def connect end private :connect + def timeouted_connect(conn_addr, conn_port) + if @tcpsocket_supports_open_timeout == nil || @tcpsocket_supports_open_timeout == true + # Try to use built-in open_timeout in TCPSocket.open if: + # - The current Ruby runtime is known to support it, or + # - It is unknown whether the current Ruby runtime supports it (so we'll try). + begin + sock = TCPSocket.open(conn_addr, conn_port, @local_host, @local_port, open_timeout: @open_timeout) + @tcpsocket_supports_open_timeout = true + return sock + rescue ArgumentError => e + raise if !(e.message.include?('unknown keyword: :open_timeout') || e.message.include?('wrong number of arguments (given 5, expected 2..4)')) + @tcpsocket_supports_open_timeout = false + end + end + + # This Ruby runtime is known not to support `TCPSocket(open_timeout:)`. + # Directly fall back to Timeout.timeout to avoid performance penalty incured by rescue. + Timeout.timeout(@open_timeout, Net::OpenTimeout) { + TCPSocket.open(conn_addr, conn_port, @local_host, @local_port) + } + end + private :timeouted_connect + def on_connect end private :on_connect diff --git a/lib/timeout.rb b/lib/timeout.rb index e1f0a4a78c6f59..f173d028a39d0a 100644 --- a/lib/timeout.rb +++ b/lib/timeout.rb @@ -133,6 +133,7 @@ def self.ensure_timeout_thread_created end end end + private_class_method :ensure_timeout_thread_created # We keep a private reference so that time mocking libraries won't break # Timeout. @@ -167,7 +168,7 @@ def self.ensure_timeout_thread_created # Note that this is both a method of module Timeout, so you can include # Timeout into your classes so they have a #timeout method, as well as # a module method, so you can call it directly as Timeout.timeout(). - def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ + def self.timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ return yield(sec) if sec == nil or sec.zero? raise ArgumentError, "Timeout sec must be a non-negative number" if 0 > sec @@ -177,7 +178,7 @@ def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ return scheduler.timeout_after(sec, klass || Error, message, &block) end - Timeout.ensure_timeout_thread_created + ensure_timeout_thread_created perform = Proc.new do |exc| request = Request.new(Thread.current, sec, exc, message) QUEUE_MUTEX.synchronize do @@ -197,5 +198,8 @@ def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ Error.handle_timeout(message, &perform) end end - module_function :timeout + + private def timeout(*args, &block) + Timeout.timeout(*args, &block) + end end diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb index df8b0accb36c84..5978ecf6736e10 100644 --- a/test/openssl/test_asn1.rb +++ b/test/openssl/test_asn1.rb @@ -426,17 +426,28 @@ def test_utctime OpenSSL::ASN1::UTCTime.new(Time.new(2049, 12, 31, 23, 0, 0, "-04:00")).to_der } - # not implemented + # UTC offset (BER): ASN1_TIME_to_tm() may or may not support it # decode_test B(%w{ 17 11 }) + "500908234339+0930".b, # OpenSSL::ASN1::UTCTime.new(Time.new(1950, 9, 8, 23, 43, 39, "+09:30")) # decode_test B(%w{ 17 0F }) + "5009082343-0930".b, # OpenSSL::ASN1::UTCTime.new(Time.new(1950, 9, 8, 23, 43, 0, "-09:30")) - # assert_raise(OpenSSL::ASN1::ASN1Error) { - # OpenSSL::ASN1.decode(B(%w{ 17 0C }) + "500908234339".b) - # } - # assert_raise(OpenSSL::ASN1::ASN1Error) { - # OpenSSL::ASN1.decode(B(%w{ 17 0D }) + "500908234339Y".b) - # } + + # Seconds is omitted (BER) + # decode_test B(%w{ 18 0D }) + "201612081934Z".b, + # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 0)) + + # Fractional seconds is not allowed in UTCTime + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.decode(B(%w{ 17 0F }) + "160908234339.5Z".b) + } + + # Missing "Z" + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.decode(B(%w{ 17 0C }) + "500908234339".b) + } + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.decode(B(%w{ 17 0D }) + "500908234339Y".b) + } end def test_generalizedtime @@ -444,24 +455,46 @@ def test_generalizedtime OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 29)) encode_decode_test B(%w{ 18 0F }) + "99990908234339Z".b, OpenSSL::ASN1::GeneralizedTime.new(Time.utc(9999, 9, 8, 23, 43, 39)) - # not implemented + + # Fractional seconds (DER). Not supported by ASN1_TIME_to_tm() + # because struct tm cannot store it. + # encode_decode_test B(%w{ 18 11 }) + "20161208193439.5Z".b, + # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 39.5)) + + # UTC offset (BER): ASN1_TIME_to_tm() may or may not support it # decode_test B(%w{ 18 13 }) + "20161208193439+0930".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 39, "+09:30")) # decode_test B(%w{ 18 11 }) + "201612081934-0930".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 0, "-09:30")) # decode_test B(%w{ 18 11 }) + "201612081934-09".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 0, "-09:00")) + + # Minutes and seconds are omitted (BER) + # decode_test B(%w{ 18 0B }) + "2016120819Z".b, + # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 0, 0)) + # Fractional hours (BER) # decode_test B(%w{ 18 0D }) + "2016120819.5Z".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 30, 0)) + # Fractional hours with "," as the decimal separator (BER) # decode_test B(%w{ 18 0D }) + "2016120819,5Z".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 30, 0)) + + # Seconds is omitted (BER) + # decode_test B(%w{ 18 0D }) + "201612081934Z".b, + # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 0)) + # Fractional minutes (BER) # decode_test B(%w{ 18 0F }) + "201612081934.5Z".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 30)) - # decode_test B(%w{ 18 11 }) + "20161208193439.5Z".b, - # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 39.5)) - # assert_raise(OpenSSL::ASN1::ASN1Error) { - # OpenSSL::ASN1.decode(B(%w{ 18 0D }) + "201612081934Y".b) - # } + + # Missing "Z" + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.decode(B(%w{ 18 0F }) + "20161208193429Y".b) + } + + # Encoding year out of range + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1::GeneralizedTime.new(Time.utc(10000, 9, 8, 23, 43, 39)).to_der + } end def test_basic_asn1data diff --git a/test/test_timeout.rb b/test/test_timeout.rb index 01156867b05609..e367df757cc9b2 100644 --- a/test/test_timeout.rb +++ b/test/test_timeout.rb @@ -4,6 +4,12 @@ class TestTimeout < Test::Unit::TestCase + def test_public_methods + assert_equal [:timeout], Timeout.private_instance_methods(false) + assert_equal [], Timeout.public_instance_methods(false) + assert_equal [:timeout], Timeout.singleton_class.public_instance_methods(false) + end + def test_work_is_done_in_same_thread_as_caller assert_equal Thread.current, Timeout.timeout(10){ Thread.current } end