-
-
Notifications
You must be signed in to change notification settings - Fork 925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compass-rails test suite fails strangely under JRuby #2423
Comments
Some additional info from the build.
There's definitely file management involved somehow. The line that fails (first link in desc) is checking that the "project file" pf is in fact a File, using File.file?. This might indicate some path coercion issue, or an issue in File.file? logic (stat? posix stuff?). Note also that there's no successful build against JRuby 1.7 either, so this may not be a regression at all. |
Ok, there's a more serious problem here, and I no longer things it has anything to do with filesystem management. We've got some bad string code, it would seem:
The file "application.js.tt" should just be named "application.js". The extra .tt is coming from a JRuby bug. I saw this on some other reports form people that accidentally started running jruby-head on Travis. |
Same issue confirmed with a simple "rails new" without compass-rails being involved. |
Looking in the logic that copies these files into place during generation, I find: def javascripts
return if options.skip_javascript?
if mountable?
template "#{app_templates_dir}/app/assets/javascripts/application.js.tt",
"app/assets/javascripts/#{name}/application.js"
elsif full?
empty_directory_with_gitkeep "app/assets/javascripts/#{name}"
end
end So the .tt files are basically the template versions of new project files. The "template" function (which I have not found yet) takes these files and processes them...presumably into the target non-.tt filename. So somewhere along the way we're not losing the .tt filename? |
The bug manifests while running Thor's logic for processing directories. In that code, it cycles through all files in the directory, handling them in one of three ways: case file_source
when /\.empty_directory$/
$stderr.puts "empty dir"
dirname = File.dirname(file_destination).gsub(/\/\.$/, "")
next if dirname == given_destination
base.empty_directory(dirname, config)
when /#{TEMPLATE_EXTNAME}$/
$stderr.puts "template"
base.template(file_source, file_destination[0..-4], config, &@block)
else
$stderr.puts "else"
base.copy_file(file_source, file_destination, config, &@block)
end This logic prints out "else" for every case I could find, including filenames like application.js.tt that should have matched the template extension. I have confirmed this with additional logging, and see output like this: Code, ahead of the case/when logic: $stderr.puts(file_source)
$stderr.puts TEMPLATE_EXTNAME
$stderr.puts /#{TEMPLATE_EXTNAME}/ === file_source Output with stderr lines from previous snippit:
What we have here is a regexp that does match the filename for a normal === call, but apparently is not matching the when clause. |
Short reproduction, now that I've tracked down the problem: FOO = '.z'
case 'x.y.z'
when /#{FOO}/
p :here
else
p :there
end This code will print out ":there" even though the regexp-based when clause should have matched the file. Note that if you remove the FOO and replace with '.z', or just make the regexp be /.z/, it follows the expected path. Digging a bit deeper...here's the IR:
If I'm reading it right, it appears to building a "beq" instruction for the dynamic-regexp when clause, checking that the incoming value is equal to the regexp. Investigating IRBuilder next. |
The equivalent IR for a plain literal regexp when clause, for comparison:
Obviously this is completely different...and correct, since it's doing eqq (===). |
Ok, I see the problem. When parsed, the dynamic-regexp when clause looks like this (AST):
The IRBuilder logic for case/when includes this logic (comments removed): if (whenNode.getExpressionNodes() instanceof ListNode) {
if (value == UndefinedValue.UNDEFINED) {
v1 = build(whenNode.getExpressionNodes(), s);
v2 = manager.getTrue();
} else {
v1 = value;
v2 = build(whenNode.getExpressionNodes(), s);
}
} else {
s.addInstr(new EQQInstr(eqqResult, build(whenNode.getExpressionNodes(), s), value));
v1 = eqqResult;
v2 = manager.getTrue();
}
s.addInstr(BEQInstr.create(v1, v2, bodyLabel)); I believe the ListNode check here is to handle constructs like The problem with this code for the current bug is that DRegexp's superclass, DNode, extends ListNode. That causes all dynamic string constructs to fall into the ListNode logic, which results in them being handled via a simple equality check (since all DNodes just return their constructed object). I have a fix that special-cases DNode, but we need to review this code to be sure it's handling all when forms properly. |
This is a gross fix, and we need to reexamine this code. It will be a fix for #2423 in the interim.
I have committed a fix based on my description above. With it, rails apps generate correctly, without the ".tt" files. Still to do for this bug:
|
@craigmcnamara If possible, you could try out a local build of jruby-head with this fix and confirm it runs green with your patch in place. I am pretty sure it will be good. When travis goes green jruby-head will be updated to the latest rev. |
Travis build for the fix: https://travis-ci.org/jruby/jruby/builds/45915597 |
I just started one for compass-rails: https://travis-ci.org/Compass/compass-rails/builds/45916037 |
jruby-head is probably not going to be updated by the time that build hits it...but if the build I linked goes green (I'll monitor it for a while) you should be able to restart the other build and pick up new jruby-head. (When builds of JRuby's master branch are green in Travis, Travis updates their build for "jruby-head") |
I thought I was wishful thinking, I can do one locally if you can tell me which of these versions I should ask ruby-build for. jruby-9.0.0.0-dev |
The ruby-build binaries are built nightly...and I don't think we're due for another build for at least a couple hours :-) The world just doesn't move fast enough for us, does it? The travis build is about 2/3 done, so I'll monitor it until it completes. Then you should have an updated travis jruby-head. |
So this is pretty awesome: https://travis-ci.org/Compass/compass-rails/builds/45918791 |
Good catch and fix. This needs more thorough tests indeed. So, reopening so we don't forget. |
I have added specs for the following cases:
I believe this should cover all paths through the associated logic in IRBuilder. I'm going to be exploring coverage tools today so we are more likely to avoide these testing gaps in the future. |
It looks like under JRuby for Rails 3.2, 4.0 and 4.2 the default assets aren't being created when
rails new
is called. The strange thing is everything works for Rails 3.1 and the failure is only on JRuby. I originally thought that it was a FileUtils issue, but it seems that it's more likely a JRuby/Rails issue.So the build that illustrates this is here: https://travis-ci.org/Compass/compass-rails/builds/45890747
The commit that makes it happen is here: https://github.com/Compass/compass-rails/compare/investigate-jruby-test-bug
The text was updated successfully, but these errors were encountered: