Maven migration (first draft)

This commit is contained in:
Graham Triggs 2015-11-19 23:47:41 +00:00
parent da79ac3e1d
commit fee48b0b50
1711 changed files with 662 additions and 0 deletions

View file

@ -0,0 +1,33 @@
#
# The path to the LoadTesting directory. Everything is based on this
#
@home = File.expand_path("../..", File.dirname(__FILE__))
#
# 'require' should look in the scripts directory
#
$: << File.expand_path('scripts', @home)
#
# convenience methods to access files
#
def version_file(path)
"#{@home}/versions/#{@version_name}/#{path}"
end
def distro_file(path)
"#{@home}/distros/#{@distro_name}/#{path}"
end
def site_file(path)
"#{@home}/sites/#{@site_name}/#{path}"
end
def test_file(path)
"#{@home}/testinfo/#{path}"
end
#
# All of the scripts need to load these parms. (Except _setVersion and _setTest)
#
require 'subscripts/loadParms'

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -0,0 +1,6 @@
require 'subscripts/_current_version'
require 'subscripts/_current_test'
require version_file('version_properties')
require distro_file('distro_properties')
require site_file('site_properties')

View file

@ -0,0 +1,39 @@
=begin
--------------------------------------------------------------------------------
A utility class that reads a properties file and returns a hash containing the
properties.
--------------------------------------------------------------------------------
=end
class PropertyFileReader
# Read a properties file and return a hash.
#
# Parameters: the path to the properties file
#
# The hash includes the special property "properties_file_path", which holds
# the path to the properties file.
#
def self.read(file_path)
properties = {}
properties["properties_file_path"] = File.expand_path(file_path)
File.open(file_path) do |file|
file.each_line do |line|
line.strip!
if line.length == 0 || line[0] == ?# || line[0] == ?!
# ignore blank lines, and lines starting with '#' or '!'.
elsif line =~ /(.*?)\s*[=:]\s*(.*)/
# key and value are separated by '=' or ':' and optional whitespace.
properties[$1.strip] = $2
else
# No '=' or ':' means that the value is empty.
properties[line] = ''
end
end
end
return properties
end
end

View file

@ -0,0 +1,102 @@
#! /usr/bin/ruby
=begin
--------------------------------------------------------------------------------
Parse a file of JMeter test results (*./jtl), summarize the times for each test,
and make the summaries easily available.
--------------------------------------------------------------------------------
=end
require "rexml/document"
include REXML
# ------------------------------------------------------------------------------------
# TestResultSummary class
# ------------------------------------------------------------------------------------
class TestResultSummary
attr_reader :label
attr_reader :how_many
attr_reader :failures
attr_reader :min_time
attr_reader :max_time
attr_reader :avg_time
def addResult(result_element)
@how_many += 1
@failures += 1 unless result_element.attributes["s"] == "true"
time = result_element.attributes["t"].to_i
@total_time += time
@min_time = [@min_time, time].min
@max_time = [@max_time, time].max
@avg_time = @total_time / how_many
end
def initialize(result_element)
@label = result_element.attributes["lb"]
@how_many = 0
@failures = 0
@min_time = 100000000
@max_time = 0
@total_time = 0
addResult(result_element)
end
end
# ------------------------------------------------------------------------------------
# TestResultFile class
# ------------------------------------------------------------------------------------
class TestResultFile
attr_reader :filename
attr_reader :timestamp
attr_reader :summaries
attr_reader :version
def parse_result_file()
@summaries = {}
@version = "_"
file = File.new( @file_path )
doc = Document.new file
XPath.each(doc, "/testResults/httpSample") do | result |
test_label = result.attributes["lb"]
if @summaries[test_label] == nil
@summaries[test_label] = TestResultSummary.new(result)
else
@summaries[test_label].addResult(result)
end
end
XPath.each(doc, "version") do | version |
@version = version.attributes["name"]
end
end
def initialize(filename, source_directory)
raise("filename must not be nil") if filename == nil
raise("source_directory must not be nil") if source_directory == nil
@filename = filename
@source_directory = source_directory
if !File.directory?(@source_directory)
raise "Directory does not exist: '#{@source_directory}'."
end
@file_path = File.expand_path(filename + ".jtl", @source_directory)
if !File.file?(@file_path)
raise "File doesn't exist: '#{@file_path}'."
end
@timestamp = File.mtime(@file_path)
parse_result_file()
end
end

View file

@ -0,0 +1,161 @@
#! /usr/bin/ruby
=begin
--------------------------------------------------------------------------------
Parse a file of JMeter test results (*./jtl), summarize the times for each test,
and make the summaries easily available.
--------------------------------------------------------------------------------
=end
# ------------------------------------------------------------------------------------
# TestResultMarshaller class
# ------------------------------------------------------------------------------------
class TestResultMarshaller
def marshall()
File.open(@output_filename, 'w') do | out |
write_html_header(out)
write_table_header(out)
write_table_lines(out)
write_table_footer(out)
write_html_footer(out)
end
end
def write_html_header(out)
out.puts <<"EOF"
<html>
<head>
<link REL='STYLESHEET' TYPE='text/css' HREF='./mergedResults.css'>
<title>Performance tests for #{@site_name}</title>
</head>
<body>
EOF
end
def write_table_header(out)
top_cells = ['<th>&nbsp</th>']
@test_results.each do | test |
top_cells.push("<th colspan='3'>#{test.version}<br/>#{test.filename}<br/>#{test.timestamp.strftime('%Y-%m-%d %H:%M:%S')}</th>")
end
bottom_cells = ['<th>Test Name</th>']
@test_results.each do | test |
bottom_cells.push('<th>Iterations</th>')
bottom_cells.push('<th>time<br/>(min/max)</th>')
bottom_cells.push("<th>compare</th>")
end
out.puts <<"EOF"
<table class='testData' cellspacing='0'>
<tr>
#{top_cells.join("\n ")}
</tr>
<tr>
#{bottom_cells.join("\n ")}
</tr>
EOF
end
def write_table_lines(out)
all_test_names().each do | test_name |
out.puts <<"EOF"
<tr>
<td class='left'>#{test_name}</td>
#{format_test_results(test_name)}
</tr>
EOF
end
end
def all_test_names
names = []
@test_results.each do | test |
names.concat(test.summaries.keys)
end
names.uniq.sort
end
def format_test_results(test_name)
results = []
@test_results.each do | test |
results.push(format_test_result(test_name, test))
end
results.join("\n ")
end
def format_test_result(test_name, test)
s = test.summaries[test_name]
if s
<<"EOF"
<td class='open'>#{s.how_many}</td>
<td>
<table class='oneResult close' cellspacing='0'>
<tr>
<td rowspan='2'>#{format_millis(s.avg_time)}</td>
<td class='minmax'>#{format_millis(s.min_time)}</td>
</tr>
<tr>
<td class='minmax'>#{format_millis(s.max_time)}</td>
</tr>
</table>
</td>
<td>#{performance_ratio(test_name, s.avg_time)}</td>
EOF
else
<<"EOF"
<td class='open'>&nbsp;</td>
<td>
<table class='oneResult close' cellspacing='0'>
<tr>
<td rowspan='2'>&nbsp;</td>
<td class='minmax'>&nbsp;</td>
</tr>
<tr>
<td class='minmax'>&nbsp;</td>
</tr>
</table>
</td>
<td>&nbsp;</td>
EOF
end
end
def format_millis(millis)
"%.3f" % [millis.to_f / 1000]
end
def performance_ratio(test_name, time)
return "&nbsp;" if @test_results.empty?
return "&nbsp;" unless @test_results[0].summaries.key?(test_name)
s = @test_results[0].summaries[test_name]
reference = s.avg_time
return "&nbsp;" if reference == 0
return "#{"%.0f" % [time * 100 / reference]}%"
end
def write_table_footer(out)
out.puts "</table>"
end
def write_html_footer(out)
out.puts <<"EOF"
</body>
</html>
EOF
end
def initialize(target_directory, site_name, test_results)
@target_directory = target_directory
@site_name = site_name
@test_results = test_results
filename = "#{site_name}-merged_#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}"
@output_filename = File.expand_path(filename, @target_directory)
end
end

View file

@ -0,0 +1,96 @@
#! /usr/bin/ruby
=begin
--------------------------------------------------------------------------------
Look through a directory of test results files (*.jtl), and produce an HTML file
that summarizes, merges, and compares the information.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
=end
$: << File.dirname(File.expand_path(__FILE__))
require 'test_result_file'
require 'test_result_marshaller'
# ------------------------------------------------------------------------------------
# TestResultMerger class
# ------------------------------------------------------------------------------------
class TestResultMerger
#
# Do we have any chance of succeeding with these properties?
#
def sanity_checks_on_properties()
raise("Properties must contain a value for 'source_directory'") if @source_directory == nil
raise("Properties must contain a value for 'target_directory'") if @target_directory == nil
raise("Properties must contain a value for 'site_name'") if @site_name == nil
if !File.directory?(@source_directory)
raise "Not a directory: '#{@source_directory}'."
end
if !File.directory?(@target_directory)
raise "Not a directory: '#{@target_directory}'."
end
end
def parse_files()
test_result_files = build_file_list()
@test_results = []
test_result_files.each() do | test_result_file |
puts "Parsing #{test_result_file}"
@test_results.push(TestResultFile.new(test_result_file, @source_directory))
end
end
def build_file_list
existing_files = []
Dir.foreach(@source_directory) do | filename |
next unless File.extname(filename) == ".jtl"
existing_files.push(File.basename(filename, ".jtl"))
end
puts "BOGUS existing files = [#{existing_files.join(', ')}]"
file_list = []
@file_order_suggestions.each() do | suggestion|
if existing_files.include?(suggestion)
file_list.push(suggestion)
existing_files.delete(suggestion)
end
end
file_list.concat(existing_files)
puts "BOGUS file list = [#{file_list.join(', ')}]"
return file_list
end
def marshall()
marshaller = TestResultMarshaller.new(@target_directory, @site_name, @test_results)
marshaller.marshall()
end
def initialize(properties)
@source_directory = properties['source_directory']
@target_directory = properties['target_directory']
@site_name = properties['site_name']
@file_order_suggestions = properties['file_order_suggestions']
puts "source_directory = #{@source_directory}"
puts "target_directory = #{@target_directory}"
puts "site_name = #{@site_name}"
if (@file_order_suggestions == nil)
puts "file_order_suggestions = nil"
else
puts "file_order_suggestions = [#{@file_order_suggestions.join(', ')}]"
end
sanity_checks_on_properties
end
def merge()
parse_files()
marshall()
end
end

View file

@ -0,0 +1,246 @@
#! /usr/bin/ruby
=begin
--------------------------------------------------------------------------------
Take a file that MySQL produced listing the URIs and filenames of all expected
upload files. Scan through the uploads directory, creating such files wherever
they are needed.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
=end
$: << File.dirname(File.expand_path(__FILE__))
require 'date'
require 'fileutils'
require 'property_file_reader'
# ------------------------------------------------------------------------------------
# FileInfoFile class
# ------------------------------------------------------------------------------------
class FileInfoFile
attr_reader :default_namespace
attr_reader :data
def parse_info_line(line)
# Lines are in this form: "URI","filename"
match = line.match(/^"([^"]*)","([^"]*)"$/)
raise "Can't parse this line: '#{line}'" if !match
return match.captures[0], match.captures[1]
end
def parse_default_namespace(uri)
match = /^(.*)individual/.match(uri)
raise "Can't find default namespace: '#{uri}'" if match == nil
"#{match.captures[0]}individual/"
end
public
def initialize(filepath)
@data = []
File.open(filepath) do |f|
f.each() do |line|
@data.push(parse_info_line(line))
end
end
puts "parsed #{@data.length} lines."
@default_namespace = parse_default_namespace(@data[0][0])
puts "default namespace is '#{@default_namespace}'"
end
end
# ------------------------------------------------------------------------------------
# NamespacesFile class
#
# Read, query, modify and write the namespace-prefixes file.
# ------------------------------------------------------------------------------------
class NamespacesFile
NAMESPACES_FILENAME = 'file_storage_namespaces.properties'
public
def initialize(uploads_directory, scan_only)
@uploads_directory = uploads_directory
@scan_only = scan_only
Dir.chdir(@uploads_directory) do |dir|
@namespaces = {}
if File.file?(NAMESPACES_FILENAME)
@namespaces = PropertyFileReader.read(NAMESPACES_FILENAME)
@namespaces.delete("properties_file_path")
end
end
end
def add_namespace(namespace)
if @namespaces.has_value?(namespace)
puts "found prefix for #{namespace}"
return
end
'abcdefghijklmnopqrstuvwxyz'.split("").each do |this_char|
if (!@namespaces.has_key?(this_char))
@namespaces[this_char] = namespace
puts "assigned prefix = '#{this_char}'"
return
end
end
raise "all prefixes are used!"
end
def prefix(namespace)
@namespaces.each() do | key, value |
return key if value == namespace
end
raise "no prefix for '#{namespace}'"
end
def write()
if @scan_only
puts "Scan-only: not writing namespaces file"
else
Dir.chdir(@uploads_directory) do |dir|
File.open(NAMESPACES_FILENAME, "w") do |f|
@namespaces.each do |prefix, namespace|
f.puts "#{prefix} = #{namespace}"
end
end
end
end
end
end
# ------------------------------------------------------------------------------------
# Main class - UploadFileFaker
# ------------------------------------------------------------------------------------
class UploadFileFaker
#
# Do we have any chance of succeeding with these properties?
#
def sanity_checks_on_properties()
raise("Properties file must contain a value for 'uploads_directory'") if @uploads_directory == nil
raise("Properties file must contain a value for 'file_info_file'") if @file_info_file == nil
raise("Properties file must contain a value for 'template_file'") if @template_file == nil
if !File.directory?(@uploads_directory)
raise "Not a directory: '#{@uploads_directory}'."
end
if !File.file?(@file_info_file)
raise "File does not exist: '#{@file_info_file}'."
end
if !File.file?(@template_file)
raise "File does not exist: '#{@template_file}'."
end
end
#
# Check each location that should contain an image, and if we're not just
# scanning, put one there.
#
def create_image_files_where_needed()
@file_info.data.each do |line|
uri, filename = line
process_file_info(uri, filename)
end
end
def process_file_info(uri, filename)
full_path = figure_full_path(uri, filename)
if File.file?(full_path)
puts "File already exists at: '#{full_path}'"
elsif @scan_only
puts "Scan only - no file at: '#{full_path}'"
else
puts "Creating file at: '#{full_path}'"
FileUtils.mkpath(File.dirname(full_path))
FileUtils.cp(@template_file, full_path)
end
end
def figure_full_path(uri, filename)
prefixed_uri = substitute_prefix_for_namespace(uri)
construct_full_path(prefixed_uri, filename)
end
def substitute_prefix_for_namespace(uri)
if uri[0, @namespace.length] == @namespace
uri.sub(@namespace, "#{@prefix}~")
else
raise "Doesn't start with default namespace: '#{uri}'"
end
end
def construct_full_path(prefixed_uri, filename)
path = ""
0.step(prefixed_uri.size - 1, 3) do |i|
path = "#{path}/#{prefixed_uri[i, 3]}"
end
"#{@uploads_directory}/file_storage_root#{path}/#{filename}"
end
public
#
# Setup and get ready to process.
#
# properties is a map of keys to values, probably parsed from a properties file.
#
def initialize(properties)
scan_only_string = properties['scan_only']
@scan_only = 'false' != scan_only_string
@uploads_directory = properties['uploads_directory']
@file_info_file = properties['file_info_file']
@template_file = properties['template_file']
sanity_checks_on_properties()
end
#
# Start the scanning (and copying).
#
def process()
@file_info = FileInfoFile.new(@file_info_file)
@namespace = @file_info.default_namespace
namespaces_file = NamespacesFile.new(@uploads_directory, @scan_only)
namespaces_file.add_namespace(@namespace)
namespaces_file.write()
@prefix = namespaces_file.prefix(@namespace)
create_image_files_where_needed()
end
end
#
# ------------------------------------------------------------------------------------
# Standalone calling.
#
# Do this if this program was called from the command line. That is, if the command
# expands to the path of this file.
# ------------------------------------------------------------------------------------
#
if File.expand_path($0) == File.expand_path(__FILE__)
if ARGV.length == 0
raise("No arguments - usage is: UploadFileFaker.rb <property_file>")
end
if !File.file?(ARGV[0])
raise "File does not exist: '#{ARGV[0]}'."
end
properties = PropertyFileReader.read(ARGV[0])
uff = UploadFileFaker.new(properties)
uff.process
puts "UploadFileFaker was successful."
end