about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2013-10-19 01:30:53 +0000
committerEric Wong <e@80x24.org>2013-10-19 01:38:06 +0000
commitf89ee896e14bfa97179f3773d303dd0a1bdcf971 (patch)
treeaee7898b68b952470d933da253b72eb4231dee9a
parent8405eb8c49196b626dfdc747be4a3b91d530074a (diff)
downloadyahns-f89ee896e14bfa97179f3773d303dd0a1bdcf971.tar.gz
flock works on file handles (which are shared across processes).
So our use of flock on a global constant was not fork safe as the
same file handle would share locks between the client/parent
process.  Since we have to create/truncate the coverage.dump file in
the Makefile before any tests run anyways, we can just lazily open
the file handle when we need to use it, and never before.
-rw-r--r--test/helper.rb49
1 files changed, 26 insertions, 23 deletions
diff --git a/test/helper.rb b/test/helper.rb
index ab9a04f..896377f 100644
--- a/test/helper.rb
+++ b/test/helper.rb
@@ -11,38 +11,41 @@ GTL = Mutex.new
 if ENV["COVERAGE"]
   require "coverage"
   COVMATCH = %r{/lib/yahns\b.*rb\z}
-  COVTMP = File.open("coverage.dump", IO::CREAT|IO::RDWR)
-  COVTMP.binmode
-  COVTMP.sync = true
 
   def __covmerge
     res = Coverage.result
 
-    # we own this file (at least until somebody tries to use NFS :x)
-    COVTMP.flock(File::LOCK_EX)
-
-    COVTMP.rewind
-    prev = COVTMP.read
-    prev = prev.empty? ? {} : Marshal.load(prev)
-    res.each do |filename, counts|
-      # filter out stuff that's not in our project
-      COVMATCH =~ filename or next
-
-      merge = prev[filename] || []
-      merge = merge
-      counts.each_with_index do |count, i|
-        count or next
-        merge[i] = (merge[i] || 0) + count
+    # do not create the file, Makefile does htis before any tests run
+    File.open("coverage.dump", IO::RDWR) do |covtmp|
+      covtmp.binmode
+      covtmp.sync = true
+
+      # we own this file (at least until somebody tries to use NFS :x)
+      covtmp.flock(File::LOCK_EX)
+
+      prev = covtmp.read
+      prev = prev.empty? ? {} : Marshal.load(prev)
+      res.each do |filename, counts|
+        # filter out stuff that's not in our project
+        COVMATCH =~ filename or next
+
+        merge = prev[filename] || []
+        merge = merge
+        counts.each_with_index do |count, i|
+          count or next
+          merge[i] = (merge[i] || 0) + count
+        end
+        prev[filename] = merge
       end
-      prev[filename] = merge
+      covtmp.rewind
+      covtmp.truncate(0)
+      covtmp.write(Marshal.dump(prev))
+      covtmp.flock(File::LOCK_UN)
     end
-    COVTMP.rewind
-    COVTMP.truncate(0)
-    COVTMP.write(Marshal.dump(prev))
-    COVTMP.flock(File::LOCK_UN)
   end
 
   Coverage.start
+  # we need to nest at_exit to fire after minitest runs
   at_exit { at_exit { __covmerge } }
 end