[Groonga-commit] groonga/groonga-query-log at 039d6a5 [master] Add groonga-query-log-run-regression-test

Back to archive index

Kouhei Sutou null+****@clear*****
Wed May 7 17:39:50 JST 2014


Kouhei Sutou	2014-05-07 17:39:50 +0900 (Wed, 07 May 2014)

  New Revision: 039d6a5948c66bb2fffbc581cbefdd79638d763b
  https://github.com/groonga/groonga-query-log/commit/039d6a5948c66bb2fffbc581cbefdd79638d763b

  Message:
    Add groonga-query-log-run-regression-test
    
    It is not tried yet.

  Added files:
    bin/groonga-query-log-run-regression-test
    lib/groonga/query-log/command/run-regression-test.rb

  Added: bin/groonga-query-log-run-regression-test (+23 -0) 100755
===================================================================
--- /dev/null
+++ bin/groonga-query-log-run-regression-test    2014-05-07 17:39:50 +0900 (c4db8d5)
@@ -0,0 +1,23 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2014  Kouhei Sutou <kou �� clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+require "groonga/query-log/command/run-regression-test"
+
+command = Groonga::QueryLog::Command::RunRegressionTest.new
+command.run(*ARGV)

  Added: lib/groonga/query-log/command/run-regression-test.rb (+343 -0) 100644
===================================================================
--- /dev/null
+++ lib/groonga/query-log/command/run-regression-test.rb    2014-05-07 17:39:50 +0900 (8eaf04e)
@@ -0,0 +1,343 @@
+# Copyright (C) 2014  Kouhei Sutou <kou �� clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+require "rbconfig"
+require "optparse"
+require "socket"
+require "pathname"
+require "net/http"
+
+require "groonga/query-log"
+require "groonga/query-log/command/verify-server"
+
+module Groonga
+  module QueryLog
+    module Command
+      class RunRegressionTest
+        def initialize
+          @input_directory = Pathname.new(".")
+          @working_directory = Pathname.new(".")
+
+          @old_groonga = "groonga"
+          @old_database = "db.old/db"
+
+          @new_groonga = "groonga"
+          @new_database = "db.new/db"
+
+          @load_data = true
+          @run_queries = true
+        end
+
+        def run(*command_line)
+          option_parser = create_option_parser
+          begin
+            option_parser.parse!(*command_line)
+          rescue OptionParser::ParseError => error
+            $stderr.puts(error.message)
+            return false
+          end
+
+          tester = Tester.new(old_groonga_server,
+                              new_groonga_server,
+                              tester_options)
+          tester.run
+        end
+
+        private
+        def create_option_parser
+          parser = OptionParser.new
+          parser.version = VERSION
+
+          parser.separator("")
+          parser.separator("Path:")
+          parser.on("--input-directory=DIRECTORY",
+                    "Load schema and data from DIRECTORY.",
+                    "(#{@input_directory})") do |directory|
+            @input_directory = Pathname.new(directory)
+          end
+          parser.on("--working-directory=DIRECTORY",
+                    "Use DIRECTORY as working directory.",
+                    "(#{@working_directory})") do |directory|
+            @working_directory = Pathname.new(directory)
+          end
+
+          parser.separator("")
+
+          parser.separator("")
+          parser.separator("Old Groonga:")
+          parser.on("--old-groonga=GROONGA",
+                    "Old groonga command",
+                    "(#{@old_groonga})") do |groonga|
+            @old_groonga = groonga
+          end
+
+          parser.separator("")
+          parser.separator("New Groonga:")
+          parser.on("--new-groonga=GROONGA",
+                    "New groonga command",
+                    "(#{@new_groonga})") do |groonga|
+            @new_groonga = groonga
+          end
+
+          parser.separator("")
+          parser.separator("Operations:")
+          parser.on("--no-load-data",
+                    "Don't load data. Just loads schema to Groonga database") do
+            @load_data = false
+          end
+          parser.on("--no-run-queries",
+                    "Don't run queries. Just creates Groonga database") do
+            @run_queries = false
+          end
+
+          parser
+        end
+
+        def directory_options
+          {
+            :input_directory   => @input_directory,
+            :working_directory => @working_directory,
+          }
+        end
+
+        def server_options
+          options = {
+            :load_data   => @load_data,
+            :run_queries => @run_queries,
+          }
+          directory_options.merge(options)
+        end
+
+        def tester_options
+          directory_options
+        end
+
+        def old_groonga_server
+          GroongaServer.new(@old_groonga,
+                            @old_database,
+                            server_options)
+        end
+
+        def new_groonga_server
+          GroongaServer.new(@new_groonga,
+                            @new_database,
+                            server_options)
+        end
+
+        class GroongaServer
+          attr_reader :host, :port
+          def initialize(groonga, database_path, options)
+            @input_directory = options[:input_directory] || Pathname.new(".")
+            @working_directory = options[:working_directory] || Pathname.new(".")
+            @groonga = groonga
+            @database_path = @working_directory + database_path
+            @host = "127.0.0.1"
+            @port = find_unused_port
+            @options = options
+          end
+
+          def run
+            ensure_database
+            return unless @options[:run_queries]
+
+            @pid = spawn(@groonga,
+                         "--bind-address", @host,
+                         "--port", @port.to_s,
+                         "--log-path", log_path.to_s,
+                         "--query-log-path", query_log_path.to_s,
+                         "--protocol", "http",
+                         "-s",
+                         @database_path.to_s)
+
+            n_retries = 10
+            begin
+              send_command("status")
+            rescue SystemCallError
+              sleep(1)
+              n_retries -= 1
+              raise if n_retries.zero?
+              retry
+            end
+
+            yield
+          end
+
+          def shutdown
+            begin
+              send_command("shutdown")
+            rescue SystemCallError
+            end
+            Process.waitpid(@pid)
+          end
+
+          private
+          def find_unused_port
+            server = TCPServer.new(@host, 0)
+            begin
+              server.addr[1]
+            ensure
+              server.close
+            end
+          end
+
+          def log_path
+            @database_path.dirname + "groonga.log"
+          end
+
+          def query_log_path
+            @database_path.dirname + "query.log"
+          end
+
+          def ensure_database
+            return if @database_path.exist?
+            FileUtils.mkdir_p(@database_path.dirname.to_s)
+            system(@groonga, "-n", @database_path.to_s, "quit")
+            grn_files.each do |grn_file|
+              command = [@groonga, @database_path.to_s]
+              command_line = "#{command.join(' ')} < #{grn_file}"
+              puts("Running...: #{command_line}")
+              pid = spawn(*command, :in => grn_file.to_s)
+              begin
+                pid, status = Process.waitpid2(pid)
+              rescue Interrupt
+                Process.kill(:TERM, pid)
+                pid, status = Process.waitpid2(pid)
+              end
+              unless status.success?
+                raise "Failed to run: #{command_line}"
+              end
+            end
+          end
+
+          def send_command(name)
+            Net::HTTP.start(@host, @port) do |http|
+              response = http.get("/d/#{name}")
+              response.body
+            end
+          end
+
+          def grn_files
+            files = schema_files
+            files += data_files if @options[:load_data]
+            files
+          end
+
+          def schema_files
+            Pathname.glob("#{@input_directory}/schema/**/*.grn").sort
+          end
+
+          def data_files
+            Pathname.glob("#{@input_directory}/data/**/*.grn").sort
+          end
+        end
+
+        class Tester
+          def initialize(old, new, options)
+            @old = old
+            @new = new
+            @input_directory = options[:input_directory] || Pathname.new(".")
+            @working_directory = options[:working_directory] || Pathname.new(".")
+            @options = options
+            @n_ready_waits = 2
+            @clone_pids = []
+          end
+
+          def run
+            old_thread = Thread.new do
+              @old.run do
+                run_test
+              end
+            end
+            new_thread = Thread.new do
+              @new.run do
+                run_test
+              end
+            end
+
+            old_thread.join
+            new_thread.join
+          end
+
+          private
+          def run_test
+            @n_ready_waits -= 1
+            return unless @n_ready_waits.zero?
+
+            @clone_pids.each do |pid|
+              Process.waitpid(pid)
+            end
+
+            query_log_paths.each do |query_log_path|
+              query_log_key = query_log_path.basename(".*").to_s
+              query_log_key = query_log_key.gsub(/\Aquery-/, "")
+              test_log_base_name = "test-result-#{query_log_key}.log"
+              test_log_path = @working_directory + test_log_base_name
+              if test_log_path.exist?
+                puts("Skip query log: #{query_log_path}")
+                next
+              else
+                puts("Running test against query log...: #{query_log_path}")
+              end
+              pid = fork do
+                verify_server(test_log_path, query_log_path)
+                exit!
+              end
+              begin
+                Process.waitpid(pid)
+              rescue Interrupt
+                Process.kill(:TERM, pid)
+                Process.waitpid(pid)
+              end
+            end
+
+            old_thread = Thread.new do
+              @old.shutdown
+            end
+            new_thread = Thread.new do
+              @new.shutdown
+            end
+            old_thread.join
+            new_thread.join
+
+            true
+          end
+
+          def verify_server(test_log_path, query_log_path)
+            command_line = [
+              "--n-clients=1",
+              "--groonga1-host=#{@old.host}",
+              "--groonga1-port=#{@old.port}",
+              "--groonga1-protocol=http",
+              "--groonga2-host=#{@new.host}",
+              "--groonga2-port=#{@new.port}",
+              "--groonga2-protocol=http",
+              "--target-command-name=select",
+              "--output", test_log_path.to_s,
+              "--abort-on-exception",
+              query_log_path.to_s,
+            ]
+            verify_serer = VerifyServer.new
+            verify_serer.run(*command_line)
+          end
+
+          def query_log_paths
+            Pathname.glob("#{@input_directory}/query-logs/**/*.log").sort
+          end
+        end
+      end
+    end
+  end
+end
-------------- next part --------------
HTML����������������������������...
Descargar 



More information about the Groonga-commit mailing list
Back to archive index