Coder Social home page Coder Social logo

xp-framework's Introduction

XP Framework

Build Status on TravisCI BSD Licence Required PHP 5.3+

This is the XP Framework's development checkout for the 5.X-SERIES.

Note: Development now focusses on the 6.X-SERIES, which are maintained in the xp-framework/core repository. Bugfixes may be backported, but new features will usually only go to 6.X

Installation

Clone this repository, e.g. using Git Read-Only:

$ cd [path]
$ git clone git://github.com/xp-framework/xp-framework.git

Directory structure

[path]/xp-framework
`- core
   |- ChangeLog         # Version log
   |- boot.pth          # Bootstrap classpath
   |- tools             # Bootstrapping (lang.base.php, class.php, xar.php, web.php)
   `- src               # Sourcecode, by Maven conventions
      |- main
      |  `- php
      `- test
         |- php
         |- config      # Unittest configuration
         `- resources   # Test resources

Runners

The entry point for software written in the XP Framework is not the PHP interpreter's CLI / web server API but either a command line runner or a specialized web entry point. These runners can be installed by using the following one-liner:

$ cd ~/bin
$ wget 'https://github.com/xp-framework/xp-runners/releases/download/v6.2.0/setup' -O - | php

Using it

To use the the XP Framework development checkout, put the following in your ~/bin/xp.ini file:

use=[path]/xp-framework/core

Enjoy!

Contributing

To contribute, use the GitHub way - fork, hack, and submit a pull request!

xp-framework's People

Contributors

andstefiul avatar beorgler avatar guel1973 avatar johannes85 avatar kiesel avatar kusnier avatar martinakraus avatar melogamepay avatar ohinckel avatar patzerr avatar ppetermann avatar stormwind avatar thekid avatar treuter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xp-framework's Issues

Mocking Library

RFC ????: Mocking Library

@authors: iigorr
@created: Fri Sep 23 14:05:00 2011
@status: draft
@category: unittest

Scope of Change

A mocking framework will be added to the unittest API.

Rationale

Easily mock interfaces and verify expected behaviour similar to EasyMock (Java),
Rhino Mocks (.Net) and many other mocking frameworks.

Functionality

A new namespace 'unittest.mock' is introduced containing everything that enables
mock functionallity. A new class 'unittest.mock.Mockery' provides a method
'createMock($interfaceName)'. This method generates a mock object which
implements the required interface and provides methods for defining and
verifying expected behaviour.

The mocking framework should follow the record/replay/verfiy paradigm as
described here http://martinfowler.com/articles/mocksArentStubs.html or here
http://ayende.com/Blog/archive/2007/12/26/The-RecordReplayVerify-model.aspx

In the first step, the mocking of return values will be implemented. Later,
following features may follow:

  • Method argument matching
  • Behaviour verification
  • Execution order verification
  • Strick mocks (unsatisfied expectation)
  • Rewinding the replay state
  • Switching back to record after replay started

Example (Return values):
Consider an interface like the following.
interface Session {
... //many methods
public function getId();
}

Now we have the following method which we would like to unittest:

public function foo(Session $session) {
$this->bar(); //do something else
$this->baz($session->getId()); //do something with the session id
}

To cover this method it is irrelevant how the session object looks like.
Only the session id is of interest. Thus it would be nice if one could quickly
create a mock object for this:

[@test]
public function fooIsCalledWithoutException() {
$sessionMock= $mockery->createMock('Session');
$sessionMock->getId()->return(7); //return 7 if getId is called
$sessionMock->replay();

$this->sut->foo($sessionMock);
}

Security considerations

n/a

Speed impact

Unittests will run faster if simple mocks are used instead of complex instantiation of dependency objects.

Dependencies

XP Framework

This change comes with an extensive refactoring/redesign of the lang.reflect.Proxy class and its usage.

Related documents

An introduction can be found on xp-forge: http://experiments.xp-forge.net/xml/view?arena,mocks,INTRODUCTION.txt

Support Unicode in .ini files

Ini files should support Unicode. The detection whether the file is in iso-8859-1 (the current default) or whether it's in Unicode could be performed analogous to the io.streams.TextReader class on the first couple of bytes in the .ini file:

  • \376\377 -> UTF-16 BE
  • \377\376-> UTF-16 LE
  • \357\273\277 -> UTF-8

This is consistent with what most text editors support, and even works in Windows Vista & 7's "notepad"!

Possible inconsistency with __ methods in lang.base.php

https://bugs.php.net/bug.php?id=55311 - When calling a non-existant static method within an objects method, php invokes
__call instead of __callStatic. Seems to affect PHP >= 5.3.5.

On php-internals, the explanation is:

To me it's simply a bug fix.
Consider the following code:

<?php
class A {
   public function __call() {
       echo "__call";
   }

   public function __callStatic() {
       echo "__callStatic";
   }
}

class B extends A {
   public function test() {
      parent::test();
   }
}


$b = new B;

$b->test();
?>

It would simply be wrong to have callStatic being called here (it always called __call before __callStatic existed), so IMO the new behavior is fine, and even though fixing it introduced a BC break (like many bug fixes), it is now more consistent. Note that reverting it again would introduce a BC break as well with current 5_3.

Summary

So we're left with an inconsistency at best, though. An investigation should show if this will affect any real-life scenarios in the XP Framework.

xp::stringOf() for primitive wrapper classes

The xp::stringOf() core functionality should use __toString() if available. To implement this, all primitive wrapper classes should implement a lang.types.PrimitiveWrapper class instead of checking whether method_exists($class, '__toString').

Register a wrapper to a state

It will be nice to have the possibility to attach (register) a wrapper to a state.

Reason: There are many times when you wish to output something based on a GET parameter and every time you should check manually each of the params.
Example: Display all products form category 5 (/xml/viewproducts?category=5). In that state you should check if 'category' param is set & is numeric. This should be done automatically.

Support keywords in ExifData class

Example: IFD0 { keywords => "Food;Salads" }

Can be edited with Windows Vista+ explorer windows in the bar at the bottom of the screen (also stored in WINXP section, a less-generic place).

Iteration support in HashTable

As discussd in issue #47: Iteration should be supported on util.collection.Map implementations via Iterator<Pair<K, V>>:

Example

<?php
  $hash= new HashTable();
  // ...
  foreach ($hash as $pair) {
    Console::writeLine($pair->key, ' => ', $pair->value);
  }
?>

The Pair class' keys and values could are realized as public properties.

lang.reflect.Field::getType() returns string, not lang.Type instance

...and is thus incosistent with all other classes in lang.reflect. My suggestion would be to change this like inside the lang.reflect.Parameter class:

  public lang.Type getType()
  public string getTypeName()

...and give the lang.Type class a __toString converter to keep BC (not unittest-wise, but usage as string will usually work just fine).

Accidentally overwriting TestCase's special methods

The following should not be allowed:

  class SystemPropertyTest extends TestCase {

    #[@test]
    public function getName() {
      $this->assertEquals('...', $this->fixture->getName());
    }
  }

It will run getName() as a unittest (which is not a real problem as long as it doesn't fail) but the test results will have incorrect names reported. If this test fails, the results are completely borked

Class 'SoapVar' not found

When running src/resources/unittest/webservices.ini, I get (abbreviated for readability):

Exception lang.Error (Fatal error: Class 'SoapVar' not found in ...\NativeSoapTypeMapperTest.class.php on line 39)
Fatal error: Access to undeclared static property: Streams::$streams in ...\Streams.class.php on line 157

Errors with Strings in Unicode Branch

Hi,

we have a few problems with the unicode branch.

For example when reading Request Parameters and putting them in the xml output the XP-Framework doesn't convert the to unicode Strings but uses native PHP Strings. At that point we get an exception when rendering the page.

To fix thius issue we made the following changes to the Node.class.php

diff -r xp_utf_8_current/xml/Node.class.php xp_utf_8_patch3//xml/Node.class.php
52,55c52
<       foreach ($attribute as $key => $field) {
<               $this->setAttribute($key,$field);
<       }
< //      $this->attribute= $attribute;

---
>       $this->attribute= $attribute;
75,82c72
<       if (is_string($field)) {
<               try {
<                       $sfield = new String($field,'utf8');
<               } catch (FormatException $e) {
<                       $sfield = new String($field,'iso-8859-1');
<               }
<       }
<         $nname= is_numeric($field) || '' == $field ? $sname : $sfield;

---
>         $nname= is_numeric($field) || '' == $field ? $sname : $field;
110,113c100
<       if ($obj instanceof String) {
<       if (NULL !== $name) return new self($name,$obj);
<       else return new self((FALSE !== ($p= strrpos($class, '::'))) ? substr($class, $p+ 2): $class, $obj);
<       }else if (!method_exists($obj, '__sleep')) {

---
>       if (!method_exists($obj, '__sleep')) {
160,166c147
<       if (is_string($content)) {
<       try {
<               $content = new String($content,'utf8');
<       } catch (FormatException $e) {
<               $content = new String($content,'iso-8859-1');
<       }
<       }

---
>
186,192c167
<       try {
<               $value = new String($value, 'utf8');
<       } catch(FormatException $e) {
<               $value = new String($value, 'iso-8859-1');
<       }
<       $this->attribute[$name]= $value->toString();
< //      $this->attribute[$name]= $value;

---
>       $this->attribute[$name]= $value;

We also needed to patch the NativeSoapClient.php cause sending parameters to a webservice when the parameter is a xp string would result in an error.

diff -r xp_utf_8_current/webservices/soap/native/NativeSoapClient.class.php xp_utf_8_patch3//webservices/soap/native/NativeSoapClient.class.php
186,188d185
<         if ($parameter->value instanceof String) {
<           return new SoapParam($parameter->value->toString(), $parameter->name);
<         }

One issue still remains by those patches. Since the XP Soap Interface uses the Node.class.php as a base class for setting up the parameters for a webservice call. Those webservice calls won't work when they use a XP String.

Regards

Constantin

util.Properties different behaviour in PHP < 5.3 to later

util.Properties contains a check for the PHP version in its static initializer:

      self::$INI_PARSE_BUG= version_compare(PHP_VERSION, '5.3.0', 'lt');

which will be looked at when trying to parse an .ini file:

      if (self::$INI_PARSE_BUG) {
        $this->_data= $this->parse(file_get_contents($this->_file));
        $error= xp::errorAt(__FILE__, __LINE__ - 1);
      } else {
        $this->_data= parse_ini_file($this->_file, TRUE);
        $error= xp::errorAt(__FILE__, __LINE__ - 1);
      }

$this->parse() and parse_ini_file() (PHP native function) do not behave identically, though: parse_ini_file() would replace values in .ini files that (coincidently?) look like constants by those constants' values. util.Properties' implementation does not do that.

We can discuss whether or not this auto-replacement is a good idea at all... The major PITA here is that the class behaves differently with different PHP versions. I suggest to remove the if-statement here and always use the custom implementation.

Errors when no declarative constraints exist

When fetching table information with the SybaseAdapter class, a fatal error occurs when ASE reports "Object does not have any declarative constraints" and a NULL result set (not an empty one!). This occurs when using ext/mssql.

XP5-Unicode: Cannot communicate with database servers without UTF-8 support

If the server doesn't support the character set "UTF-8", the XP Framework will not be able to communicate with this RDBMS. I suggest to add a character set detection / parameter to DSN in order to support these systems, too. The XP Framework would then take care of character set conversions to Unicode on the client side from the server's character set.

Make Inet6Address accept packed form

The peer.net.Inet6Address uses a packed form internally, as can be seen in the constructor:

<?php
 // ...
    public function __construct($addr) {
      $addr= self::normalize($addr);
      $this->addr= pack('H*', $addr);    
    }
 // ...

In my experimental DNS API, I read the packed data directly from the socket, but then have to convert it as follows:

<?php
  $ip= unpack('H*quads', $input->read(16));
  $dotted= substr(chunk_split($ip['quads'], 4, ':'), 0, -1));

The variable $dotted is now something like 2a00:1450:8007:0000:0000:0000:0000:0068.

What I'd like to be able to do is to directly create the peer.net.Inet6Address instance from the packed data.

run test suite

Using the new directory layout, I wasn't able to run the test suite:

cd ~[root]/xp-framework
unittest core/src/resources/unittest/*.ini

until I set use=[root]/xp-framework/core:[root]/xp-framework/tools:[root]/xp-framework/ports to "`/bin/xp.ini" and created a "~[root]/xp-framework/ports/boot.pth" containing only the "classes" entry.

I tried to add the ports classpath only to the unittest command:

unittest -cp ports/classes core/src/resources/unittest/*.ini

but 2 tests failed:

F unittest.TestError(test= net.xp_lang.tests.integration.ExtensionMethodsIntegrationTest::trimMethod, time= 0.035 seconds) {
  Exception io.IOException (Uncaught exception: Exception lang.ClassNotFoundException (Class "net.xp_lang.tests.integration.ExtensionMethodsIntegrationTestFixture" could not be found)

F unittest.TestAssertionFailed(test= net.xp_lang.tests.integration.ExtensionMethodsIntegrationTest::nonExistantMethod, time= 0.034 seconds) {
  unittest.AssertionFailedError (Expected exception not caught) { expected: [string:"lang.IllegalStateException"] but was: [string:"io.IOException"] }

Is there another way of running the test suite?

Add general EXIF tag accessor

...to fetch any unparsed values directly.

<?php
  // ...
    /**
     * Gets any other key
     *
     * @param   string section
     * @param   string key used case-insensitive
     * @return  string or NULL if nothing can be found
     */
    public function get($section, $key);
  // ...
?>

Dependencies between wrapper parameters

It will be nice to have the possibility to define dependencies between wrapper parameters.

Reason: Sometimes maybe you wish to check if two parameters are mutually exclusive. Or maybe if a param was flagged as mandatory another one (or more) should be mandatory.
Example: If a product has a property size set, it's mandatory to complete also the property color.

This is the actual registration procedure for a wrapper:

registerParamInfo(
$name,
$occurrence= self::OCCURRENCE_UNDEFINED,
$default= NULL,
$caster= NULL,
$precheck= NULL,
$postcheck= NULL,
$type= 'core:string',
$values= array()
)

This could be changed to:

registerParamInfo(
$name,
$occurrence= self::OCCURRENCE_UNDEFINED,
$default= NULL,
$caster= NULL,
$precheck= NULL,
$postcheck= NULL,
$type= 'core:string',
$values= array(),
$dependency= array(),
$exclude= array()
)

And this is a sample wrapper, where param2 depends on param1:

class SampleWrapper extends Wrapper {
public function __construct() {
$this->registerParamInfo(
'param1',
OCCURRENCE_OPTIONAL,
NULL,
NULL,
NULL,
NULL
);
$this->registerParamInfo(
'param2',
OCCURRENCE_OPTIONAL,
NULL,
NULL,
NULL,
NULL,
'core:string',
array(),
array('param1')
);
}
}

Primitives in HashSet cause fatal error in toString()

Reproduce

$ xp -e 'uses("util.collections.HashSet"); $hashset= create("new HashSet<string>"); $hashset->add("hello"); Console::writeLine($hashset->toString());'
Exception lang.Error (Fatal error: Call to a member function toString() on a non-object)
[...]

Regression in lang.XPClass' annotation parser

In commit af2e08d a change to XPClass::detailsForClass() introduced a regression that is not yet covered in any test case - I just stumbled upon it in real-life code.

A class containing this code cannot be parsed:

    /**
     * Enable verboseness
     *
     */
    #[@arg(name= 'verbose', short='v')]
    public function setVerbose() {
      $this->strategy->setVerbose(TRUE);
    }

It fails with:

PHP Parse error:  syntax error, unexpected '=', expecting ')' in /home/ak/dev/xp.public/core/src/main/php/lang/XPClass.class.php(617) : eval()'d code on line 1
Uncaught exception: Exception lang.reflect.TargetInvocationException (xp·command·Runner::main() invocation failed)
  at lang.reflect.Method::invoke(NULL, array[1]) [line 90 of class.php] 
Caused by Exception lang.ClassFormatException (Parse error: Parse error: syntax error, unexpected '=', expecting ')' in /home/ak/dev/xp.public/core/src/main/php/lang/XPClass.class.php(617) : eval()'d code on line 1
 of "@arg(name= 'strategy', short='s')]\n" in de.schlund.install.cmd.Installer, line 32)
  at php.ReflectionClass::newInstanceArgs(array[1]) [line 156 of XPClass.class.php] 
...

lang.FormatException for IPV6 addresses

Reproduce with:

xp -e 'uses("peer.net.NameserverLookup"); $n= new NameserverLookup(); Console::writeLine($n->lookupAll("ipv6.google.com"));'

Results in an lang.FormatException with Given argument does not look like an IP address: and is due to the fact that dns_get_result() will return the IPV6 address in a field called "ipv6", not "ip".

APC support

Inspired by @outofbound in OutOfBound/xp-framework@198587a7d39ab475d5c4 and OutOfBound/xp-framework@5d28a71656dac88d0e72 we should add dev and ino elements to the stream implementations in our class loading infrastructure. This adds support for APC, which as of PHP 5.4 will be built in.

Remove lang.Collection leftovers

lang.Collection is deprecated and was removed from sources; however there are places that still check for this class - these should be adapted.

util.collections.HashSet is not working with floating point numbers

Following test code yields an HashSet with one element instead of the expected ten elements:

$i = 1.0;
$hashset = create('new HashSet');
while ($i < 2) {
$hashset->add($i);
Console::writeLine($i);
$i += 0.1;
}

This problem is caused by the following line in util.collections.HashSet:

$h= $element instanceof Generic ? $element->hashCode() : (is_array($element) ? serialize($element) : $element);
and
$this->_elements[$h]= $element;

Since PHP truncates floats to integers only one element is added.

Proposed fix:
Also serialize floating point keys?
$h= $element instanceof Generic ? $element->hashCode() : ((is_array($element) || is_float($element)) ? serialize($element) : $element);
Edit: Or convert them to a string?

Iterating over empty HashTable

xp -e '

uses("util.collections.HashTable");
$ht=new HashTable(); 
var_dump($ht->size(), $ht->isEmpty()); 
foreach($ht as $i) { var_dump($i); }

'
EXPECTED :
int(0)
bool(true)

ACTUAL:
int(0)
bool(true)
NULL

UnknownRemoteObject exception message

Show the name of the class in UnknownRemoteObject's exception message when accessing members / calling methods.

Example

$ xp -e 'uses("remote.UnknownRemoteObject"); $r= new UnknownRemoteObject("class.Name", array("member" => "value")); $r->member;'

The exception message should contain class.Name in the raised lang.IllegalAccessException's message.

Extend parser for annotations

The following annotation is not parsed correctly

#[@permission(names= array('rn=login, rt=config1', 'rn=login, rt=config2'))]

ScriptletRunner - graceful header handling

The sapi.scriptlet.ScriptletRunner doesn't allow the scriptlet to send its headers by its own. This will cause an exception because sending headers twice isn't allowed.

It is needed to allow scriptlets to send its headers on its own to realize more complex download scriptles, e. g. for CSV downloads.

BC issue: Multiple annotation values

One thing broken by the new annotation parser implementation spawned from pull request #56 are annotations like this:

#[@xmlmapping('hw_server', 'server')] 

These were never officially supported - see RFC #0016 for the syntax definitions - but have rather worked "by accident", but would have to be written as follows:

#[@xmlmapping(array('hw_server', 'server'))] 

At least for the current series, BC should be retained although we could argue it's a bug... so this would be explicitely deprecated and removed in 5.9.0.

Support array shorthand as annotation value

These annotations work:

#[@xmlmapping('hw_server', 'server')] 

...but were never officially supported - see xp-framework/rfc#16 for the syntax definitions. The XP developer mailing list - while discussing how to deal with this currently - came up with the following proposal:

#[@xmlmapping(['hw_server', 'server'])]

...so basically supporting short array syntax.

The "accidental feature" would be dropped in favor of this and a note would be added to the ChangeLog.

Bug in readLine() in io.File

Hi,

I found a bug in io.File.
If you use gets() to read a file line by line you will retrieve FALSE, if you reach the end of the file.
But when you use readLine(), you'll get an empty string instead of FALSE at the end of the file.

<?php
$file= new File($example);
$file->open();

$line= $file->readLine();
while ($line !== FALSE) {
  ...
  $line= $file->readLine();
}
?>

Regards,
Rebecca

Properties::remove*()

Currently the only way to completely delete a section from a property file is:

<?php
  $prop= new Properties();
  // ...
  unset($prop->_data[$section]);
?>

Suggestion is to add a removeSection() method and a removeKey() to complement it.

Quiet mode for unittest command

Add a command line argument -q to suppress all output. Can be useful in conjunction with -l fully.qualified.class.name.of.Listener <output>.

SOAP Driver inconsistencies

In XP driver: setEncoding() will set the character set, in the native driver, setEncoding() will determine whether to use rpc/encoded or document/literal, and setCharset() takes over the job of the first.

This inconsistency should be fixed.

Support GPS tag in ExifData class

Example:

  GPS => [
    gpsversion => ""
    gpslatituderef => "N"
    gpslatitude => [
      0 => "47/1"
      1 => "39/1"
      2 => "5/1"
    ]
    gpslongituderef => "E"
    gpslongitude => [
      0 => "8/1"
      1 => "8/1"
      2 => "33/1"
    ]
    gpsaltituderef => ""
    gpsaltitude => "0/100"
    gpsmeasuremode => "2"
    gpsdop => "5500/100"
  ]

xp::CHARSET

Forward-compatible introduction of a xp::CHARSET constant to remove all hard-coded string constants 'iso-8859-1' (master, sometimes 'iso-8859-15') and 'utf-8' (unicode branch). This way we can replace any utf8_encode() calls with iconv(xp::CHARSET, 'utf-8', ...) and utf8_decode() calls with iconv('utf-8', xp::CHARSET, ...).

JSON Testcase failing

Seems to be related to JSON parser merge (pull request #37) which you probably didn't have on your branch:

unittest core/src/resources/unittest/rest.ini

F unittest.TestAssertionFailed(test= net.xp_framework.unittest.rest.server.transport.JsonHttpRequestAdapterTest::getData, time= 0.005 seconds) {
  unittest.AssertionFailedError (notequal) { expected: [array:[
    some => "thing"
  ]] but was: [array:[
    some => thing
  ]] }

It's a lang.types.String, not a strìng as expected...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.