Skip to content

Commit

Permalink
Test with The Ruby Spec Suite
Browse files Browse the repository at this point in the history
Adds The Ruby Spec Suite as a submodule and configures for running with
the FasterPatch monkey patches. Unfortunately, this doesn't run yet
because FasterPath has a bug that affects bundler.

Also fixes the `File.basename` monkeypatch.
  • Loading branch information
glebm committed Jun 21, 2016
1 parent 36f116a commit 72879c9
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 34 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
mkmf.log
**/*.swp
**/*.gem
/rubyspec_temp/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "spec/ruby_spec"]
path = spec/ruby_spec
url = https://github.com/ruby/spec
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ source 'https://rubygems.org'

# Specify your gem's dependencies in faster_path.gemspec
gemspec

# https://github.com/ruby/spec dependencies
eval_gemfile File.expand_path('spec/ruby_spec/Gemfile', File.dirname(__FILE__))
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ And then execute:
Or install it yourself as:

$ gem install faster_path

**MAC USERS:** At the moment Mac users need to install the extension manualy. Go to the gem directory and run `cargo build --release` . There is an issue opened for this and I'm looking for people who have Macs to help on this.

## Usage
Expand All @@ -134,7 +134,7 @@ Current methods implemented:
| `FasterPath.add_trailing_separator` | `Pathname#add_trailing_separator` | 46.8% |

You may choose to use the methods directly, or scope change to rewrite behavior on the
standard library with the included refinements, or even call a method to monkeypatch
standard library with the included refinements, or even call a method to monkeypatch
everything everywhere.

**Note:** `Pathname#chop_basename` in Ruby STDLIB has a bug with blank strings, that is the
Expand Down Expand Up @@ -169,6 +169,42 @@ Whenever feasible implement it in Rust.
After checking out the repo, make sure you have Rust installed. Then run `bundle && rake build_lib` .
Then, run `rake test` to run the tests, and `rake bench` for benchmarks.

### Building and running tests

First, bundle the gem's development dependencies by running `bundle`.

Then, build the rust code:

```sh
rake build_src
```

FasterPath is tested with [The Ruby Spec Suite](https://github.com/ruby/spec) to ensure it is compatible with the
native implementation, and also has its own test suite testing its monkey-patching and refinements functionality.

To run all the tests at once, simply run `rake`.
To run all the ruby spec tests, run `mspec`.

To run an individual test or benchmark from FasterPath's own suite:

```sh
# An individual test file:
ruby -I lib:test test/benches/absolute_benchmark.rb
# All tests:
rake minitest
```

To run an individual ruby spec test, run `mspec` with a path relative to `spec/ruby_spec`, e.g.:

```sh
# A path to a file or a directory:
mspec core/file/basename_spec.rb
# Tests most relevant to FasterPath:
mspec core/file library/pathname
# All tests:
mspec
```

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/danielpclark/faster_path.
Expand Down
6 changes: 5 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ task :build_lib => [:build_src, :clean_src] do
puts "Completed build!"
end

Rake::TestTask.new(:test) do |t|
Rake::TestTask.new(:minitest) do |t|
t.libs << "test"
t.libs << "lib"
t.test_files = FileList['test/**/*_test.rb']
end

task :test => :minitest do |t|
exec 'mspec core/file library/pathname'
end

Rake::TestTask.new(:bench) do |t|
t.libs = %w(lib test)
t.pattern = 'test/**/*_benchmark.rb'
Expand Down
12 changes: 7 additions & 5 deletions lib/faster_path/optional/monkeypatches.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
require 'pathname'

module FasterPath
def self.sledgehammer_everything!
::File.class_eval do
def basename(pth)
FasterPath.basename(pth)
end
end
::File.module_eval do
def self.basename(pth, ext = '')
FasterPath.basename(pth, ext)
end
end

::Pathname.class_eval do
def absolute?
Expand Down
6 changes: 3 additions & 3 deletions lib/faster_path/optional/refinements.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
module FasterPath
module RefineFile
refine File do
def basename(pth)
FasterPath.basename(pth)
def self.basename(pth, ext = '')
FasterPath.basename(pth, ext)
end
end
end
end

module RefinePathname
refine Pathname do
Expand Down
8 changes: 8 additions & 0 deletions spec/default.mspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
load 'spec/ruby_spec/default.mspec'

class MSpecScript
set :requires, ["-r#{File.expand_path('init', File.dirname(__FILE__))}"]
set :prefix, 'spec/ruby_spec'
end

MSpec.disable_feature :encoding
5 changes: 5 additions & 0 deletions spec/init.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__))
$LOAD_PATH.unshift File.expand_path('../lib', File.dirname(__FILE__))
require 'faster_path'
require 'faster_path/optional/monkeypatches'
FasterPath.sledgehammer_everything!
1 change: 1 addition & 0 deletions spec/ruby_spec
Submodule ruby_spec added at 8190a7
56 changes: 33 additions & 23 deletions src/basename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ fn it_chomps_strings_correctly(){
assert_eq!(rubyish_basename(".ruby/ruby.rb.swp",".rb") , "ruby.rb.swp");
assert_eq!(rubyish_basename(".ruby/ruby.rb.swp",".swp") , "ruby.rb");
assert_eq!(rubyish_basename(".ruby/ruby.rb.swp",".*") , "ruby.rb");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp","") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".*") , "asdf.rb");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", "*") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".*") , "asdf.rb");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".rb") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".swp") , "asdf.rb");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".sw") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".sw*") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp","") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".*") , "asdf.rb");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", "*") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".*") , "asdf.rb");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".rb") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".swp") , "asdf.rb");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".sw") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".sw*") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".rb.s*") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".s*") , "asdf.rb.swp");
assert_eq!(rubyish_basename("asdf/asdf.rb.swp", ".s**") , "asdf.rb.swp");
Expand All @@ -55,32 +55,42 @@ fn it_chomps_strings_correctly(){

#[no_mangle]
pub extern fn basename(str_pth: *const c_char, comp_ext: *const c_char) -> *const c_char {
if str_pth.is_null() || comp_ext.is_null() {
return str_pth;
}
let c_str1 = unsafe {
if str_pth.is_null(){
return str_pth;
}
CStr::from_ptr(str_pth)
};
let c_str2 = unsafe {
if comp_ext.is_null() {
return str_pth;
}
CStr::from_ptr(comp_ext)
};
// TODO: rb_raise on utf-8 errors
let string = str::from_utf8(c_str1.to_bytes()).unwrap();
let globish_string = str::from_utf8(c_str2.to_bytes()).unwrap();

let result = if globish_string == ".*" {
let base = string.rsplit_terminator(MAIN_SEPARATOR).nth(0).unwrap_or("");
let index = base.rfind(".");
let (first, _) = base.split_at(index.unwrap());
first
let result = if string.is_empty() {
string
} else if globish_string == ".*" {
let base = extract_last_segment(string);
match base.rfind(".") {
Some(index) => &base[0..index],
_ => base,
}
} else {
if &string[string.len()-globish_string.len()..] == globish_string {
&string[0..string.len()-globish_string.len()]
extract_last_segment(if &string[string.len() - globish_string.len()..] == globish_string {
&string[0..string.len() - globish_string.len()]
} else {
string
}.rsplit_terminator(MAIN_SEPARATOR).nth(0).unwrap_or("")
})
};
CString::new(result).unwrap().into_raw()
}

fn extract_last_segment(str: &str) -> &str {
let trimmed_str = str.trim_matches(MAIN_SEPARATOR);
if trimmed_str.is_empty() {
"/"
} else {
trimmed_str.rsplit_terminator(MAIN_SEPARATOR).nth(0).unwrap_or("")
}
}

0 comments on commit 72879c9

Please sign in to comment.