Commit graph

41 commits

Author SHA1 Message Date
Jeremy Evans
29f2cb83fb
Fix evaluation order issue in f(**h, &h.delete(key))
Previously, this would delete the key in `h` before keyword
splatting `h`.  This goes against how ruby handles `f(*a, &a.pop)`
and similar expressions.

Fix this by having the compiler check whether the block pass
expression is safe.  If it is not safe, then dup the keyword
splatted hash before evaluating the block pass expression.

For expression: `h=nil; f(**h, &h.delete(:key))`

VM instructions before:

```
0000 putnil                                                           (   1)[Li]
0001 setlocal_WC_0                          h@0
0003 putself
0004 getlocal_WC_0                          h@0
0006 getlocal_WC_0                          h@0
0008 putobject                              :key
0010 opt_send_without_block                 <calldata!mid:delete, argc:1, ARGS_SIMPLE>
0012 splatkw
0013 send                                   <calldata!mid:f, argc:1, ARGS_BLOCKARG|FCALL|KW_SPLAT>, nil
0016 leave
```

VM instructions after:

```
0000 putnil                                                           (   1)[Li]
0001 setlocal_WC_0                          h@0
0003 putself
0004 putspecialobject                       1
0006 newhash                                0
0008 getlocal_WC_0                          h@0
0010 opt_send_without_block                 <calldata!mid:core#hash_merge_kwd, argc:2, ARGS_SIMPLE>
0012 getlocal_WC_0                          h@0
0014 putobject                              :key
0016 opt_send_without_block                 <calldata!mid:delete, argc:1, ARGS_SIMPLE>
0018 send                                   <calldata!mid:f, argc:1, ARGS_BLOCKARG|FCALL|KW_SPLAT|KW_SPLAT_MUT>, nil
0021 leave
```

This is the same as 07d3bf4832, except that
it removes unnecessary hash allocations when using the prism compiler.

Fixes [Bug #20640]
2024-09-18 12:46:07 -07:00
Jeremy Evans
9c12c39ed1 Revert "Fix evaluation order issue in f(**h, &h.delete(key))"
This reverts commit 07d3bf4832.

No failures in the pull request CI, but there are now allocation
test failures.
2024-09-18 11:26:10 -07:00
Jeremy Evans
07d3bf4832
Fix evaluation order issue in f(**h, &h.delete(key))
Previously, this would delete the key in h before keyword
splatting h.  This goes against how ruby handles f(*a, &a.pop)
and similar expressions.

Fix this by having the compiler check whether the block pass
expression is safe.  If it is not safe, then dup the keyword
splatted hash before evaluating the block pass expression.

For expression: `h=nil; f(**h, &h.delete(:key))`

VM instructions before:

```
0000 putnil                                                           (   1)[Li]
0001 setlocal_WC_0                          h@0
0003 putself
0004 getlocal_WC_0                          h@0
0006 getlocal_WC_0                          h@0
0008 putobject                              :key
0010 opt_send_without_block                 <calldata!mid:delete, argc:1, ARGS_SIMPLE>
0012 splatkw
0013 send                                   <calldata!mid:f, argc:1, ARGS_BLOCKARG|FCALL|KW_SPLAT>, nil
0016 leave
```

VM instructions after:

```
0000 putnil                                                           (   1)[Li]
0001 setlocal_WC_0                          h@0
0003 putself
0004 putspecialobject                       1
0006 newhash                                0
0008 getlocal_WC_0                          h@0
0010 opt_send_without_block                 <calldata!mid:core#hash_merge_kwd, argc:2, ARGS_SIMPLE>
0012 getlocal_WC_0                          h@0
0014 putobject                              :key
0016 opt_send_without_block                 <calldata!mid:delete, argc:1, ARGS_SIMPLE>
0018 send                                   <calldata!mid:f, argc:1, ARGS_BLOCKARG|FCALL|KW_SPLAT|KW_SPLAT_MUT>, nil
0021 leave
```

Fixes [Bug #20640]
2024-09-18 11:18:29 -07:00
Yusuke Endoh
0f3dc2f958 Prevent warnings "the block passed to ... may be ignored" 2024-09-13 16:52:38 +09:00
Jeremy Evans
a3562c2a0a
Remove incorrect setting of KW_SPLAT_MUT flag
Fixes [Bug #20701]

Co-authored-by: Pablo Herrero <pablodherrero@gmail.com>
2024-08-27 09:08:22 -07:00
Jeremy Evans
3de20efc30 Avoid unnecessary array allocations for f(arg, *arg, **arg, **arg), f(*arg, a: lvar), and other calls
The `f(arg, *arg, **arg, **arg)` case was previously not optimized.
The optimizer didn't optimize this case because of the multiple
keyword splats, and the compiler didn't optimize it because the
`f(*arg, **arg, **arg)` optimization added in
0ee3960685 didn't apply.

I found it difficult to apply this optimization without changing
the `setup_args_core` API, since by the time you get to the ARGSCAT
case, you don't know whether you were called recursively or directly,
so I'm not sure if it was possible to know at that point whether the
array allocation could be avoided.

This changes the dup_rest argument in `setup_args_core` from an int
to a pointer to int.  This allows us to track whether we have allocated
a caller side array for multiple splats or splat+post across
recursive calls. Check the pointed value (*dup_rest) to determine the
`splatarray` argument. If dup_rest is 1, then use `splatarray true`
(caller-side array allocation), then set *dup_rest back to 0, ensuring
only a single `splatarray true` per method call.

Before calling `setup_args_core`, check whether the array allocation
can be avoided safely using `splatarray false`.  Optimizable cases are:

```
// f(*arg)
SPLAT

// f(1, *arg)
ARGSCAT
 LIST

// f(*arg, **arg)
ARGSPUSH
 SPLAT
 HASH nd_brace=0

// f(1, *arg, **arg)
ARGSPUSH
  ARGSCAT
   LIST
  HASH nd_brace=0
```

If so, dup_rest is set to 0 instead of 1 to avoid the allocation.

After calling `setup_args_core`, check the flag. If the flag
includes `VM_CALL_ARGS_SPLAT`, and the pointed value has changed,
indicating `splatarray true` was used, then also set
`VM_CALL_ARGS_SPLAT_MUT` in the flag.

My initial attempt at this broke the `f(*ary, &ary.pop)` test,
because we were not duplicating the ary in the splat even though
it was modified later (evaluation order issue). The initial attempt
would also break `f(*ary, **ary.pop)` or `f(*ary, kw: ary.pop)` cases
for the same reason. I added test cases for those evaluation
order issues.

Add setup_args_dup_rest_p static function that checks that a given
node is safe.  Call that on the block pass node to determine if
the block pass node is safe.  Also call it on each of the hash
key/value nodes to test that they are safe.  If any are not safe,
then set dup_rest = 1 so that `splatarray true` will be used to
avoid the evaluation order issue.

This new approach has the affect of optimizing most cases of
literal keywords after positional splats.  Previously, only
static keyword hashes after positional splats avoided array
allocation for the splat.  Now, most dynamic keyword hashes
after positional splats also avoid array allocation.

Add allocation tests for dynamic keyword keyword hashes after
positional splats.

setup_args_dup_rest_p is currently fairly conservative. It
could definitely be expanded to handle additional node types
to reduce allocations in additional cases.
2024-07-18 22:17:21 -07:00
Jeremy Evans
89486c79bb
Make error messages clear blocks/keywords are disallowed in index assignment
Blocks and keywords are allowed in regular index.

Also update NEWS to make this more clear.

Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2024-05-31 08:22:40 -07:00
Yusuke Endoh
cb30c3d2b3 Prevent "assigned but unused variable" warnings 2024-04-04 13:29:41 +09:00
Nobuyoshi Nakada
0d5b16599a
[Bug #20218] Reject keyword arguments in index 2024-03-17 13:20:23 +09:00
Jeremy Evans
29e99c84ae Remove unused variables in test_call_op_asgn_keywords_mutable 2023-12-14 18:44:13 -08:00
Jeremy Evans
a18819e65f Fix op asgn method calls passing mutable keyword splats
When passing the keyword splat to [], it cannot be mutable, because
mutating the keyword splat inside [] would result in changes to the
keyword splat passed to []=.
2023-12-14 08:13:43 -08:00
Jeremy Evans
2f1d6da8c4
Fix op asgn calls with keywords
Examples of such calls:

```ruby
obj[kw: 1] += fo
obj[**kw] &&= bar
```

Before this patch, literal keywords would segfault in the compiler,
and keyword splat usage would result in TypeError.

This handles all cases I can think of:

* literal keywords
* keyword splats
* combined with positional arguments
* combined with regular splats
* both with and without blocks
* both popped and non-popped cases

This also makes sure that to_hash is only called once on the keyword
splat argument, instead of twice, and make sure it is called before
calling to_proc on a passed block.

Fixes [Bug #20051]

Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2023-12-12 07:34:53 -08:00
Jeremy Evans
f64357540e Ensure super(**kw, &block) calls kw.to_hash before block.to_proc
Similar as previous commit, but handles the super case with
explicit arguments.
2023-12-09 13:15:47 -08:00
Jeremy Evans
a950f23078 Ensure f(**kw, &block) calls kw.to_hash before block.to_proc
Previously, block.to_proc was called first, by vm_caller_setup_arg_block.
kw.to_hash was called later inside CALLER_SETUP_ARG or setup_parameters_complex.

This adds a splatkw instruction that is inserted before sends with
ARGS_BLOCKARG and KW_SPLAT and without KW_SPLAT_MUT. This is not needed in the
KW_SPLAT_MUT case, because then you know the value is a hash, and you don't
need to call to_hash on it.

The splatkw instruction checks whether the second to top block is a hash,
and if not, replaces it with the value of calling to_hash on it (using
rb_to_hash_type).  As it is always before a send with ARGS_BLOCKARG and
KW_SPLAT, second to top is the keyword splat, and top is the passed block.
2023-12-09 13:15:47 -08:00
Jeremy Evans
13cd963500 Prevent modification of splat array inside setup_parameters_complex
For the following:

```
def f(*a); a end
p f(*a, kw: 3)
```

`setup_parameters_complex` pushes `{kw: 3}` onto `a`.  This worked fine
back when `concatarray true` was used and `a` was already a copy. It
does not work correctly with the optimization to switch to
`concatarray false`.  This duplicates the array on the callee side
in such a case.

This affects cases when passing a regular splat and a keyword splat
(or literal keywords) in a method call, where the method does not
accept keywords.

This allocation could probably be avoided, but doing so would
make `setup_parameters_complex` more complicated.
2023-12-07 11:27:55 -08:00
Jeremy Evans
ae48d4ad2e Ensure keyword splat method argument is hash
Commit e87d088291 introduced a
regression where the keyword splat object passed by the caller
would be directly used by callee as keyword splat parameters,
if it implemented #to_hash.  The return value of #to_hash would be
ignored in this case.
2023-11-18 09:44:42 -08:00
Nobuyoshi Nakada
7b3a531fff
Split the bmethod proc test to avoid redefinition 2023-06-17 12:29:28 +09:00
Jeremy Evans
f6254f77f7 Speed up calling iseq bmethods
Currently, bmethod arguments are copied from the VM stack to the
C stack in vm_call_bmethod, then copied from the C stack to the VM
stack later in invoke_iseq_block_from_c.  This is inefficient.

This adds vm_call_iseq_bmethod and vm_call_noniseq_bmethod.
vm_call_iseq_bmethod is an optimized method that skips stack
copies (though there is one copy to remove the receiver from
the stack), and avoids calling vm_call_bmethod_body,
rb_vm_invoke_bmethod, invoke_block_from_c_proc,
invoke_iseq_block_from_c, and vm_yield_setup_args.

Th vm_call_iseq_bmethod argument handling is similar to the
way normal iseq methods are called, and allows for similar
performance optimizations when using splats or keywords.
However, even in the no argument case it's still significantly
faster.

A benchmark is added for bmethod calling.  In my environment,
it improves bmethod calling performance by 38-59% for simple
bmethod calls, and up to 180% for bmethod calls passing
literal keywords on both sides.

```

./miniruby-iseq-bmethod:  18159792.6 i/s
          ./miniruby-m:  13174419.1 i/s - 1.38x  slower

                   bmethod_simple_1
./miniruby-iseq-bmethod:  15890745.4 i/s
          ./miniruby-m:  10008972.7 i/s - 1.59x  slower

             bmethod_simple_0_splat
./miniruby-iseq-bmethod:  13142804.3 i/s
          ./miniruby-m:  11168595.2 i/s - 1.18x  slower

             bmethod_simple_1_splat
./miniruby-iseq-bmethod:  12375791.0 i/s
          ./miniruby-m:   8491140.1 i/s - 1.46x  slower

                   bmethod_no_splat
./miniruby-iseq-bmethod:  10151258.8 i/s
          ./miniruby-m:   8716664.1 i/s - 1.16x  slower

                    bmethod_0_splat
./miniruby-iseq-bmethod:   8138802.5 i/s
          ./miniruby-m:   7515600.2 i/s - 1.08x  slower

                    bmethod_1_splat
./miniruby-iseq-bmethod:   8028372.7 i/s
          ./miniruby-m:   5947658.6 i/s - 1.35x  slower

                   bmethod_10_splat
./miniruby-iseq-bmethod:   6953514.1 i/s
          ./miniruby-m:   4840132.9 i/s - 1.44x  slower

                  bmethod_100_splat
./miniruby-iseq-bmethod:   5287288.4 i/s
          ./miniruby-m:   2243218.4 i/s - 2.36x  slower

                         bmethod_kw
./miniruby-iseq-bmethod:   8931358.2 i/s
          ./miniruby-m:   3185818.6 i/s - 2.80x  slower

                      bmethod_no_kw
./miniruby-iseq-bmethod:  12281287.4 i/s
          ./miniruby-m:  10041727.9 i/s - 1.22x  slower

                   bmethod_kw_splat
./miniruby-iseq-bmethod:   5618956.8 i/s
          ./miniruby-m:   3657549.5 i/s - 1.54x  slower
```
2023-04-25 08:06:16 -07:00
Jeremy Evans
99c6d19e50 Generalize cfunc large array splat fix to fix many additional cases raising SystemStackError
Originally, when 2e7bceb34e fixed cfuncs to no
longer use the VM stack for large array splats, it was thought to have fully
fixed Bug #4040, since the issue was fixed for methods defined in Ruby (iseqs)
back in Ruby 2.2.

After additional research, I determined that same issue affects almost all
types of method calls, not just iseq and cfunc calls.  There were two main
types of remaining issues, important cases (where large array splat should
work) and pedantic cases (where large array splat raised SystemStackError
instead of ArgumentError).

Important cases:

```ruby
define_method(:a){|*a|}
a(*1380888.times)

def b(*a); end
send(:b, *1380888.times)

:b.to_proc.call(self, *1380888.times)

def d; yield(*1380888.times) end
d(&method(:b))

def self.method_missing(*a); end
not_a_method(*1380888.times)

```

Pedantic cases:

```ruby
def a; end
a(*1380888.times)
def b(_); end
b(*1380888.times)
def c(_=nil); end
c(*1380888.times)

c = Class.new do
  attr_accessor :a
  alias b a=
end.new
c.a(*1380888.times)
c.b(*1380888.times)

c = Struct.new(:a) do
  alias b a=
end.new
c.a(*1380888.times)
c.b(*1380888.times)
```

This patch fixes all usage of CALLER_SETUP_ARG with splatting a large
number of arguments, and required similar fixes to use a temporary
hidden array in three other cases where the VM would use the VM stack
for handling a large number of arguments.  However, it is possible
there may be additional cases where splatting a large number
of arguments still causes a SystemStackError.

This has a measurable performance impact, as it requires additional
checks for a large number of arguments in many additional cases.

This change is fairly invasive, as there were many different VM
functions that needed to be modified to support this. To avoid
too much API change, I modified struct rb_calling_info to add a
heap_argv member for storing the array, so I would not have to
thread it through many functions.  This struct is always stack
allocated, which helps ensure sure GC doesn't collect it early.

Because of how invasive the changes are, and how rarely large
arrays are actually splatted in Ruby code, the existing test/spec
suites are not great at testing for correct behavior.  To try to
find and fix all issues, I tested this in CI with
VM_ARGC_STACK_MAX to -1, ensuring that a temporary array is used
for all array splat method calls.  This was very helpful in
finding breaking cases, especially ones involving flagged keyword
hashes.

Fixes [Bug #4040]

Co-authored-by: Jimmy Miller <jimmy.miller@shopify.com>
2023-04-25 08:06:16 -07:00
Koichi Sasada
2e7bceb34e Do not use VM stack for splat arg on cfunc
On the cfunc methods, if a splat argument is given, all array elements
are expanded on the VM stack and it can cause SystemStackError.
The idea to avoid it is making a hidden array to contain all parameters
and use this array as an argv.

This patch is reviesed version of https://github.com/ruby/ruby/pull/6816
The main change is all changes are closed around calling cfunc logic.

Fixes [Bug #4040]

Co-authored-by: Jeremy Evans <code@jeremyevans.net>
2023-01-13 09:30:29 +09:00
John Hawthorn
b361bdc200 [Bug #19021] Fix safe call w/ conditional assign
As of fbaac837cf, when we were performing
a safe call (`o&.x=`) with a conditional assign (`||= 1`) and discarding
the result the stack would end up in a bad state due to a missing pop.

This commit fixes that by adjusting the target label of the branchnil to
be before a pop in that case (as was previously done in the
non-conditional assignment case).
2022-09-25 20:44:54 -07:00
Jeremy Evans
aae8223c70 Dup splat array in certain cases where there is a block argument
This makes:

```ruby
  args = [1, 2, -> {}]; foo(*args, &args.pop)
```

call `foo` with 1, 2, and the lambda, in addition to passing the
lambda as a block.  This is different from the previous behavior,
which passed the lambda as a block but not as a regular argument,
which goes against the expected left-to-right evaluation order.

This is how Ruby already compiled arguments if using leading
arguments, trailing arguments, or keywords in the same call.

This works by disabling the optimization that skipped duplicating
the array during the splat (splatarray instruction argument
switches from false to true).  In the above example, the splat
call duplicates the array.  I've tested and cases where a
local variable or symbol are used do not duplicate the array,
so I don't expect this to decrease the performance of most Ruby
programs.  However, programs such as:

```ruby
  foo(*args, &bar)
```

could see a decrease in performance, if `bar` is a method call
and not a local variable.

This is not a perfect solution, there are ways to get around
this:

```ruby
  args = Struct.new(:a).new([:x, :y])
  def args.to_a; a; end
  def args.to_proc; a.pop; ->{}; end
  foo(*args, &args)
  # calls foo with 1 argument (:x)
  # not 2 arguments (:x and :y)
```

A perfect solution would require completely disabling the
optimization.

Fixes [Bug #16504]
Fixes [Bug #16500]
2020-06-18 08:19:33 -07:00
nobu
548698397a test_call.rb: refine test_safe_call
* test/ruby/test_call.rb (test_safe_call): rhs should not be
  evaluated when the receiver is nil.  simplified the assertion
  for  [Bug #13964].

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60100 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-10-02 11:43:36 +00:00
nobu
896e7f2d8d compile.c: fix stack consitency error
* compile.c (iseq_compile_each0): fix stack consitency error on
  attr-assign with safe navigation operator when the receiver is
  nil, should pop it too.  [ruby-core:83078] [Bug #13964]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60099 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-10-02 08:33:30 +00:00
nobu
d506a3521c compile.c: order with splatting
* compile.c (setup_args): duplicate splatting array if more
  arguments present to obey left-to-right execution order.
  [ruby-core:77701] [Bug# 12860]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56469 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-10-22 00:52:59 +00:00
nobu
c79402c4f0 symbol.h: unexpected safe call
* symbol.h (is_attrset_id): ASET is an attrset ID.  fix
  unexpected safe call instead of an ordinary ASET.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53485 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-01-09 09:26:23 +00:00
naruse
3e92b635fb Add frozen_string_literal: false for all files
When you change this to true, you may need to add more tests.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53141 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-16 05:07:31 +00:00
nobu
bfd34365b6 parse.y: fix block_call&.call
* parse.y (block_command, block_call): fix `&.` calls after
  block_call.  [Feature #11537]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53138 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-16 01:49:42 +00:00
nobu
837babd564 change DOTQ
* defs/id.def (token_ops), parse.y (parser_yylex): change DOTQ
  from ".?" to "&.".  [ruby-core:71363] [Feature #11537]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52462 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-06 03:39:23 +00:00
nobu
a3ee54f8a6 parse.y: revert lbracket
* parse.y (lbracket): remove .? before aref.  [Feature #11537]
  revert r52422 and r52424

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52430 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-03 00:27:04 +00:00
nobu
dbf73f6fc2 parse.y: lbracket
* parse.y (lbracket): support .? before aref.  [Feature #11537]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52422 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-02 11:07:13 +00:00
hsbt
a2845a44ff * test/ruby/test_call.rb: added test for safe navigation operator.
[fix GH-1066]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52383 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-30 03:56:06 +00:00
nobu
1d3c07633c test_call.rb: add tests
* test_call.rb (test_safe_call): Add test cases for safe
  navigation operator assignment.  [Fix GH-1064]
  Validate:
  * can assign an attribute which is `nil`
  * can "or assign" an attribute which is `nil`

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52238 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-23 04:51:35 +00:00
nobu
0b7d473734 safe navigation attrset
* compile.c (iseq_compile_each): support safe navigation of simple
  attribute assignment.  [Feature #11537]
* parse.y (mlhs_node, lhs, attrset_gen): ditto.  keep mid
  non-attrset as the sign of safe navigation.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52234 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-23 01:49:38 +00:00
nobu
a356fe1c35 Safe navigation operator
* compile.c (iseq_peephole_optimize): peephole optimization for
  branchnil jumps.
* compile.c (iseq_compile_each): generate save navigation operator
  code.
* insns.def (branchnil): new opcode to pop the tos and branch if
  it is nil.
* parse.y (NEW_QCALL, call_op, parser_yylex): parse token '.?'.
  [Feature #11537]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52214 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-22 06:30:12 +00:00
nobu
c28b5723f6 vm_insnhelper.c: disable fastpath if splat
* vm_insnhelper.c (vm_callee_setup_arg): disable fastpath if splat
  argument, since argc may differ for each calls.
  [ruby-core:61422] [Bug #9622]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45321 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2014-03-12 02:19:13 +00:00
nobu
00b4a3f9c4 * test: assert_raises has been deprecated since a long time ago.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19536 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-09-24 17:44:39 +00:00
nahi
994dfc0ae6 * test/*: should not depend on $KCODE.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5764 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2004-02-18 13:08:08 +00:00
nobu
44785befea * lib/optparse.rb (OptionParser#order, #permute, #parse): allow an
array as argument.

* test/ruby/test_*.rb: moved invariants to left side in
  assert_equal, and use assert_nil, assert_raises and so on.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4516 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-09-05 15:15:43 +00:00
nahi
65264eadbd * test/ruby/test_*.rb: replace 'assert(a == b)' with assert_equal(a, b)'
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4512 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-09-05 11:28:27 +00:00
nahi
aaf5d9c03c * test/ruby: tests for ruby itself.
* test/ruby/test_*.rb: split sample/test.rb into 28 test/unit testcases.  some
  tests could not be translates...  search '!!' mark to see it.

* test/csv/test_csv.rb: should require 'csv', not '../lib/csv'.  test runner
  should set load path correctly.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4498 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-09-04 16:18:59 +00:00