cuke4php 0.9.6.c → 0.9.8

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/HISTORY CHANGED
@@ -18,3 +18,6 @@
18
18
  * utilizes cucumber 0.10.2's ability to use erb templates in .wire files to listen to a specific port
19
19
  * release 0.9.3
20
20
  * modify cuke4php runner script to dynamically pick an unused port
21
+
22
+ 2011-08-30 -- 0.9.8
23
+ * add support for a forking socket listener
data/Rakefile CHANGED
@@ -27,6 +27,9 @@ begin
27
27
  Install PHPUnit:
28
28
  pear install phpunit/PHPUnit
29
29
 
30
+ Optional: Use PEAR/Net_Server for a remote forking server implementation
31
+ (requires PHP with pcntl extensions)
32
+
30
33
  ********************************************************************************
31
34
  eos
32
35
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.6.c
1
+ 0.9.8
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env ruby
2
+ exec File.dirname(__FILE__) + "/../php_bin/cuke4php_forking_server.php #{ARGV.join(' ')}"
data/cuke4php.gemspec CHANGED
@@ -5,14 +5,14 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{cuke4php}
8
- s.version = "0.9.6.c"
8
+ s.version = "0.9.8"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Kevin Olbrich", "Alessandro Dal Grande"]
12
- s.date = %q{2011-05-07}
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Kevin Olbrich}, %q{Alessandro Dal Grande}]
12
+ s.date = %q{2011-08-31}
13
13
  s.description = %q{Using this protocol it is possible to directly interact with PHP code at any level without the need for a web server. To accomplish this, when cucumber is running against a directory containing feature files and it cannot resolve a particular step definition, it will ask a known wire server (as defined in a .wire file) to interpret and run those steps.}
14
- s.email = ["kevin.olbrich+cuke4php@gmail.com", "aledalgrande@gmail.com"]
15
- s.executables = ["cuke4php_server", "cuke4php"]
14
+ s.email = [%q{kevin.olbrich+cuke4php@gmail.com}, %q{aledalgrande@gmail.com}]
15
+ s.executables = [%q{cuke4php_forking_server}, %q{cuke4php_server}, %q{cuke4php}]
16
16
  s.extra_rdoc_files = [
17
17
  "LICENSE",
18
18
  "README.md"
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  "Rakefile",
27
27
  "VERSION",
28
28
  "bin/cuke4php",
29
+ "bin/cuke4php_forking_server",
29
30
  "bin/cuke4php_server",
30
31
  "cucumber.yml",
31
32
  "cuke4php.gemspec",
@@ -40,11 +41,12 @@ Gem::Specification.new do |s|
40
41
  "lib/CucumberScenario.php",
41
42
  "lib/CucumberSteps.php",
42
43
  "lib/Cuke4Php.php",
44
+ "lib/Cuke4PhpForkingServer.php",
45
+ "php_bin/cuke4php_forking_server.php",
43
46
  "php_bin/cuke4php_server.php",
44
47
  "tests/lib/CucumberScenarioTest.php",
45
48
  "tests/lib/Cuke4PhpTest.php"
46
49
  ]
47
- s.has_rdoc = false
48
50
  s.homepage = %q{http://github.com/olbrich/cuke4php}
49
51
  s.post_install_message = %q{********************************************************************************
50
52
 
@@ -58,15 +60,17 @@ Gem::Specification.new do |s|
58
60
  Install PHPUnit:
59
61
  pear install phpunit/PHPUnit
60
62
 
63
+ Optional: Use PEAR/Net_Server for a remote forking server implementation
64
+ (requires PHP with pcntl extensions)
65
+
61
66
  ********************************************************************************
62
67
  }
63
- s.require_paths = ["lib"]
64
- s.requirements = ["PHP 5.2+", "PHPUnit 3.0+"]
65
- s.rubygems_version = %q{1.3.7}
68
+ s.require_paths = [%q{lib}]
69
+ s.requirements = [%q{PHP 5.2+}, %q{PHPUnit 3.0+}]
70
+ s.rubygems_version = %q{1.8.5}
66
71
  s.summary = %q{Implementation of the Cucumber wire protocol for PHP projects}
67
72
 
68
73
  if s.respond_to? :specification_version then
69
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
70
74
  s.specification_version = 3
71
75
 
72
76
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
@@ -54,4 +54,7 @@ Scenario Outline: Error Handling
54
54
  @exception
55
55
  Scenario: Exception Handling
56
56
  When an "Exception" is thrown with message "generic exception"
57
- Then an "Exception" should be caught
57
+ Then an "Exception" should be caught
58
+
59
+ Scenario: nested capture groups work fine
60
+ Given the losing code "one" has the prize "two"
@@ -1,4 +1,2 @@
1
1
  host: localhost
2
2
  port: <%= ENV['CUKE4PHP_PORT'] || 16816 %>
3
- invoke:
4
- timeout: 0.1
@@ -231,6 +231,13 @@ class WireSteps extends CucumberSteps {
231
231
  self::assertInternalType($sTypeName, $this->$sKey);
232
232
  }
233
233
 
234
+ /**
235
+ * Given /^the(?: losing)? code "([^"]*)"(?: has the prize "([^"]*)")?$/
236
+ **/
237
+ public function stepTheLosingCodeParameterHasThePrizeParameter($sCode, $sPrize) {
238
+ $this->$sCode = $sPrize;
239
+ }
240
+
234
241
  }
235
242
 
236
243
  ?>
@@ -66,6 +66,7 @@ class CucumberScenario {
66
66
  if (array_key_exists('tags', $aBeforeHook)) {
67
67
  if (count($aBeforeHook['tags']) == 0 || count(array_intersect($aTags, $aBeforeHook['tags'])) > 0) {
68
68
  $oStep = CucumberSteps::getInstance($aBeforeHook['class'], $this->aGlobals);
69
+ syslog(LOG_DEBUG,"Invoking Before Hook \"{$aBeforeHook['method']}\"");
69
70
  $oResult = $oStep->invoke($aBeforeHook['method']);
70
71
  if ($oResult === false) {
71
72
  return array('failure');
@@ -89,6 +90,7 @@ class CucumberScenario {
89
90
  if (array_key_exists('tags', $aAfterHook)) {
90
91
  if (count($aAfterHook['tags']) == 0 || count(array_intersect($aTags, $aAfterHook['tags'])) > 0) {
91
92
  $oStep = CucumberSteps::getInstance($aAfterHook['class'], $this->aGlobals);
93
+ syslog(LOG_DEBUG,"Invoking After Hook \"{$aAfterHook['method']}\"");
92
94
  $oResult = $oStep->invoke($aAfterHook['method']);
93
95
  if ($oResult === false) {
94
96
  return array('failure');
@@ -132,14 +134,19 @@ class CucumberScenario {
132
134
 
133
135
  }
134
136
  try {
137
+ syslog(LOG_DEBUG,"Invoking Step \"{$aStep['method']}\"");
135
138
  call_user_func_array(array($oStep, $aStep['method']),$aArgs);
136
139
  } catch (PHPUnit_Framework_IncompleteTestError $e) {
140
+ syslog(LOG_DEBUG,"Step Pending");
137
141
  return array('pending',$e->getMessage());
138
142
  } catch (PHPUnit_Framework_SkippedTestError $e) {
143
+ syslog(LOG_DEBUG,"Step Pending");
139
144
  return array('pending',$e->getMessage());
140
145
  } catch (PHPUnit_Framework_ExpectationFailedException $e) {
146
+ syslog(LOG_DEBUG,"Step Failed due to unmet expectation: " . $e->getMessage());
141
147
  return array('fail', array('message' => $e->getMessage()));
142
148
  } catch (Exception $e) {
149
+ syslog(LOG_DEBUG,"Step failed due to ". get_class($e) ." exception :" . $e->getMessage());
143
150
  return array('fail', array('message' => $e->getMessage() . " " . $e->getFile() . ":" . $e->getLine(), 'exception' => get_class($e), 'backtrace' => $e->getTraceAsString()));
144
151
  }
145
152
  return array('success');
data/lib/Cuke4Php.php CHANGED
@@ -26,6 +26,7 @@ class Cuke4Php {
26
26
  );
27
27
 
28
28
  function __construct($_sFeaturePath, $_iPort = 16816) {
29
+ openlog("cuke4php", LOG_PID, LOG_DAEMON);
29
30
  if (is_file($_sFeaturePath)) {
30
31
  $_sFeaturePath = dirname($_sFeaturePath);
31
32
  }
@@ -119,21 +120,40 @@ class Cuke4Php {
119
120
  }
120
121
 
121
122
  function run() {
122
- print "Cuke4Php listening on port $this->iPort\n";
123
+ syslog(LOG_INFO,"Cuke4Php listening on port $this->iPort\n");
123
124
  $this->oSocket = socket_create_listen($this->iPort);
124
125
  $this->bRun = true;
125
126
  while ($this->bRun && ($connection = socket_accept($this->oSocket))) {
126
127
  socket_getpeername($connection, $raddr, $rport);
127
- while ($this->bRun && ($input = socket_read($connection, 1024 * 4))) {
128
- $data = trim($input);
129
- if ($data !== "") {
130
- $output = json_encode($this->process($data)) . "\n";
131
- if ($this->bRun) {
132
- socket_write($connection, $output);
128
+ syslog(LOG_INFO,"Connection from $raddr");
129
+ try {
130
+ while ($this->bRun && ($input = socket_read($connection, 4096, PHP_NORMAL_READ))) {
131
+ $data = trim($input);
132
+ if ($data !== "") {
133
+ $output = json_encode($this->process($data)) . "\n";
134
+ if ($this->bRun) {
135
+ socket_write($connection, $output);
136
+ }
133
137
  }
138
+ }
139
+ } catch (Exception $e) {
140
+ switch (socket_last_error($connection)) {
141
+ case 54:
142
+ // connection closed by peer
143
+ case 104:
144
+ // unable to read from socket
145
+ // these errors just mean we are done and the connection should be closed.
146
+ // it does not mean we should stop listening for new connections.
147
+ break;
148
+
149
+ default:
150
+ syslog(LOG_ERR,$e->getMessage());
151
+ throw $e;
152
+ break;
134
153
  }
135
154
  }
136
155
  socket_close($connection);
156
+ syslog(LOG_INFO,"Connection closed");
137
157
  sleep(1);
138
158
  }
139
159
  }
@@ -183,6 +203,7 @@ class Cuke4Php {
183
203
  * run any before hooks for a scenario
184
204
  */
185
205
  function beginScenario($aTags) {
206
+ syslog(LOG_DEBUG,"Begin Scenario: Tags: " . implode(", ", $aTags));
186
207
  $this->setScenario(CucumberScenario::getInstance($this->aWorld));
187
208
  return $this->oScenario->invokeBeforeHooks($aTags);
188
209
  }
@@ -216,6 +237,7 @@ class Cuke4Php {
216
237
  */
217
238
  function endScenario($aTags) {
218
239
  $oResult = $this->oScenario->invokeAfterHooks($aTags);
240
+ syslog(LOG_DEBUG,"End Scenario");
219
241
  $this->oScenario = null;
220
242
  return $oResult;
221
243
  }
@@ -0,0 +1,34 @@
1
+ <?php
2
+
3
+ /**
4
+ * This class allows multiple concurrent connections to the same Cuke4php port. Each connection forks a process that
5
+ * loads the same feature files and then runs the step definitions. This is useful for cases where the Cuke4php server
6
+ * is deployed to a remote machine and multiple automation scripts are simultaneously connecting to the server.
7
+ *
8
+ * Uses the PEAR Net_Server package
9
+ **/
10
+
11
+ require_once "Cuke4Php.php";
12
+ require_once "Net/Server.php";
13
+ require_once "Net/Server/Handler.php";
14
+
15
+ class Cuke4PhpForkingServer extends Net_Server_Handler
16
+ {
17
+ private $cuke4php;
18
+
19
+ function __construct($_sFeaturePath, $_iPort) {
20
+ $this->cuke4php = new Cuke4Php($_sFeaturePath, $_iPort);
21
+ }
22
+
23
+ function onReceiveData($iClientId = 0, $data = "") {
24
+ $output = json_encode($this->cuke4php->process($data)) . "\n";
25
+ $this->_server->sendData($iClientId, $output);
26
+ }
27
+
28
+ function onClose($iClientId) {
29
+ // Do nothing
30
+ }
31
+ }
32
+
33
+
34
+ ?>
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env php
2
+ <?php
3
+ /**
4
+ * main entry point for starting a Cuke4Php wire server
5
+ * @package Cuke4Php
6
+ */
7
+
8
+ /**
9
+ * load the Cuke4PhpForkingServer server
10
+ */
11
+ require_once dirname(__FILE__) . "/../lib/Cuke4PhpForkingServer.php";
12
+
13
+ $aOptions = getopt("p:");
14
+ if (array_key_exists('p',$aOptions)) {
15
+ $iPort = $aOptions['p'];
16
+ } else {
17
+ $iPort = 16816;
18
+ }
19
+
20
+ $oServer = &Net_Server::create('fork','0.0.0.0', $iPort);
21
+ $oServerHandler = &new Cuke4PhpForkingServer(realpath($argv[$argc-1]), $iPort);
22
+ $oServer->setCallbackObject($oServerHandler);
23
+ $oServer->start();
24
+ ?>
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuke4php
3
3
  version: !ruby/object:Gem::Version
4
- hash: 120
5
- prerelease: true
4
+ hash: 43
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 6
10
- - c
11
- version: 0.9.6.c
9
+ - 8
10
+ version: 0.9.8
12
11
  platform: ruby
13
12
  authors:
14
13
  - Kevin Olbrich
@@ -17,11 +16,10 @@ autorequire:
17
16
  bindir: bin
18
17
  cert_chain: []
19
18
 
20
- date: 2011-05-07 00:00:00 -04:00
21
- default_executable:
19
+ date: 2011-08-31 00:00:00 Z
22
20
  dependencies:
23
21
  - !ruby/object:Gem::Dependency
24
- requirement: &id001 !ruby/object:Gem::Requirement
22
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
23
  none: false
26
24
  requirements:
27
25
  - - ">="
@@ -33,11 +31,11 @@ dependencies:
33
31
  - 2
34
32
  version: 0.10.2
35
33
  type: :runtime
36
- name: cucumber
34
+ requirement: *id001
37
35
  prerelease: false
38
- version_requirements: *id001
36
+ name: cucumber
39
37
  - !ruby/object:Gem::Dependency
40
- requirement: &id002 !ruby/object:Gem::Requirement
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
41
39
  none: false
42
40
  requirements:
43
41
  - - ~>
@@ -48,11 +46,11 @@ dependencies:
48
46
  - 0
49
47
  version: "1.0"
50
48
  type: :development
51
- name: bundler
49
+ requirement: *id002
52
50
  prerelease: false
53
- version_requirements: *id002
51
+ name: bundler
54
52
  - !ruby/object:Gem::Dependency
55
- requirement: &id003 !ruby/object:Gem::Requirement
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
56
54
  none: false
57
55
  requirements:
58
56
  - - ">="
@@ -62,14 +60,15 @@ dependencies:
62
60
  - 0
63
61
  version: "0"
64
62
  type: :development
65
- name: jeweler
63
+ requirement: *id003
66
64
  prerelease: false
67
- version_requirements: *id003
65
+ name: jeweler
68
66
  description: Using this protocol it is possible to directly interact with PHP code at any level without the need for a web server. To accomplish this, when cucumber is running against a directory containing feature files and it cannot resolve a particular step definition, it will ask a known wire server (as defined in a .wire file) to interpret and run those steps.
69
67
  email:
70
68
  - kevin.olbrich+cuke4php@gmail.com
71
69
  - aledalgrande@gmail.com
72
70
  executables:
71
+ - cuke4php_forking_server
73
72
  - cuke4php_server
74
73
  - cuke4php
75
74
  extensions: []
@@ -86,6 +85,7 @@ files:
86
85
  - Rakefile
87
86
  - VERSION
88
87
  - bin/cuke4php
88
+ - bin/cuke4php_forking_server
89
89
  - bin/cuke4php_server
90
90
  - cucumber.yml
91
91
  - cuke4php.gemspec
@@ -100,10 +100,11 @@ files:
100
100
  - lib/CucumberScenario.php
101
101
  - lib/CucumberSteps.php
102
102
  - lib/Cuke4Php.php
103
+ - lib/Cuke4PhpForkingServer.php
104
+ - php_bin/cuke4php_forking_server.php
103
105
  - php_bin/cuke4php_server.php
104
106
  - tests/lib/CucumberScenarioTest.php
105
107
  - tests/lib/Cuke4PhpTest.php
106
- has_rdoc: false
107
108
  homepage: http://github.com/olbrich/cuke4php
108
109
  licenses: []
109
110
 
@@ -120,6 +121,9 @@ post_install_message: |
120
121
  Install PHPUnit:
121
122
  pear install phpunit/PHPUnit
122
123
 
124
+ Optional: Use PEAR/Net_Server for a remote forking server implementation
125
+ (requires PHP with pcntl extensions)
126
+
123
127
  ********************************************************************************
124
128
 
125
129
  rdoc_options: []
@@ -138,19 +142,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
138
142
  required_rubygems_version: !ruby/object:Gem::Requirement
139
143
  none: false
140
144
  requirements:
141
- - - ">"
145
+ - - ">="
142
146
  - !ruby/object:Gem::Version
143
- hash: 25
147
+ hash: 3
144
148
  segments:
145
- - 1
146
- - 3
147
- - 1
148
- version: 1.3.1
149
+ - 0
150
+ version: "0"
149
151
  requirements:
150
152
  - PHP 5.2+
151
153
  - PHPUnit 3.0+
152
154
  rubyforge_project:
153
- rubygems_version: 1.3.7
155
+ rubygems_version: 1.8.5
154
156
  signing_key:
155
157
  specification_version: 3
156
158
  summary: Implementation of the Cucumber wire protocol for PHP projects