pg-ct 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/rake/testing.rb ADDED
@@ -0,0 +1,151 @@
1
+ #
2
+ # Rake tasklib for testing tasks
3
+
4
+ #
5
+ # Authors:
6
+ # * Michael Granger <ged@FaerieMUD.org>
7
+ #
8
+
9
+ unless defined?( COVERAGE_MINIMUM )
10
+ if ENV['COVVERAGE_MINIMUM']
11
+ COVERAGE_MINIMUM = Float( ENV['COVERAGE_MINIMUM'] )
12
+ else
13
+ COVERAGE_MINIMUM = 85.0
14
+ end
15
+ end
16
+ SPEC_FILES = [] unless defined?( SPEC_FILES )
17
+ TEST_FILES = [] unless defined?( TEST_FILES )
18
+
19
+ COMMON_RSPEC_OPTS = [] unless defined?( COMMON_RSPEC_OPTS )
20
+
21
+ COVERAGE_TARGETDIR = BASEDIR + 'coverage' unless defined?( COVERAGE_TARGETDIR )
22
+ RCOV_EXCLUDES = 'spec,tests,/Library/Ruby,/var/lib,/usr/local/lib' unless
23
+ defined?( RCOV_EXCLUDES )
24
+
25
+
26
+ desc "Run all defined tests"
27
+ task :test do
28
+ unless SPEC_FILES.empty?
29
+ log "Running specs"
30
+ Rake::Task['spec:quiet'].invoke
31
+ end
32
+
33
+ unless TEST_FILES.empty?
34
+ log "Running unit tests"
35
+ Rake::Task[:unittests].invoke
36
+ end
37
+ end
38
+
39
+
40
+ ### RSpec specifications
41
+ begin
42
+ gem 'rspec', '>= 2.0.0'
43
+
44
+ require 'rspec'
45
+ require 'rspec/core/rake_task'
46
+
47
+ ### Task: spec
48
+ desc "Run specs"
49
+ task :spec => 'spec:doc'
50
+
51
+ namespace :spec do
52
+ desc "Run rspec every time there's a change to one of the files"
53
+ task :autotest do
54
+ require 'autotest'
55
+ Autotest.add_discovery { "rspec2" }
56
+ Autotest.run
57
+ end
58
+
59
+ desc "Generate regular color 'doc' spec output"
60
+ RSpec::Core::RakeTask.new( :doc ) do |task|
61
+ task.rspec_opts = COMMON_RSPEC_OPTS + ['-f', 'd', '-c']
62
+ end
63
+
64
+ desc "Generate spec output with profiling"
65
+ RSpec::Core::RakeTask.new( :profile ) do |task|
66
+ task.rspec_opts = COMMON_RSPEC_OPTS + ['-f', 'p', '-p']
67
+ end
68
+
69
+ desc "Generate quiet non-colored plain-text output"
70
+ RSpec::Core::RakeTask.new( :quiet ) do |task|
71
+ task.rspec_opts = COMMON_RSPEC_OPTS + ['-f', 'p']
72
+ end
73
+
74
+ desc "Generate HTML output"
75
+ RSpec::Core::RakeTask.new( :html ) do |task|
76
+ task.rspec_opts = COMMON_RSPEC_OPTS + ['-f', 'h']
77
+ end
78
+
79
+
80
+ end
81
+
82
+ ### Task: coverage (via RCov)
83
+ desc "Build test coverage reports"
84
+ RSpec::Core::RakeTask.new( :coverage ) do |task|
85
+ task.ruby_opts = [ "-I#{LIBDIR}" ]
86
+ task.rspec_opts = ['-f', 'p', '-b']
87
+ task.rcov_opts = RCOV_OPTS
88
+ task.rcov = true
89
+ end
90
+
91
+ ### Task: rcov
92
+ task :rcov => :coverage
93
+
94
+ ### Other coverage tasks
95
+ namespace :coverage do
96
+ desc "Generate a detailed text coverage report"
97
+ RSpec::Core::RakeTask.new( :text ) do |task|
98
+ task.rcov_opts = RCOV_OPTS + ['--text-report']
99
+ task.rcov = true
100
+ end
101
+
102
+ desc "Show differences in coverage from last run"
103
+ RSpec::Core::RakeTask.new( :diff ) do |task|
104
+ task.rspec_opts = ['-f', 'p', '-b']
105
+ task.rcov_opts = RCOV_OPTS - ['--save'] + ['--text-coverage-diff']
106
+ task.rcov = true
107
+ end
108
+
109
+ desc "Run RCov in 'spec-only' mode to check coverage from specs"
110
+ RSpec::Core::RakeTask.new( :speconly ) do |task|
111
+ task.rcov_opts = ['--exclude', RCOV_EXCLUDES, '--text-report', '--save']
112
+ task.rcov = true
113
+ end
114
+ end
115
+
116
+ CLOBBER.include( COVERAGE_TARGETDIR )
117
+ rescue LoadError => err
118
+ task :no_rspec do
119
+ $stderr.puts "Specification tasks not defined: %s" % [ err.message ]
120
+ end
121
+
122
+ task :spec => :no_rspec
123
+ namespace :spec do
124
+ task :autotest => :no_rspec
125
+ task :doc => :no_rspec
126
+ task :profile => :no_rspec
127
+ task :quiet => :no_rspec
128
+ task :html => :no_rspec
129
+ end
130
+ end
131
+
132
+
133
+ ### Test::Unit tests
134
+ begin
135
+ require 'rake/testtask'
136
+
137
+ Rake::TestTask.new( :unittests ) do |task|
138
+ task.libs += [LIBDIR]
139
+ task.test_files = TEST_FILES
140
+ task.verbose = true
141
+ end
142
+
143
+ rescue LoadError => err
144
+ task :no_test do
145
+ $stderr.puts "Test tasks not defined: %s" % [ err.message ]
146
+ end
147
+
148
+ task :unittests => :no_rspec
149
+ end
150
+
151
+
@@ -0,0 +1,64 @@
1
+ #####################################################################
2
+ ### S U B V E R S I O N T A S K S A N D H E L P E R S
3
+ #####################################################################
4
+
5
+ require 'rake/tasklib'
6
+
7
+ #
8
+ # Work around the inexplicable behaviour of the original RDoc::VerifyTask, which
9
+ # errors if your coverage isn't *exactly* the threshold.
10
+ #
11
+
12
+ # A task that can verify that the RCov coverage doesn't
13
+ # drop below a certain threshold. It should be run after
14
+ # running Spec::Rake::SpecTask.
15
+ class VerifyTask < Rake::TaskLib
16
+
17
+ COVERAGE_PERCENTAGE_PATTERN =
18
+ %r{<tt class='coverage_code'>(\d+\.\d+)%</tt>}
19
+
20
+ # Name of the task. Defaults to :verify_rcov
21
+ attr_accessor :name
22
+
23
+ # Path to the index.html file generated by RCov, which
24
+ # is the file containing the total coverage.
25
+ # Defaults to 'coverage/index.html'
26
+ attr_accessor :index_html
27
+
28
+ # Whether or not to output details. Defaults to true.
29
+ attr_accessor :verbose
30
+
31
+ # The threshold value (in percent) for coverage. If the
32
+ # actual coverage is not equal to this value, the task will raise an
33
+ # exception.
34
+ attr_accessor :threshold
35
+
36
+ def initialize( name=:verify )
37
+ @name = name
38
+ @index_html = 'coverage/index.html'
39
+ @verbose = true
40
+ yield self if block_given?
41
+ raise "Threshold must be set" if @threshold.nil?
42
+ define
43
+ end
44
+
45
+ def define
46
+ desc "Verify that rcov coverage is at least #{threshold}%"
47
+
48
+ task @name do
49
+ total_coverage = nil
50
+ if match = File.read( index_html ).match( COVERAGE_PERCENTAGE_PATTERN )
51
+ total_coverage = Float( match[1] )
52
+ else
53
+ raise "Couldn't find the coverage percentage in #{index_html}"
54
+ end
55
+
56
+ puts "Coverage: #{total_coverage}% (threshold: #{threshold}%)" if verbose
57
+ if total_coverage < threshold
58
+ raise "Coverage must be at least #{threshold}% but was #{total_coverage}%"
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # vim: set nosta noet ts=4 sw=4:
@@ -0,0 +1,26 @@
1
+ To backend> Msg Q
2
+ To backend> "SELECT 1 AS one"
3
+ To backend> Msg complete, length 21
4
+ From backend> T
5
+ From backend (#4)> 28
6
+ From backend (#2)> 1
7
+ From backend> "one"
8
+ From backend (#4)> 0
9
+ From backend (#2)> 0
10
+ From backend (#4)> 23
11
+ From backend (#2)> 4
12
+ From backend (#4)> -1
13
+ From backend (#2)> 0
14
+ From backend> D
15
+ From backend (#4)> 11
16
+ From backend (#2)> 1
17
+ From backend (#4)> 1
18
+ From backend (1)> 1
19
+ From backend> C
20
+ From backend (#4)> 11
21
+ From backend> "SELECT"
22
+ From backend> Z
23
+ From backend (#4)> 5
24
+ From backend> Z
25
+ From backend (#4)> 5
26
+ From backend> T
Binary file
@@ -0,0 +1,236 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+ require 'rspec'
5
+
6
+
7
+ RSpec.configure do |config|
8
+ ruby_version_vec = RUBY_VERSION.split('.').map {|c| c.to_i }.pack( "N*" )
9
+
10
+ config.mock_with :rspec
11
+ config.filter_run_excluding :ruby_19 => true if ruby_version_vec <= [1,9,1].pack( "N*" )
12
+ end
13
+
14
+ module PgTestingHelpers
15
+
16
+
17
+ # Set some ANSI escape code constants (Shamelessly stolen from Perl's
18
+ # Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
19
+ ANSI_ATTRIBUTES = {
20
+ 'clear' => 0,
21
+ 'reset' => 0,
22
+ 'bold' => 1,
23
+ 'dark' => 2,
24
+ 'underline' => 4,
25
+ 'underscore' => 4,
26
+ 'blink' => 5,
27
+ 'reverse' => 7,
28
+ 'concealed' => 8,
29
+
30
+ 'black' => 30, 'on_black' => 40,
31
+ 'red' => 31, 'on_red' => 41,
32
+ 'green' => 32, 'on_green' => 42,
33
+ 'yellow' => 33, 'on_yellow' => 43,
34
+ 'blue' => 34, 'on_blue' => 44,
35
+ 'magenta' => 35, 'on_magenta' => 45,
36
+ 'cyan' => 36, 'on_cyan' => 46,
37
+ 'white' => 37, 'on_white' => 47
38
+ }
39
+
40
+
41
+ ###############
42
+ module_function
43
+ ###############
44
+
45
+ ### Create a string that contains the ANSI codes specified and return it
46
+ def ansi_code( *attributes )
47
+ attributes.flatten!
48
+ attributes.collect! {|at| at.to_s }
49
+ # $stderr.puts "Returning ansicode for TERM = %p: %p" %
50
+ # [ ENV['TERM'], attributes ]
51
+ return '' unless /(?:vt10[03]|xterm(?:-color)?|linux|screen)/i =~ ENV['TERM']
52
+ attributes = ANSI_ATTRIBUTES.values_at( *attributes ).compact.join(';')
53
+
54
+ # $stderr.puts " attr is: %p" % [attributes]
55
+ if attributes.empty?
56
+ return ''
57
+ else
58
+ return "\e[%sm" % attributes
59
+ end
60
+ end
61
+
62
+
63
+ ### Colorize the given +string+ with the specified +attributes+ and return it, handling
64
+ ### line-endings, color reset, etc.
65
+ def colorize( *args )
66
+ string = ''
67
+
68
+ if block_given?
69
+ string = yield
70
+ else
71
+ string = args.shift
72
+ end
73
+
74
+ ending = string[/(\s)$/] || ''
75
+ string = string.rstrip
76
+
77
+ return ansi_code( args.flatten ) + string + ansi_code( 'reset' ) + ending
78
+ end
79
+
80
+
81
+ ### Output a message with highlighting.
82
+ def message( *msg )
83
+ $stderr.puts( colorize(:bold) { msg.flatten.join(' ') } )
84
+ end
85
+
86
+
87
+ ### Output a logging message if $VERBOSE is true
88
+ def trace( *msg )
89
+ return unless $VERBOSE
90
+ output = colorize( msg.flatten.join(' '), 'yellow' )
91
+ $stderr.puts( output )
92
+ end
93
+
94
+
95
+ ### Return the specified args as a string, quoting any that have a space.
96
+ def quotelist( *args )
97
+ return args.flatten.collect {|part| part.to_s =~ /\s/ ? part.to_s.inspect : part.to_s }
98
+ end
99
+
100
+
101
+ ### Run the specified command +cmd+ with system(), failing if the execution
102
+ ### fails.
103
+ def run( *cmd )
104
+ cmd.flatten!
105
+
106
+ if cmd.length > 1
107
+ trace( quotelist(*cmd) )
108
+ else
109
+ trace( cmd )
110
+ end
111
+
112
+ system( *cmd )
113
+ raise "Command failed: [%s]" % [cmd.join(' ')] unless $?.success?
114
+ end
115
+
116
+
117
+ NOFORK_PLATFORMS = %w{java}
118
+
119
+ ### Run the specified command +cmd+ after redirecting stdout and stderr to the specified
120
+ ### +logpath+, failing if the execution fails.
121
+ def log_and_run( logpath, *cmd )
122
+ cmd.flatten!
123
+
124
+ if cmd.length > 1
125
+ trace( quotelist(*cmd) )
126
+ else
127
+ trace( cmd )
128
+ end
129
+
130
+ # Eliminate the noise of creating/tearing down the database by
131
+ # redirecting STDERR/STDOUT to a logfile if the Ruby interpreter
132
+ # supports fork()
133
+ if NOFORK_PLATFORMS.include?( RUBY_PLATFORM )
134
+ system( *cmd )
135
+ else
136
+ logfh = File.open( logpath, File::WRONLY|File::CREAT|File::APPEND )
137
+ if pid = fork
138
+ logfh.close
139
+ else
140
+ $stdout.reopen( logfh )
141
+ $stderr.reopen( $stdout )
142
+ exec( *cmd )
143
+ $stderr.puts "After the exec()?!??!"
144
+ exit!
145
+ end
146
+
147
+ Process.wait( pid )
148
+ end
149
+
150
+ raise "Command failed: [%s]" % [cmd.join(' ')] unless $?.success?
151
+ end
152
+
153
+
154
+ ### Check the current directory for directories that look like they're
155
+ ### testing directories from previous tests, and tell any postgres instances
156
+ ### running in them to shut down.
157
+ def stop_existing_postmasters
158
+ # tmp_test_0.22329534700318
159
+ pat = Pathname.getwd + 'tmp_test_*'
160
+ Pathname.glob( pat.to_s ).each do |testdir|
161
+ datadir = testdir + 'data'
162
+ pidfile = datadir + 'postmaster.pid'
163
+ if pidfile.exist? && pid = pidfile.read.chomp.to_i
164
+ begin
165
+ Process.kill( 0, pid )
166
+ rescue Errno::ESRCH
167
+ trace "No postmaster running for %s" % [ datadir ]
168
+ # Process isn't alive, so don't try to stop it
169
+ else
170
+ trace "Stopping lingering database at PID %d" % [ pid ]
171
+ run 'pg_ctl', '-D', datadir.to_s, '-m', 'fast', 'stop'
172
+ end
173
+ end
174
+ end
175
+ end
176
+
177
+
178
+ ### Set up a PostgreSQL database instance for testing.
179
+ def setup_testing_db( description )
180
+ require 'pg'
181
+ stop_existing_postmasters()
182
+
183
+ puts "Setting up test database for #{description} tests"
184
+ @test_directory = Pathname.getwd + "tmp_test_specs"
185
+ @test_pgdata = @test_directory + 'data'
186
+ @test_pgdata.mkpath
187
+
188
+ @port = 54321
189
+ ENV['PGPORT'] = @port.to_s
190
+ ENV['PGHOST'] = 'localhost'
191
+ @conninfo = "host=localhost port=#{@port} dbname=test"
192
+
193
+ @logfile = @test_directory + 'setup.log'
194
+ trace "Command output logged to #{@logfile}"
195
+
196
+ begin
197
+ unless (@test_pgdata+"postgresql.conf").exist?
198
+ FileUtils.rm_rf( @test_pgdata, :verbose => $DEBUG )
199
+ trace "Running initdb"
200
+ log_and_run @logfile, 'initdb', '--no-locale', '-D', @test_pgdata.to_s
201
+ end
202
+
203
+ trace "Starting postgres"
204
+ log_and_run @logfile, 'pg_ctl', '-w', '-o', "-k #{@test_directory.to_s.inspect}",
205
+ '-D', @test_pgdata.to_s, 'start'
206
+
207
+ if `psql -l` =~ /^\s*test\s/
208
+ trace "Dropping the test DB"
209
+ log_and_run @logfile, 'dropdb', 'test'
210
+ end
211
+ trace "Creating the test DB"
212
+ log_and_run @logfile, 'createdb', 'test'
213
+ rescue => err
214
+ $stderr.puts "%p during test setup: %s" % [ err.class, err.message ]
215
+ $stderr.puts "See #{@logfile} for details."
216
+ $stderr.puts *err.backtrace if $DEBUG
217
+ fail
218
+ end
219
+
220
+ conn = PGconn.connect( @conninfo )
221
+ conn.set_notice_processor do |message|
222
+ $stderr.puts( message ) if $DEBUG
223
+ end
224
+
225
+ return conn
226
+ end
227
+
228
+
229
+ def teardown_testing_db( conn )
230
+ puts "Tearing down test database"
231
+ conn.finish if conn
232
+ log_and_run @logfile, 'pg_ctl', '-D', @test_pgdata.to_s, 'stop'
233
+ end
234
+ end
235
+
236
+