<?PHP

/* RDFInt.php - RDF Interfaces for PHP
 * Copyright 2011 netlabs.org
 * Author: Christian Langanke, Adrian Gschwend
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// load library setup
define( 'RDFINT', getenv( 'PHP_LIBROOT_RDFINT'));
define( 'FDEBUG_SESSION_NAME', 'RDF Test Cases Unittest');
require_once( RDFINT.'/rdfa.php');
require_once( 'rdftestcases.php');

class UnitTest extends PHPUnit_Framework_TestCase {

  static protected $manifest;

  // --------------------------------------------------------

  // rune once initializer
  public static function setUpBeforeClass() {

    // create manifest data object
    self::$manifest = new RDFTestCasesManifest;

  }

  // --------------------------------------------------------

  // helper: adjusts serialization results so that comparison can work
  // - make all blank node identifiers unique
  // - sort the n-triple lines
  private function _refineResult( $data) {
    // replace all blank nodes by one ID
    // NOTE: thi sis not accurate, but not much better
    // possible without access to the triple data
    $data = preg_replace( '/_:[^ ]*/', '_:a', $data);

    // sort the data
    $adata = explode( "\n", $data);
    sort( &$adata);
    $data = implode( "\n", $adata);

    return $data;
  }

  // --------------------------------------------------------
  // helper: write input and output data to new output
  // directory for manual examination
  private function _writeErrorData( $testcase, $source, $result) {
    if (!is_dir( $testcase->name))
      mkdir( $testcase->name, NULL, true);

    $orgsource = file_get_contents( $testcase->input);
    file_put_contents ( $testcase->name."/org_source.txt" , $orgsource);

    $orgresult = file_get_contents( $testcase->output);
    file_put_contents ( $testcase->name."/org_result.txt" , $orgresult);

    file_put_contents ( $testcase->name."/parsed_source.txt" , $source);
    file_put_contents ( $testcase->name."/parsed_result.txt" , $result);
  }

  // --------------------------------------------------------

  // helper: serialize data from URI to N3
  private function _getSerializedData( $uri) {

    $rdfaData = new \rdfa\Data();
    $this->assertInstanceOf( '\rdfa\Data', $rdfaData);
    $rdfaData->parse( $uri);
    return  $rdfaData->_serialize( 'n3');

  } // private function _getSerializedData

  // --------------------------------------------------------

  public function _executePositiveParserTest( $testcase) {

    // read source data
    $source = $this->_getSerializedData( $testcase->input);
    $this->assertEquals( ($source !== false), true);

    // read target data
    $result = $this->_getSerializedData( $testcase->output);
    $this->assertEquals( ($result !== false), true);

    // resolve problems with blnak node identifiers
    // and different sorting of triples
    $source = $this->_refineResult( $source);
    $result = $this->_refineResult( $result);

    // check if results are equal
    $success = ($source == $result);

    // in case of error, write serialized data to subdirectory
    if (!$success)
      $this->_writeErrorData( $testcase,
                              $source,
                              $result);

    // compare source and target data
    $this->assertEquals( $success, true);

  } // public function test_parse_sparql()


  // --------------------------------------------------------

  public function test() {

    $category = trim( getenv( 'CATEGORY'));
    if ($category == '')
      $categories = self::$manifest->getCategories();
    else
      $categories = array( $type);

    // run test
    // NOTE: all assertions are made in the specific test routine
    foreach ($categories as $category) {
      echo "\nExecuting RDF Test Cases of category: $category\n\n";
      $testcases = self::$manifest->getParserTests( $category);
      foreach ($testcases as $testcase) {

        echo "  Executing: " . $testcase->name . "\n";
        switch ($category) {
          case 'PositiveParserTest':
            $result = $this->_executePositiveParserTest( $testcase);
            break;
        } // switch ($category)
      }
    }

  } // public function test

  // --------------------------------------------------------

  public function disabled_test() {

    // get testcase name again in object context
    $testcase = trim( getenv( 'TESTCASE'));
    $this->assertGreaterThan( 0, strlen( $testcase));

    // read source data
    $sourceuri = self::BASEURI."/$testcase.rdf";
    $source = $this->_getSerializedData( $sourceuri);
    $this->assertEquals( ($source !== false), true);

    // read target data
    $resulturi = self::BASEURI."/$testcase.nt";
    $result = $this->_getSerializedData( $resulturi);
    $this->assertEquals( ($result !== false), true);

    // resolve problems with blnak node identifiers
    // and different sorting of triples
    $source = $this->_refineResult( $source);
    $result = $this->_refineResult( $result);

    // check if results are equal
    $success = ($source == $result);

    // in case of error, write serialized data to subdirectory
    if (!$success)
      $this->_writeErrorData( $testcase,
                              $source, $sourceuri,
                              $result, $resulturi);

    // compare source and target data
    $this->assertEquals( $success, true);


  } // public function test_parse_sparql()


  // --------------------------------------------------------

  public function _dumpTestcaseInfo( $testcases) {
    foreach ($testcases as $testcase) {
      echo "=====================================================================\n";
      echo 'URI: ' . $testcase->getSubject() . "\n";
      echo 'Input: ' . $testcase->input . "\n";
      echo 'Output: ' . $testcase->output . "\n";
      echo 'Conclusion: ' . $testcase->conclusion . "\n";
    }
  }


} // class UnitTest


