[ap4r-devel] [279] branches/200709_gihyo/async_shop: Add test support including asynchronous processing.

shino at rubyforge.org shino at rubyforge.org
Wed Aug 29 23:59:02 EDT 2007


Revision: 279
Author:   shino
Date:     2007-08-29 23:59:01 -0400 (Wed, 29 Aug 2007)

Log Message:
-----------
Add test support including asynchronous processing.
Now Rails and AP4R servers should be started manually.

Modified Paths:
--------------
    branches/200709_gihyo/async_shop/as_rails/vendor/plugins/ap4r/tasks/ap4r.rake

Added Paths:
-----------
    branches/200709_gihyo/async_shop/as_ap4r/config/queues_test.cfg
    branches/200709_gihyo/async_shop/as_rails/config/test_async.yml
    branches/200709_gihyo/async_shop/as_rails/test/async/
    branches/200709_gihyo/async_shop/as_rails/test/async/ap4r_test_helper.rb
    branches/200709_gihyo/async_shop/as_rails/test/async/async_shop_test.rb
    branches/200709_gihyo/async_shop/as_rails/vendor/plugins/ap4r/lib/ap4r/service_handler.rb

Property Changed:
----------------
    branches/200709_gihyo/async_shop/as_ap4r/log/

Added: branches/200709_gihyo/async_shop/as_ap4r/config/queues_test.cfg
===================================================================
--- branches/200709_gihyo/async_shop/as_ap4r/config/queues_test.cfg	                        (rev 0)
+++ branches/200709_gihyo/async_shop/as_ap4r/config/queues_test.cfg	2007-08-30 03:59:01 UTC (rev 279)
@@ -0,0 +1,19 @@
+--- 
+store: 
+  type: mysql
+  host: localhost
+  database: ap4r
+  username: ap4r
+  password: ap4r
+drb: 
+  host: 
+  port: 6438
+  acl: allow 127.0.0.1 allow ::1
+dispatchers:
+  -
+    targets: queue.*
+    threads: 1
+#carriers:
+#  - 
+#    source_uri: druby://another.host.local:6438
+#    threads: 1


Property changes on: branches/200709_gihyo/async_shop/as_ap4r/log
___________________________________________________________________
Name: svn:ignore
   + *


Added: branches/200709_gihyo/async_shop/as_rails/config/test_async.yml
===================================================================
--- branches/200709_gihyo/async_shop/as_rails/config/test_async.yml	                        (rev 0)
+++ branches/200709_gihyo/async_shop/as_rails/config/test_async.yml	2007-08-30 03:59:01 UTC (rev 279)
@@ -0,0 +1,7 @@
+---
+ap4r:
+  root_dir: ../as_ap4r
+  config_file: config/queues_test.cfg
+  start_ruby_args: -I ~/d/ap4r-core-trunk/lib
+  stop_ruby_args: -I ~/d/ap4r-core-trunk/lib
+rails:

Added: branches/200709_gihyo/async_shop/as_rails/test/async/ap4r_test_helper.rb
===================================================================
--- branches/200709_gihyo/async_shop/as_rails/test/async/ap4r_test_helper.rb	                        (rev 0)
+++ branches/200709_gihyo/async_shop/as_rails/test/async/ap4r_test_helper.rb	2007-08-30 03:59:01 UTC (rev 279)
@@ -0,0 +1,38 @@
+# Author:: Shunichi Shinohara
+# Copyright:: Copyright (c) 2007 Future Architect Inc.
+# Licence:: MIT Licence
+
+ENV["RAILS_ENV"] = "test"
+require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
+require "ap4r/service_handler.rb"
+
+ap4r_test_helper = Ap4rTestHelper.new
+# ap4r_test_helper.start_rails_service
+# at_exit { ap4r_test_helper.stop_rails_service }
+
+# ap4r_test_helper.start_ap4r_service
+# at_exit { ap4r_test_helper.stop_ap4r_service }
+
+# puts
+# at_exit { puts }
+
+# Test::Unit also use at_exit hook, so load at the end
+require 'test_help'
+
+class Test::Unit::TestCase
+  self.use_transactional_fixtures = false
+  self.use_instantiated_fixtures  = false
+
+  # Add more helper methods to be used by all tests here...
+  cattr_accessor :ap4r_helper
+
+  def ap4r_helper
+    @@ap4r_helper
+  end
+
+  def with_services(&block)
+    ap4r_helper.with_services(&block)
+  end
+end
+
+Test::Unit::TestCase.ap4r_helper = ap4r_test_helper

Added: branches/200709_gihyo/async_shop/as_rails/test/async/async_shop_test.rb
===================================================================
--- branches/200709_gihyo/async_shop/as_rails/test/async/async_shop_test.rb	                        (rev 0)
+++ branches/200709_gihyo/async_shop/as_rails/test/async/async_shop_test.rb	2007-08-30 03:59:01 UTC (rev 279)
@@ -0,0 +1,49 @@
+require "#{File.dirname(__FILE__)}/ap4r_test_helper"
+
+require 'net/http'
+
+# Test cases with ap4r integration.
+# some comments:
+# - Clearance of data in a database and queues should be included.
+# - Workspaces of ap4r and rails should have some conventions for convinience.
+# - Think about transition to RSpec.
+# - HTTP session holding support is needed?
+class AsyncShopTest < Test::Unit::TestCase
+
+  def test_http_dispatch
+    ap4r_helper.stop_dispatchers
+
+    assert_rows_added(Order, 1) {
+      do_order
+    }
+
+    assert_rows_added(Payment, 1) {
+      ap4r_helper.start_dispatchers
+      ap4r_helper.wait_all_done
+    }
+
+  end
+
+  def test_just_fail
+    assert false
+  end
+
+  private
+
+  # Requests to <tt>async_shop/order</tt>.
+  def do_order(item_name = "test item")
+    Net::HTTP.start("localhost", 3000, nil, nil) do |http|
+      http.request_post("/async_shop/order",
+                        "order[item]=#{item_name}") do |res|
+        #nop
+      end
+    end
+  end
+
+  def assert_rows_added(model, rows)
+    rows_before = model.count
+    yield
+    rows_after = model.count
+    assert_equal rows, rows_after - rows_before, "table '#{model.table_name}' should count up by #{rows}"
+  end
+end

Added: branches/200709_gihyo/async_shop/as_rails/vendor/plugins/ap4r/lib/ap4r/service_handler.rb
===================================================================
--- branches/200709_gihyo/async_shop/as_rails/vendor/plugins/ap4r/lib/ap4r/service_handler.rb	                        (rev 0)
+++ branches/200709_gihyo/async_shop/as_rails/vendor/plugins/ap4r/lib/ap4r/service_handler.rb	2007-08-30 03:59:01 UTC (rev 279)
@@ -0,0 +1,161 @@
+# Author:: Shunichi Shinohara
+# Copyright:: Copyright (c) 2007 Future Architect Inc.
+# Licence:: MIT Licence
+
+require 'erb'
+require 'yaml'
+require 'reliable-msg'
+require 'ap4r'
+
+class Ap4rTestHelper
+
+  def initialize(config_file = RAILS_ROOT + "/config/test_async.yml")
+    raise "please create config/async_test.yml to configure ap4r service." unless File.exist?(config_file)
+
+    config = {}
+    File.open(config_file, "r") do |input|
+      YAML.load_documents(ERB.new(input.read).result) do |doc|
+        config.merge! doc
+      end
+    end
+    @test_config = config["ap4r"]
+    @root_dir = @test_config["root_dir"]
+    @config_file = @test_config["config_file"]
+    @test_server_config = ReliableMsg::Config.new(File.join(@root_dir, @config_file))
+    raise "config file #{@test_server_config.path} NOT exist!" unless @test_server_config.exist?
+
+    @test_server_config.load_no_create
+    @qm = nil
+  end
+
+  def qm
+    @qm ||= DRbObject.new_with_uri("druby://localhost:#{@test_server_config.drb["port"]}")
+  end
+
+  # Starts ap4r service.
+  def start_ap4r_service(wait_until_started = true)
+    command = "ruby #{@test_config["start_ruby_args"]} #{@root_dir}/script/mongrel_ap4r " +
+      "start -d -c #{@root_dir} -A #{@config_file} -p 13038"
+    message = "Starting Mongrel(AP4R)"
+    execute_command(command, message, false)
+    if wait_until_started
+      print "and waiting..."
+      wait_until_alive
+    end
+    puts "Done."
+  end
+
+  # Stops ap4r service.
+  def stop_ap4r_service
+    command = "ruby #{@test_config["stop_ruby_args"]} #{@root_dir}/script/mongrel_ap4r " +
+      "stop -c #{@root_dir}"
+    message = "Terminating Mongrel(AP4R)"
+    execute_command(command, message, false)
+    @qm = nil
+  end
+
+  # Starts rails service.
+  # Invokes mongrel_rails, so mongrel_rails should be installed.
+  def start_rails_service
+    # TODO: Can use script/server? It's more general. 2007/05/31 by shino
+    command = "mongrel_rails start -d --environment test"
+    message = "Starting Mongrel(Rails)"
+    execute_command(command, message)
+  end
+
+  require 'timeout'
+  # Stops rails service.
+  def stop_rails_service
+#     puts "read pid"
+#     pid = File.read('log/mongrel.pid').to_i
+#     puts "send signal to #{pid}"
+#     Process.kill(:TERM, `cat log/mongrel.pid`.to_i)
+#     puts "done"
+#     return
+    command = "mongrel_rails stop"
+#    command = "kill " + `cat log/mongrel.pid`
+    command = "sh -c 'mongrel_rails stop'"
+    message = "Terminating Mongrel(Rails)"
+    begin
+      timeout(5) do
+        execute_command(command, message, false)
+      end
+    rescue TimeoutError
+      puts "!!! command timed out !!!"
+    end
+  end
+
+  # Starts rails service and ap4r service.
+  # After block execution, stops both.
+  def with_services
+    begin
+      start_rails_service
+      begin
+        start_ap4r_service
+        yield
+      ensure
+        stop_ap4r_service
+      end
+    ensure
+      stop_rails_service
+    end
+  end
+
+  def start_dispatchers
+    qm.dispatchers.start
+  end
+
+  def stop_dispatchers
+    qm.dispatchers.stop
+  end
+
+  def clear(*queues)
+    raise "not yet implemented"
+    queues.each do |queue|
+      q = ReliableMsg::Queue.new(queue)
+      loop do
+        break unless q.get
+      end
+    end
+  end
+
+  def wait_for_saf_forward
+    50.times do
+      count = ::Ap4r::StoredMessage.count(:conditions => {:status => ::Ap4r::StoredMessage::STATUS_STORED})
+      break if count == 0
+      sleep 0.2
+    end
+  end
+
+  def wait_all_done
+    50.times do
+      break if flag = qm.no_active_message?
+      sleep 0.2
+    end
+  end
+
+  def dlq
+    qm.list :queue => "$dlq"
+  end
+
+  private
+  def execute_command(command, message, with_done_message = true)
+#    print "#{message} with command: #{command}..."
+    result = system(command, "")
+    # TODO: handle result 2007/08/29 by shino
+    puts "Done." if with_done_message
+  end
+
+  def wait_until_alive(message = nil)
+    50.times do
+      print message if message
+      begin
+        break if qm.alive?
+      rescue => e
+        # ignore
+      end
+      sleep 0.2
+    end
+  end
+
+end

Modified: branches/200709_gihyo/async_shop/as_rails/vendor/plugins/ap4r/tasks/ap4r.rake
===================================================================
--- branches/200709_gihyo/async_shop/as_rails/vendor/plugins/ap4r/tasks/ap4r.rake	2007-08-30 02:01:26 UTC (rev 278)
+++ branches/200709_gihyo/async_shop/as_rails/vendor/plugins/ap4r/tasks/ap4r.rake	2007-08-30 03:59:01 UTC (rev 279)
@@ -1,8 +1,23 @@
 namespace :test do
-  Rake::TestTask.new(:async => "db:test:prepare") do |t|
-    t.libs << "test"
-    t.pattern = 'test/async/**/*_test.rb'
-    t.verbose = true
+
+#  task :asyncs do
+#    setup - run - teardown comes here.
+#    Names should be considered further.
+#  end
+
+  namespace :asyncs do
+    desc "Start Rails and AP4R servers to test:asyncs:exec"
+    task :setup do |t|
+      puts "setup task should be implemented here"
+    end
+
+    Rake::TestTask.new(:run => "db:test:prepare") do |t|
+      t.libs << "test"
+      t.pattern = 'test/async/**/*_test.rb'
+      t.verbose = true
+    end
+    Rake::Task['test:asyncs:run'].comment = "Run the unit tests in test/async"
+
   end
-  Rake::Task['test:async'].comment = "Run the unit tests in test/async"
+
 end




More information about the ap4r-devel mailing list