diff --git a/Gemfile b/Gemfile index 8365077..fc8fa1e 100644 --- a/Gemfile +++ b/Gemfile @@ -13,3 +13,4 @@ gem 'growl' gem 'rake', '0.8.7' gem 'mocha', '0.9.12' gem 'guard-jasmine-headless-webkit' +gem 'facter' diff --git a/Guardfile b/Guardfile index f0c26ca..1488233 100644 --- a/Guardfile +++ b/Guardfile @@ -4,7 +4,11 @@ # guard 'shell' do - watch(%r{ext/jasmine-webkit-specrunner/.*\.(cpp|h)}) { compile } + watch(%r{ext/jasmine-webkit-specrunner/.*\.(cpp|h|pro|pri)}) { |m| + if !m[0]['moc_'] + compile + end + } end # A sample Guardfile # More info at https://github.com/guard/guard#readme @@ -22,7 +26,7 @@ guard 'jasmine-headless-webkit', :all_on_start => false do end def compile - system %{cd ext/jasmine-webkit-specrunner && ruby extconf.rb} + system %{cd ext/jasmine-webkit-specrunner && ruby test.rb && ruby extconf.rb} end compile diff --git a/ext/jasmine-webkit-specrunner/ConsoleOutput.cpp b/ext/jasmine-webkit-specrunner/ConsoleOutput.cpp new file mode 100644 index 0000000..431aacd --- /dev/null +++ b/ext/jasmine-webkit-specrunner/ConsoleOutput.cpp @@ -0,0 +1,39 @@ +#include "ConsoleOutput.h" + +namespace HeadlessSpecRunner { + ConsoleOutput::ConsoleOutput() : QObject(), + showColors(false) { + outputIO = &std::cout; + } + + void ConsoleOutput::passed(const QString &specDetail) { + green(); + *outputIO << '.'; + clear(); + fflush(stdout); + + successes.push(specDetail); + } + + void ConsoleOutput::failed(const QString &specDetail) + { + red(); + *outputIO << 'F'; + clear(); + fflush(stdout); + + failures.push(specDetail); + } + + void ConsoleOutput::green() { + if (showColors) std::cout << "\033[0;32m"; + } + + void ConsoleOutput::clear() { + if (showColors) std::cout << "\033[m"; + } + + void ConsoleOutput::red() { + if (showColors) std::cout << "\033[0;31m"; + } +} diff --git a/ext/jasmine-webkit-specrunner/ConsoleOutput.h b/ext/jasmine-webkit-specrunner/ConsoleOutput.h new file mode 100644 index 0000000..0861aa3 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/ConsoleOutput.h @@ -0,0 +1,26 @@ +#ifndef JHW_CONSOLE_OUTPUT +#define JHW_CONSOLE_OUTPUT + +#include <QObject> +#include <iostream> +#include <QStack> + +namespace HeadlessSpecRunner { + class ConsoleOutput : public QObject { + Q_OBJECT + public: + ConsoleOutput(); + void passed(const QString &specDetail); + void failed(const QString &specDetail); + std::ostream *outputIO; + QStack<QString> successes; + QStack<QString> failures; + bool showColors; + private: + void green(); + void clear(); + void red(); + }; +} + +#endif diff --git a/ext/jasmine-webkit-specrunner/ConsoleOutput_test.cpp b/ext/jasmine-webkit-specrunner/ConsoleOutput_test.cpp new file mode 100644 index 0000000..6917615 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/ConsoleOutput_test.cpp @@ -0,0 +1,36 @@ +#include <QtTest/QtTest> + +#include "ConsoleOutput.h" +#include "ConsoleOutput_test.h" + +using namespace std; + +namespace HeadlessSpecRunner { + ConsoleOutputTest::ConsoleOutputTest() : QObject() { + } + + void ConsoleOutputTest::testPassed() { + stringstream buffer; + HeadlessSpecRunner::ConsoleOutput output; + + output.outputIO = &buffer; + output.passed("test"); + QVERIFY(buffer.str() == "."); + QVERIFY(output.successes.size() == 1); + QVERIFY(output.failures.size() == 0); + } + + void ConsoleOutputTest::testFailed() { + stringstream buffer; + HeadlessSpecRunner::ConsoleOutput output; + + output.outputIO = &buffer; + output.failed("test"); + QVERIFY(buffer.str() == "F"); + QVERIFY(output.successes.size() == 0); + QVERIFY(output.failures.size() == 1); + } +} + +QTEST_MAIN(HeadlessSpecRunner::ConsoleOutputTest); + diff --git a/ext/jasmine-webkit-specrunner/ConsoleOutput_test.h b/ext/jasmine-webkit-specrunner/ConsoleOutput_test.h new file mode 100644 index 0000000..455113a --- /dev/null +++ b/ext/jasmine-webkit-specrunner/ConsoleOutput_test.h @@ -0,0 +1,25 @@ +#ifndef JHW_TEST_PAGE +#define JHW_TEST_PAGE + +#include <QtTest/QtTest> +#include <iostream> +#include <sstream> +#include <string> + +#include "ConsoleOutput.h" + +namespace HeadlessSpecRunner { + class ConsoleOutputTest : public QObject { + Q_OBJECT + public: + ConsoleOutputTest(); + + private slots: + void testPassed(); + void testFailed(); + }; +} + +#endif + + diff --git a/ext/jasmine-webkit-specrunner/ConsoleOutput_test.pro b/ext/jasmine-webkit-specrunner/ConsoleOutput_test.pro new file mode 100644 index 0000000..7b09285 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/ConsoleOutput_test.pro @@ -0,0 +1,7 @@ +include(common.pri) +include(test.pri) + +SOURCES += ConsoleOutput_test.cpp +HEADERS += ConsoleOutput_test.h + + diff --git a/ext/jasmine-webkit-specrunner/HeadlessSpecRunner/ConsoleOutput.cpp b/ext/jasmine-webkit-specrunner/HeadlessSpecRunner/ConsoleOutput.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/ext/jasmine-webkit-specrunner/HeadlessSpecRunner/ConsoleOutput.h b/ext/jasmine-webkit-specrunner/HeadlessSpecRunner/ConsoleOutput.h deleted file mode 100644 index e69de29..0000000 diff --git a/ext/jasmine-webkit-specrunner/HeadlessSpecRunner/Page.cpp b/ext/jasmine-webkit-specrunner/Page.cpp similarity index 100% rename from ext/jasmine-webkit-specrunner/HeadlessSpecRunner/Page.cpp rename to ext/jasmine-webkit-specrunner/Page.cpp diff --git a/ext/jasmine-webkit-specrunner/HeadlessSpecRunner/Page.h b/ext/jasmine-webkit-specrunner/Page.h similarity index 100% rename from ext/jasmine-webkit-specrunner/HeadlessSpecRunner/Page.h rename to ext/jasmine-webkit-specrunner/Page.h diff --git a/ext/jasmine-webkit-specrunner/Page_test.cpp b/ext/jasmine-webkit-specrunner/Page_test.cpp new file mode 100644 index 0000000..a184d26 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/Page_test.cpp @@ -0,0 +1,45 @@ +#include <QtTest/QtTest> + +#include "Page.h" +#include "Page_test.h" + +namespace HeadlessSpecRunner { + PageTest::PageTest() : QObject(), internalLogCalled(false) { + } + + void PageTest::internalLog(const QString ¬e, const QString &msg) { + internalLogCalled = true; + } + + void PageTest::consoleLog(const QString &message, int lineNumber, const QString &source) { + consoleLogCalled = true; + } + + void PageTest::testJavaScriptConfirmWithLog() { + connect(&page, SIGNAL(internalLog(QString, QString)), this, SLOT(internalLog(QString, QString))); + internalLogCalled = false; + + page.mainFrame()->setHtml("<script>confirm('test')</script>"); + QVERIFY(internalLogCalled); + } + + void PageTest::testJavaScriptConfirmWithoutLog() { + connect(&page, SIGNAL(internalLog(QString, QString)), this, SLOT(internalLog(QString, QString))); + internalLogCalled = false; + + page.oneFalseConfirm(); + page.mainFrame()->setHtml("<script>confirm('test')</script>"); + QVERIFY(!internalLogCalled); + } + + void PageTest::testJavaScriptConsoleMessage() { + connect(&page, SIGNAL(consoleLog(QString, int, QString)), this, SLOT(consoleLog(QString, int, QString))); + consoleLogCalled = false; + + page.mainFrame()->setHtml("<script>cats();</script>"); + QVERIFY(consoleLogCalled); + } +} + +QTEST_MAIN(HeadlessSpecRunner::PageTest); + diff --git a/ext/jasmine-webkit-specrunner/Page_test.h b/ext/jasmine-webkit-specrunner/Page_test.h new file mode 100644 index 0000000..7d500b1 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/Page_test.h @@ -0,0 +1,29 @@ +#ifndef JHW_TEST_PAGE +#define JHW_TEST_PAGE + +#include <QtTest/QtTest> + +#include "Page.h" + +namespace HeadlessSpecRunner { + class PageTest : public QObject { + Q_OBJECT + public: + PageTest(); + + private: + bool internalLogCalled; + bool consoleLogCalled; + HeadlessSpecRunner::Page page; + + private slots: + void internalLog(const QString ¬e, const QString &msg); + void consoleLog(const QString &message, int lineNumber, const QString &source); + void testJavaScriptConfirmWithLog(); + void testJavaScriptConfirmWithoutLog(); + void testJavaScriptConsoleMessage(); + }; +} + +#endif + diff --git a/ext/jasmine-webkit-specrunner/Page_test.pro b/ext/jasmine-webkit-specrunner/Page_test.pro new file mode 100644 index 0000000..9482e83 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/Page_test.pro @@ -0,0 +1,6 @@ +include(common.pri) +include(test.pri) + +SOURCES += Page_test.cpp +HEADERS += Page_test.h + diff --git a/ext/jasmine-webkit-specrunner/HeadlessSpecRunner/Runner.cpp b/ext/jasmine-webkit-specrunner/Runner.cpp similarity index 97% rename from ext/jasmine-webkit-specrunner/HeadlessSpecRunner/Runner.cpp rename to ext/jasmine-webkit-specrunner/Runner.cpp index d778fb1..83ed612 100644 --- a/ext/jasmine-webkit-specrunner/HeadlessSpecRunner/Runner.cpp +++ b/ext/jasmine-webkit-specrunner/Runner.cpp @@ -66,6 +66,7 @@ namespace HeadlessSpecRunner { void Runner::setColors(bool colors) { showColors = colors; + consoleOutput.showColors = colors; } void Runner::reportFile(const QString &file) @@ -100,21 +101,15 @@ namespace HeadlessSpecRunner { void Runner::specPassed() { consoleNotUsedThisRun = true; - green(); - std::cout << '.'; - clear(); - fflush(stdout); + consoleOutput.passed(""); } void Runner::specFailed(const QString &specDetail) { consoleNotUsedThisRun = true; + consoleOutput.failed(""); didFail = true; - red(); - std::cout << 'F'; failedSpecs.push(specDetail); - clear(); - fflush(stdout); } void Runner::errorLog(const QString &msg, int lineNumber, const QString &sourceID) diff --git a/ext/jasmine-webkit-specrunner/HeadlessSpecRunner/Runner.h b/ext/jasmine-webkit-specrunner/Runner.h similarity index 95% rename from ext/jasmine-webkit-specrunner/HeadlessSpecRunner/Runner.h rename to ext/jasmine-webkit-specrunner/Runner.h index 5ff0e0a..c00e575 100644 --- a/ext/jasmine-webkit-specrunner/HeadlessSpecRunner/Runner.h +++ b/ext/jasmine-webkit-specrunner/Runner.h @@ -9,6 +9,7 @@ #include <QQueue> #include "Page.h" +#include "ConsoleOutput.h" namespace HeadlessSpecRunner { class Runner: public QObject { @@ -50,6 +51,8 @@ namespace HeadlessSpecRunner { QString reportFilename; QStack<QString> failedSpecs; + HeadlessSpecRunner::ConsoleOutput consoleOutput; + void red(); void green(); void yellow(); diff --git a/ext/jasmine-webkit-specrunner/common.pri b/ext/jasmine-webkit-specrunner/common.pri new file mode 100644 index 0000000..e19d607 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/common.pri @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG -= app_bundle +QMAKE_INFO_PLIST = Info.plist +QMAKESPEC = macx-g++ +QT += network webkit + +SOURCES = Page.cpp Runner.cpp ConsoleOutput.cpp +HEADERS = Page.h Runner.h ConsoleOutput.h + diff --git a/ext/jasmine-webkit-specrunner/extconf.rb b/ext/jasmine-webkit-specrunner/extconf.rb index df888d3..d950511 100644 --- a/ext/jasmine-webkit-specrunner/extconf.rb +++ b/ext/jasmine-webkit-specrunner/extconf.rb @@ -4,5 +4,6 @@ $: << File.expand_path("../../../lib", __FILE__) require 'qt/qmake' -Qt::Qmake.make!('jasmine-headless-webkit') +system %{make clean} +Qt::Qmake.make!('jasmine-headless-webkit', 'specrunner.pro') diff --git a/ext/jasmine-webkit-specrunner/jasmine-webkit-specrunner.pro b/ext/jasmine-webkit-specrunner/jasmine-webkit-specrunner.pro new file mode 100644 index 0000000..e6710d1 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/jasmine-webkit-specrunner.pro @@ -0,0 +1,19 @@ +###################################################################### +# Automatically generated by qmake (2.01a) Tue Aug 2 10:37:48 2011 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . HeadlessSpecRunner Test +INCLUDEPATH += . HeadlessSpecRunner Test + +# Input +HEADERS += HeadlessSpecRunner/ConsoleOutput.h \ + HeadlessSpecRunner/Page.h \ + HeadlessSpecRunner/Runner.h \ + Test/Page_test.h +SOURCES += specrunner.cpp \ + HeadlessSpecRunner/ConsoleOutput.cpp \ + HeadlessSpecRunner/Page.cpp \ + HeadlessSpecRunner/Runner.cpp \ + Test/Page_test.cpp diff --git a/ext/jasmine-webkit-specrunner/jhw-test b/ext/jasmine-webkit-specrunner/jhw-test new file mode 100755 index 0000000..347fe5a Binary files /dev/null and b/ext/jasmine-webkit-specrunner/jhw-test differ diff --git a/ext/jasmine-webkit-specrunner/specrunner.cpp b/ext/jasmine-webkit-specrunner/specrunner.cpp index 4827ac9..0ae4469 100644 --- a/ext/jasmine-webkit-specrunner/specrunner.cpp +++ b/ext/jasmine-webkit-specrunner/specrunner.cpp @@ -21,8 +21,8 @@ THE SOFTWARE. */ -#include "HeadlessSpecRunner/Page.h" -#include "HeadlessSpecRunner/Runner.h" +#include "Page.h" +#include "Runner.h" #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) #error Use Qt 4.7 or later version diff --git a/ext/jasmine-webkit-specrunner/specrunner.pro b/ext/jasmine-webkit-specrunner/specrunner.pro index 43201b9..820c444 100644 --- a/ext/jasmine-webkit-specrunner/specrunner.pro +++ b/ext/jasmine-webkit-specrunner/specrunner.pro @@ -1,8 +1,4 @@ -TEMPLATE = app -CONFIG -= app_bundle +include(common.pri) + +SOURCES += specrunner.cpp TARGET = jasmine-webkit-specrunner -SOURCES = HeadlessSpecRunner/Page.cpp HeadlessSpecRunner/Runner.cpp specrunner.cpp -HEADERS = HeadlessSpecRunner/Page.h HeadlessSpecRunner/Runner.h -QT += network webkit -QMAKE_INFO_PLIST = Info.plist -QMAKESPEC = macx-gcc diff --git a/ext/jasmine-webkit-specrunner/test.pri b/ext/jasmine-webkit-specrunner/test.pri new file mode 100644 index 0000000..4804421 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/test.pri @@ -0,0 +1,3 @@ +TARGET = jhw-test +QT += testlib + diff --git a/ext/jasmine-webkit-specrunner/test.rb b/ext/jasmine-webkit-specrunner/test.rb new file mode 100644 index 0000000..4585da1 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/test.rb @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby + +system %{make clean} + +Dir['*_test.pro'].each do |test| + $: << File.expand_path("../../../lib", __FILE__) + + require 'qt/qmake' + Qt::Qmake.make!('jasmine-headless-webkit', test) + + system %{./jhw-test} + if $?.exitstatus != 0 + exit 1 + end +end + diff --git a/lib/qt/qmake.rb b/lib/qt/qmake.rb index 935dd20..0c684e5 100644 --- a/lib/qt/qmake.rb +++ b/lib/qt/qmake.rb @@ -2,9 +2,14 @@ require 'rbconfig' require 'rubygems' require 'rubygems/version' +begin + require 'facter' +rescue LoadError + warn 'Including Facter allows for detection of # of cpus, resulting in faster compilations.' +end + module Qt class NotInstalledError < StandardError; end - class Qmake class << self QMAKES = %w{qmake-qt4 qmake} @@ -17,25 +22,34 @@ module Qt make_path != nil end - def command - case platform + def command(project_file = nil) + spec = (case platform when :linux - "#{path} -spec linux-g++" + "linux-g++" when :freebsd - "#{path} -spec freebsd-g++" + "freebsd-g++" when :mac_os_x - "#{path} -spec macx-g++" - end + "macx-g++" + end) + + command = "#{path} -spec #{spec}" + command << " #{project_file}" if project_file + command end - def make!(name) + def make!(name, project_file = nil) @name = name check_make! check_qmake! - system command - system %{make} + system command(project_file) + + system %{make #{make_options}} + end + + def make_options + "-j#{number_of_cpus}" end # @@ -46,7 +60,7 @@ module Qt end def make_path - get_exe_path('gmake') || get_exe_path('make') + get_exe_path('gmake') || get_exe_path('make') end def platform @@ -74,13 +88,21 @@ module Qt end result end.compact.sort { |a, b| b.last <=> a.last }.first - qmake_path.first + qmake_path.first else nil end end private + def number_of_cpus + if defined?(Facter) + Facter.sp_number_processors rescue Facter.processorcount + else + 1 + end + end + def get_exe_path(command) path = %x{which #{command}}.strip path = nil if path == '' @@ -101,9 +123,9 @@ module Qt ) $stderr.puts <<-MSG -make is not installed. You'll need to install it to build #{@name}. -#{install_method} should do it for you. -MSG + make is not installed. You'll need to install it to build #{@name}. + #{install_method} should do it for you. + MSG raise NotInstalledError end end @@ -114,26 +136,27 @@ MSG case platform when :linux <<-MSG -sudo apt-get install libqt4-dev qt4-qmake on Debian-based systems, or downloading -Nokia's prebuilt binary at http://qt.nokia.com/downloads/ -MSG + sudo apt-get install libqt4-dev qt4-qmake on Debian-based systems, or downloading + Nokia's prebuilt binary at http://qt.nokia.com/downloads/ + MSG when :freebsd <<-MSG -Install /usr/ports/www/qt4-webkit and /usr/ports/devel/qmake4. + Install /usr/ports/www/qt4-webkit and /usr/ports/devel/qmake4. MSG + MSG when :mac_os_x <<-MSG -sudo port install qt4-mac (for the patient) or downloading Nokia's pre-built binary -at http://qt.nokia.com/downloads/ -MSG + sudo port install qt4-mac (for the patient) or downloading Nokia's pre-built binary + at http://qt.nokia.com/downloads/ + MSG end ).strip $stderr.puts <<-MSG -qmake is not installed or is not the right version (#{@name} needs Qt 4.7 or above). -You'll need to install it to build #{@name}. -#{install_method} should do it for you. -MSG + qmake is not installed or is not the right version (#{@name} needs Qt 4.7 or above). + You'll need to install it to build #{@name}. + #{install_method} should do it for you. + MSG end end end diff --git a/script/gemfile b/script/gemfile new file mode 100755 index 0000000..eb78755 --- /dev/null +++ b/script/gemfile @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby + +require 'rubygems' +require 'penchant' + +if Penchant::Gemfile.do_full_env_switch!(ARGV[0]) + puts "Gemfile switched to #{ARGV[0]}" +else + exit 0 +end + diff --git a/script/hooks/pre-commit b/script/hooks/pre-commit new file mode 100755 index 0000000..e1b1e1c --- /dev/null +++ b/script/hooks/pre-commit @@ -0,0 +1,15 @@ +#!/bin/bash + +OLD_GIT_DIR=$GIT_DIR + +if [ "$(penchant gemfile-env)" != "remote" ]; then + unset GIT_DIR + penchant gemfile remote + GIT_DIR=$OLD_GIT_DIR + git add Gemfile* +fi + +bundle exec rake +R=$? +if [ $R -ne 0 ]; then exit $R; fi + diff --git a/script/initialize-environment b/script/initialize-environment new file mode 100755 index 0000000..222c8f1 --- /dev/null +++ b/script/initialize-environment @@ -0,0 +1,35 @@ +#!/usr/bin/env ruby + +if File.file?('Gemfile.erb') + pwd = Dir.pwd + + Dir.chdir '..' do + File.readlines(File.join(pwd, 'Gemfile.erb')).find_all { |line| line[':git'] }.each do |line| + repo = line[%r{:git => (['"])(.*)\1}, 2] + + puts "Installing #{repo}" + system %{git clone #{repo}} + end + end + + puts "Bundling for local environment" + system %{script/gemfile local} +else + puts "Bundling..." + system %{bundle} +end + +puts "Installing git hooks" +system %{script/install-git-hooks} + +bundle = File.file?('Gemfile') ? 'bundle exec' : '' + +command = [ bundle, 'rake', '-s', '-T', 'bootstrap' ] + +if !(%x{#{command.join(' ')}}).empty? + puts "Trying to run rake bootstrap..." + system %{#{bundle} rake bootstrap} +end + +puts "Done!" + diff --git a/script/install-git-hooks b/script/install-git-hooks new file mode 100755 index 0000000..0644244 --- /dev/null +++ b/script/install-git-hooks @@ -0,0 +1,6 @@ +#!/bin/bash + +for hook in script/hooks/* ; do + ln -sf $PWD/$hook .git/hooks/${hook##*/} +done + diff --git a/spec/lib/qt/qmake_spec.rb b/spec/lib/qt/qmake_spec.rb index 64d2dd9..4cc7016 100644 --- a/spec/lib/qt/qmake_spec.rb +++ b/spec/lib/qt/qmake_spec.rb @@ -136,5 +136,16 @@ describe Qt::Qmake do end end end + + describe '.make_options' do + let(:cpu_count) { 3 } + subject { Qt::Qmake.make_options } + + before do + Qt::Qmake.stubs(:number_of_cpus).returns(cpu_count) + end + + it { should == "-j#{cpu_count}" } + end end