From 11bcd88b93a327b9f05b2125e9d59557e753644d Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Fri, 29 May 2020 18:57:17 +0200 Subject: [PATCH] migrate from travis to github actions (#792) ... and run all integration tests in cloud mode, too. --- .github/workflows/run-tests.yml | 51 ++ .travis.yml | 59 -- phpunit.xml.dist => phpunit.xml | 2 + phpunit.xml.travis | 26 - tests/Integration/AbstractCloudTest.php | 95 +++ tests/Integration/AbstractCollectionsTest.php | 88 --- tests/Integration/AbstractCoreTest.php | 578 ------------------ tests/Integration/AbstractServerTest.php | 210 +++++++ .../Integration/AbstractTechproductsTest.php | 577 +++++++++++++---- .../docker/solr7_cloud/docker-compose.yml | 7 + .../docker/solr7_server/docker-compose.yml | 7 + .../docker/solr8_cloud/docker-compose.yml | 7 + .../docker/solr8_server/docker-compose.yml | 7 + .../SolrCloud/CollectionsPsr18Test.php | 14 - .../{CollectionsCurlTest.php => CurlTest.php} | 8 +- .../{CollectionsHttpTest.php => HttpTest.php} | 8 +- tests/Integration/SolrCloud/Psr18Test.php | 14 + .../CurlTest.php} | 10 +- tests/Integration/SolrServer/HttpTest.php | 20 + tests/Integration/SolrServer/Psr18Test.php | 14 + .../TechproductsHttpTest.php | 20 - .../TechproductsPsr18Test.php | 14 - 22 files changed, 914 insertions(+), 922 deletions(-) create mode 100644 .github/workflows/run-tests.yml delete mode 100755 .travis.yml rename phpunit.xml.dist => phpunit.xml (99%) delete mode 100644 phpunit.xml.travis create mode 100644 tests/Integration/AbstractCloudTest.php delete mode 100644 tests/Integration/AbstractCollectionsTest.php delete mode 100644 tests/Integration/AbstractCoreTest.php create mode 100644 tests/Integration/AbstractServerTest.php create mode 100644 tests/Integration/Fixtures/docker/solr7_cloud/docker-compose.yml create mode 100644 tests/Integration/Fixtures/docker/solr7_server/docker-compose.yml create mode 100644 tests/Integration/Fixtures/docker/solr8_cloud/docker-compose.yml create mode 100644 tests/Integration/Fixtures/docker/solr8_server/docker-compose.yml delete mode 100644 tests/Integration/SolrCloud/CollectionsPsr18Test.php rename tests/Integration/SolrCloud/{CollectionsCurlTest.php => CurlTest.php} (71%) rename tests/Integration/SolrCloud/{CollectionsHttpTest.php => HttpTest.php} (54%) create mode 100644 tests/Integration/SolrCloud/Psr18Test.php rename tests/Integration/{TechproductsAdapters/TechproductsCurlTest.php => SolrServer/CurlTest.php} (64%) create mode 100644 tests/Integration/SolrServer/HttpTest.php create mode 100644 tests/Integration/SolrServer/Psr18Test.php delete mode 100644 tests/Integration/TechproductsAdapters/TechproductsHttpTest.php delete mode 100644 tests/Integration/TechproductsAdapters/TechproductsPsr18Test.php diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 000000000..ace93dfa6 --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,51 @@ +name: Run Tests + +on: + push: + + schedule: + - cron: '0 8 * * *' # run at 08:00 UTC + +jobs: + run-tests: + runs-on: ubuntu-latest + + strategy: + matrix: + php: [7.2, 7.3, 7.4] + solr: [7, 8] + mode: [cloud, server] + symfony: [4.3.*, 4.4.*, 5.0.*] + + name: PHP ${{ matrix.php }}, symfony ${{ matrix.symfony }}, Solr ${{ matrix.solr }} ${{ matrix.mode }} + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, intl, iconv, json, simplexml + ini-values: memory_limit=256M,post_max_size=256M + coverage: pcov + + - name: Checkout solarium + uses: actions/checkout@v2 + + - name: Start Solr ${{ matrix.solr }} in ${{ matrix.mode }} mode + run: | + cd tests/Integration/Fixtures/docker/solr${{ matrix.solr }}_${{ matrix.mode }} + docker-compose up -d + + - name: Install dependencies + run: | + composer global require hirak/prestissimo + composer require --dev symfony/event-dispatcher:${{ matrix.symfony }} + + - name: Run tests + env: + COVERALLS_RUN_LOCALLY: 1 + COVERALLS_REPO_TOKEN: + run: | + vendor/bin/phpstan analyze src/ tests/ --level=1 + vendor/bin/phpunit -c phpunit.xml --exclude-group skip_for_solr_${{ matrix.mode }} -v + vendor/bin/php-coveralls -v --dry-run diff --git a/.travis.yml b/.travis.yml deleted file mode 100755 index 6d3c66599..000000000 --- a/.travis.yml +++ /dev/null @@ -1,59 +0,0 @@ -language: php - -# Solr 6.x doesn't work with the Java versions included in "xenial" or "bionic". -dist: trusty - -php: - - 7.4 - - 7.3 - - 7.2 - # phpunit/phpunit 8.0.0 requires php ^7.2 -> your PHP version (7.1.11) does not satisfy that requirement. - #- 7.1 - -env: - - SYMFONY_VERSION=5.0.* SOLR_VERSION=8.5.1 SOLR_CLOUD=true - - SYMFONY_VERSION=5.0.* SOLR_VERSION=8.5.1 SOLR_CLOUD=false - - SYMFONY_VERSION=4.4.* SOLR_VERSION=8.5.1 SOLR_CLOUD=true - - SYMFONY_VERSION=4.3.* SOLR_VERSION=8.5.1 SOLR_CLOUD=false - - SYMFONY_VERSION=4.4.* SOLR_VERSION=7.7.3 SOLR_CLOUD=true - - SYMFONY_VERSION=4.3.* SOLR_VERSION=7.7.3 SOLR_CLOUD=false - -cache: - directories: - - $HOME/.composer/cache - - solr_downloads - -before_install: - - composer global require "hirak/prestissimo:^0.3" - - ls solr_downloads/ - - wget -nc --continue -v --tries=3 --directory-prefix=solr_downloads "http://archive.apache.org/dist/lucene/solr/${SOLR_VERSION}/solr-${SOLR_VERSION}.tgz" - - tar -xzf solr_downloads/solr-${SOLR_VERSION}.tgz - -before_script: -# - pecl install pecl_http - - composer require --dev symfony/event-dispatcher:${SYMFONY_VERSION} - - | - if [ ${SOLR_CLOUD} == "true" ]; then - solr-${SOLR_VERSION}/bin/solr start -e cloud -noprompt || travis_terminate 1; - solr-${SOLR_VERSION}/bin/solr delete -c gettingstarted || travis_terminate 1; - solr-${SOLR_VERSION}/bin/solr create -c techproducts -s 2 -rf 2 -d solr-${SOLR_VERSION}/server/solr/configsets/sample_techproducts_configs/conf -n sample_techproducts_configs || travis_terminate 1; - solr-${SOLR_VERSION}/bin/post -c techproducts solr-${SOLR_VERSION}/example/exampledocs/*.xml || travis_terminate 1; - else - solr-${SOLR_VERSION}/bin/solr start -e techproducts || travis_terminate 1; - # make configsets available for techproducts instance for core admin tests - cp -R solr-${SOLR_VERSION}/server/solr/configsets solr-${SOLR_VERSION}/example/techproducts/solr/ || travis_terminate 1; - fi - -script: - - vendor/bin/phpstan analyze src/ tests/ --level=1 - - | - if [ ${SOLR_CLOUD} == "true" ]; then - vendor/bin/phpunit -c phpunit.xml.travis --exclude-group solr_no_cloud -v || travis_terminate 1; - else - vendor/bin/phpunit -c phpunit.xml.travis --exclude-group solr_cloud -v || travis_terminate 1; - fi - -after_success: - - travis_retry php vendor/bin/php-coveralls -v - -sudo: false diff --git a/phpunit.xml.dist b/phpunit.xml similarity index 99% rename from phpunit.xml.dist rename to phpunit.xml index 9839279ab..1e53e9a27 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml @@ -6,6 +6,7 @@ backupStaticAttributes="false" colors="true" > + tests @@ -23,4 +24,5 @@ src + diff --git a/phpunit.xml.travis b/phpunit.xml.travis deleted file mode 100644 index 3d4eeea53..000000000 --- a/phpunit.xml.travis +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - tests - - - - - - - - - - src - - - - diff --git a/tests/Integration/AbstractCloudTest.php b/tests/Integration/AbstractCloudTest.php new file mode 100644 index 000000000..089fb2793 --- /dev/null +++ b/tests/Integration/AbstractCloudTest.php @@ -0,0 +1,95 @@ + [ + 'localhost' => [ + 'host' => '127.0.0.1', + 'port' => 8983, + 'path' => '/', + 'collection' => self::$name, + ], + ], + ]; + + self::$client = TestClientFactory::createWithPsr18Adapter(self::$config); + + $collectionsQuery = self::$client->createCollections(); + + // create core with unique name using the techproducts configset + $createAction = $collectionsQuery->createCreate(); + $createAction->setName(self::$name) + ->setCollectionConfigName('techproducts') + ->setNumShards(2); + $collectionsQuery->setAction($createAction); + $response = self::$client->collections($collectionsQuery); + static::assertTrue($response->getWasSuccessful()); + } + + public static function tearDownAfterClass(): void + { + $collectionsQuery = self::$client->createCollections(); + + // now we delete the collection we created in setUpBeforeClass() + $deleteAction = $collectionsQuery->createDelete(); + $deleteAction->setName(self::$name); + $collectionsQuery->setAction($deleteAction); + $response = self::$client->collections($collectionsQuery); + static::assertTrue($response->getWasSuccessful()); + } + + public function testCreateDelete() + { + $collectionsQuery = self::$client->createCollections(); + + $action = $collectionsQuery->createCreate(); + $action->setName('test'); + $action->setNumShards(1); + $collectionsQuery->setAction($action); + $result = self::$client->collections($collectionsQuery); + $this->assertTrue($result->getWasSuccessful()); + + $action = $collectionsQuery->createDelete(); + $action->setName('test'); + $collectionsQuery->setAction($action); + $result = self::$client->collections($collectionsQuery); + $this->assertTrue($result->getWasSuccessful()); + } + + public function testReload() + { + $collectionsQuery = self::$client->createCollections(); + + $action = $collectionsQuery->createReload(); + $action->setName(self::$name); + $collectionsQuery->setAction($action); + $result = self::$client->collections($collectionsQuery); + $this->assertTrue($result->getWasSuccessful()); + } + + public function testClusterStatus() + { + $collectionsQuery = self::$client->createCollections(); + + $action = $collectionsQuery->createClusterStatus(); + $collectionsQuery->setAction($action); + $result = self::$client->collections($collectionsQuery); + $this->assertTrue($result->getWasSuccessful()); + $clusterState = $result->getClusterState(); + $this->assertSame(ClusterState::class, get_class($clusterState)); + $this->assertCount(2, $clusterState->getLiveNodes()); + $this->assertCount(1, $clusterState->getCollections()); + $this->assertTrue($clusterState->collectionExists(self::$name)); + } +} diff --git a/tests/Integration/AbstractCollectionsTest.php b/tests/Integration/AbstractCollectionsTest.php deleted file mode 100644 index ca23efd32..000000000 --- a/tests/Integration/AbstractCollectionsTest.php +++ /dev/null @@ -1,88 +0,0 @@ - [ - 'localhost' => [ - 'host' => '127.0.0.1', - 'port' => 8983, - 'path' => '/', - 'collection' => $this->collection, - ], - ], - ]; - - $this->client = TestClientFactory::createWithPsr18Adapter($config); - - try { - $ping = $this->client->createPing(); - $this->client->ping($ping); - } catch (\Exception $e) { - $this->markTestSkipped('SolrCloud techproducts example not reachable.'); - } - - $this->query = $this->client->createCollections(); - } - - public function testCreateDelete() - { - $action = $this->query->createCreate(); - $action->setName('test'); - $action->setNumShards(1); - $this->query->setAction($action); - $result = $this->client->collections($this->query); - $this->assertTrue($result->getWasSuccessful()); - - $action = $this->query->createDelete(); - $action->setName('test'); - $this->query->setAction($action); - $result = $this->client->collections($this->query); - $this->assertTrue($result->getWasSuccessful()); - } - - public function testReload() - { - $action = $this->query->createReload(); - $action->setName($this->collection); - $this->query->setAction($action); - $result = $this->client->collections($this->query); - $this->assertTrue($result->getWasSuccessful()); - } - - public function testClusterStatus() - { - $action = $this->query->createClusterStatus(); - $this->query->setAction($action); - $result = $this->client->collections($this->query); - $this->assertTrue($result->getWasSuccessful()); - $clusterState = $result->getClusterState(); - $this->assertSame(ClusterState::class, get_class($clusterState)); - $this->assertCount(2, $clusterState->getLiveNodes()); - $this->assertCount(1, $clusterState->getCollections()); - $this->assertTrue($clusterState->collectionExists('techproducts')); - } -} diff --git a/tests/Integration/AbstractCoreTest.php b/tests/Integration/AbstractCoreTest.php deleted file mode 100644 index 747ab4391..000000000 --- a/tests/Integration/AbstractCoreTest.php +++ /dev/null @@ -1,578 +0,0 @@ - [ - 'localhost' => [ - 'host' => '127.0.0.1', - 'port' => 8983, - 'path' => '/', - 'core' => self::$core, - ], - ], - ]; - - $client = TestClientFactory::createWithPsr18Adapter(self::$config); - - try { - $coreAdminQuery = $client->createCoreAdmin(); - - // create core with unique name using the techproducts configset - $createAction = $coreAdminQuery->createCreate(); - $createAction->setCore(self::$core); - $createAction->setConfigSet('sample_techproducts_configs'); - $coreAdminQuery->setAction($createAction); - $response = $client->coreAdmin($coreAdminQuery); - static::assertTrue($response->getWasSuccessful()); - - $ping = $client->createPing(); - $client->ping($ping); - } catch (\Exception $e) { - static::markTestSkipped('Solr techproducts example not reachable.'); - } - - try { - // index techproducts sample data - foreach (glob(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'techproducts'.DIRECTORY_SEPARATOR.'*.xml') as $file) { - $update = $client->createUpdate(); - - if (null !== $encoding = self::getXmlEncoding($file)) { - $update->setInputEncoding($encoding); - } - - $update->addRawXmlFile($file); - $client->update($update); - } - - $update = $client->createUpdate(); - $update->addCommit(true, true); - $client->update($update); - - // check that everything was indexed properly - $select = $client->createSelect(); - $select->setFields('id'); - $result = $client->select($select); - static::assertSame(32, $result->getNumFound()); - - $select->setQuery('êâîôû'); - $result = $client->select($select); - static::assertCount(1, $result); - static::assertSame([ - 'id' => 'UTF8TEST', - ], $result->getIterator()->current()->getFields()); - - $select->setQuery('这是一个功能'); - $result = $client->select($select); - static::assertCount(1, $result); - static::assertSame([ - 'id' => 'GB18030TEST', - ], $result->getIterator()->current()->getFields()); - } catch (\Exception $e) { - self::tearDownAfterClass(); - static::markTestSkipped('Solr techproducts sample data not indexed properly.'); - } - } - - public static function tearDownAfterClass(): void - { - $client = TestClientFactory::createWithPsr18Adapter(self::$config); - - $coreAdminQuery = $client->createCoreAdmin(); - - // now we unload the core we created in setUpBeforeClass() - $unloadAction = $coreAdminQuery->createUnload(); - $unloadAction->setCore(self::$core); - $unloadAction->setDeleteDataDir(true)->setDeleteIndex(true)->setDeleteInstanceDir(true); - $coreAdminQuery->setAction($unloadAction); - $response = $client->coreAdmin($coreAdminQuery); - static::assertTrue($response->getWasSuccessful()); - } - - public function setUp(): void - { - $this->client = TestClientFactory::createWithPsr18Adapter(self::$config); - - try { - $ping = $this->client->createPing(); - $this->client->ping($ping); - } catch (\Exception $e) { - $this->markTestSkipped('Solr techproducts example not reachable.'); - } - } - - public function testCanReloadCore() - { - $coreAdminQuery = $this->client->createCoreAdmin(); - $reloadAction = $coreAdminQuery->createReload(); - $reloadAction->setCore(self::$core); - $coreAdminQuery->setAction($reloadAction); - - $result = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($result->getWasSuccessful()); - - // reloading a non existing core should not be successful - $this->expectException(HttpException::class); - $reloadAction2 = $coreAdminQuery->createReload(); - $reloadAction2->setCore('nonExistingCore'); - $coreAdminQuery->setAction($reloadAction2); - $this->client->coreAdmin($coreAdminQuery); - } - - public function testCoreAdminStatus() - { - $coreAdminQuery = $this->client->createCoreAdmin(); - $statusAction = $coreAdminQuery->createStatus(); - $statusAction->setCore(self::$core); - - $coreAdminQuery->setAction($statusAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $json = json_decode($response->getResponse()->getBody()); - $this->assertTrue($response->getWasSuccessful()); - $this->assertGreaterThanOrEqual(0, $json->responseHeader->QTime); - $this->assertNotNull($response->getStatusResult()->getUptime()); - $this->assertGreaterThan(0, $response->getStatusResult()->getStartTime()->format('U')); - // lastModified is either null for a very fresh core or a valid DateTime - $this->assertThat($response->getStatusResult()->getLastModified(), $this->logicalOr( - $this->isNull(), - $this->isInstanceOf(\DateTime::class) - )); - $this->assertSame(self::$core, $response->getStatusResult()->getCoreName()); - - $statusAction = $coreAdminQuery->createStatus(); - $statusAction->setCore('unknowncore'); - - $coreAdminQuery->setAction($statusAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - $this->assertSame(0, $response->getStatusResult()->getUptime()); - $this->assertNull($response->getStatusResult()->getLastModified()); - $this->assertNull($response->getStatusResult()->getStartTime()); - } - - public function testSplitAndMerge() - { - $coreAdminQuery = $this->client->createCoreAdmin(); - // create core *_a - $createAction = $coreAdminQuery->createCreate(); - $createAction->setCore(self::$core.'_a'); - $createAction->setConfigSet('sample_techproducts_configs'); - $coreAdminQuery->setAction($createAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - - // create core *_b - $createAction = $coreAdminQuery->createCreate(); - $createAction->setCore(self::$core.'_b'); - $createAction->setConfigSet('sample_techproducts_configs'); - $coreAdminQuery->setAction($createAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - - // split the original core into *_a and *_b - $splitAction = $coreAdminQuery->createSplit(); - $splitAction->setCore(self::$core); - $splitAction->setTargetCore([self::$core.'_a', self::$core.'_b']); - $coreAdminQuery->setAction($splitAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - - // reload core *_a - $reloadAction = $coreAdminQuery->createReload(); - $reloadAction->setCore(self::$core.'_a'); - $coreAdminQuery->setAction($reloadAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - - // reload core *_b - $reloadAction = $coreAdminQuery->createReload(); - $reloadAction->setCore(self::$core.'_b'); - $coreAdminQuery->setAction($reloadAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - - // check that we have 32 documents in the original core, 16 in *_a and 16 in *_b - $statusAction = $coreAdminQuery->createStatus(); - $statusAction->setCore(self::$core); - $coreAdminQuery->setAction($statusAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - $this->assertSame(32, $response->getStatusResult()->getNumberOfDocuments()); - - $statusAction = $coreAdminQuery->createStatus(); - $statusAction->setCore(self::$core.'_a'); - $coreAdminQuery->setAction($statusAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - $this->assertSame(16, $response->getStatusResult()->getNumberOfDocuments()); - - $statusAction = $coreAdminQuery->createStatus(); - $statusAction->setCore(self::$core.'_b'); - $coreAdminQuery->setAction($statusAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - $this->assertSame(16, $response->getStatusResult()->getNumberOfDocuments()); - // now we cleanup the created cores - $unloadAction = $coreAdminQuery->createUnload(); - $unloadAction->setCore(self::$core.'_a'); - $unloadAction->setDeleteDataDir(true)->setDeleteIndex(true)->setDeleteInstanceDir(true); - $coreAdminQuery->setAction($unloadAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - - $unloadAction = $coreAdminQuery->createUnload(); - $unloadAction->setCore(self::$core.'_b'); - $unloadAction->setDeleteDataDir(true)->setDeleteIndex(true)->setDeleteInstanceDir(true); - $coreAdminQuery->setAction($unloadAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - } - - public function testGetStatusFromAllCoreWhenNoCoreNameWasSet() - { - $coreAdminQuery = $this->client->createCoreAdmin(); - - // create new core using the techproducts config set - $createAction = $coreAdminQuery->createCreate(); - $createAction->setCore(self::$core.'_new'); - $createAction->setConfigSet('sample_techproducts_configs'); - $coreAdminQuery->setAction($createAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - - // we now have three cores and when we retrieve the status for all we should have three status objects - // (the original techproducts, the core we created in setUpBeforeClass() and the one we created just now) - $statusAction = $coreAdminQuery->createStatus(); - $coreAdminQuery->setAction($statusAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - - $statusResults = $response->getStatusResults(); - $this->assertCount(3, $statusResults); - $this->assertGreaterThan(0, $statusResults[0]->getUptime(), 'Can not get uptime of first core'); - - // now we unload the created core again - $unloadAction = $coreAdminQuery->createUnload(); - $unloadAction->setCore(self::$core.'_new'); - $unloadAction->setDeleteDataDir(true)->setDeleteIndex(true)->setDeleteInstanceDir(true); - $coreAdminQuery->setAction($unloadAction); - $response = $this->client->coreAdmin($coreAdminQuery); - $this->assertTrue($response->getWasSuccessful()); - } - - public function testManagedStopwords() - { - $query = $this->client->createManagedStopwords(); - $query->setName('english'); - $term = 'managed_stopword_test'; - - // Add stopwords - $add = new AddStopwords(); - $add->setStopwords([$term]); - $query->setCommand($add); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check if single stopword exists - $exists = new ExistsStopwords(); - $exists->setTerm($term); - $query->setCommand($exists); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // We need to remove the current command in order to have no command. Having no command lists the items. - $query->removeCommand(); - - // List stopwords - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - $items = $result->getItems(); - $this->assertContains($term, $items); - - // Delete stopword - $delete = new DeleteStopwords(); - $delete->setTerm($term); - $query->setCommand($delete); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check if stopword is gone - $this->expectException(HttpException::class); - $exists = new ExistsStopwords(); - $exists->setTerm($term); - $query->setCommand($exists); - $this->client->execute($query); - } - - public function testManagedStopwordsCreation() - { - $query = $this->client->createManagedStopwords(); - $query->setName(uniqid()); - $term = 'managed_stopword_test'; - - // Create a new stopword list - $create = new CreateStopwords(); - $query->setCommand($create); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Whatever happens next ... - try { - // Configure the new list to be case sensitive - $initArgs = new InitArgsStopwords(); - $initArgs->setIgnoreCase(false); - $config = new ConfigStopwords(); - $config->setInitArgs($initArgs); - $query->setCommand($config); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check the configuration - $query->removeCommand(); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - $this->assertFalse($result->isIgnoreCase()); - - // Check if we can add to it - $add = new AddStopwords(); - $add->setStopwords([$term]); - $query->setCommand($add); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check if stopword exists in its original lowercase form - $exists = new ExistsStopwords(); - $exists->setTerm($term); - $query->setCommand($exists); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check if stopword DOESN'T exist in uppercase form - $this->expectException(HttpException::class); - $exists->setTerm(strtoupper($term)); - $query->setCommand($exists); - $this->client->execute($query); - } - // ... we have to remove the created resource! - finally { - // Remove the stopword list - $remove = new RemoveStopwords(); - $query->setCommand($remove); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check if stopword list is gone - $this->expectException(HttpException::class); - $query->removeCommand(); - $this->client->execute($query); - } - } - - public function testManagedSynonyms() - { - $query = $this->client->createManagedSynonyms(); - $query->setName('english'); - $term = 'managed_synonyms_test'; - - // Add synonyms - $add = new AddSynonyms(); - $synonyms = new Synonyms(); - $synonyms->setTerm($term); - $synonyms->setSynonyms(['managed_synonym', 'synonym_test']); - $add->setSynonyms($synonyms); - $query->setCommand($add); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check if single synonym exists - $exists = new ExistsSynonyms(); - $exists->setTerm($term); - $query->setCommand($exists); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - $this->assertSame(['managed_synonyms_test' => ['managed_synonym', 'synonym_test']], $result->getData()); - - // We need to remove the current command in order to have no command. Having no command lists the items. - $query->removeCommand(); - - // List synonyms - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - $items = $result->getItems(); - $success = false; - foreach ($items as $item) { - if ('managed_synonyms_test' === $item->getTerm()) { - $success = true; - } - } - if (!$success) { - $this->fail('Couldn\'t find synonym.'); - } - - // Delete synonyms - $delete = new DeleteSynonyms(); - $delete->setTerm($term); - $query->setCommand($delete); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check if synonyms are gone - $this->expectException(HttpException::class); - $exists = new ExistsSynonyms(); - $exists->setTerm($term); - $query->setCommand($exists); - $this->client->execute($query); - } - - public function testManagedSynonymsCreation() - { - $query = $this->client->createManagedSynonyms(); - $query->setName(uniqid()); - $term = 'managed_synonyms_test'; - - // Create a new synonym map - $create = new CreateSynonyms(); - $query->setCommand($create); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Whatever happens next ... - try { - // Configure the new map to be case sensitive and use the 'solr' format - $initArgs = new InitArgsSynonyms(); - $initArgs->setIgnoreCase(false); - $initArgs->setFormat(InitArgsSynonyms::FORMAT_SOLR); - $config = new ConfigSynonyms(); - $config->setInitArgs($initArgs); - $query->setCommand($config); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check the configuration - $query->removeCommand(); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - $this->assertFalse($result->isIgnoreCase()); - $this->assertEquals(InitArgsSynonyms::FORMAT_SOLR, $result->getFormat()); - - // Check if we can add to it - $add = new AddSynonyms(); - $synonyms = new Synonyms(); - $synonyms->setTerm($term); - $synonyms->setSynonyms(['managed_synonym', 'synonym_test']); - $add->setSynonyms($synonyms); - $query->setCommand($add); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check if synonym exists in its original lowercase form - $exists = new ExistsSynonyms(); - $exists->setTerm($term); - $query->setCommand($exists); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - $this->assertSame(['managed_synonyms_test' => ['managed_synonym', 'synonym_test']], $result->getData()); - - // Check if synonym DOESN'T exist in uppercase form - $this->expectException(HttpException::class); - $exists->setTerm(strtoupper($term)); - $query->setCommand($exists); - $this->client->execute($query); - } - // ... we have to remove the created resource! - finally { - // Remove the synonym map - $remove = new RemoveSynonyms(); - $query->setCommand($remove); - $result = $this->client->execute($query); - $this->assertEquals(200, $result->getResponse()->getStatusCode()); - - // Check if synonym map is gone - $this->expectException(HttpException::class); - $query->removeCommand(); - $this->client->execute($query); - } - } - - public function testManagedResources() - { - // Check if we can find the 2 default managed resources - // (and account for additional resources we might have created while testing) - $query = $this->client->createManagedResources(); - $result = $this->client->execute($query); - $items = $result->getItems(); - $this->assertGreaterThanOrEqual(2, count($items)); - } - - /** - * Extracts the encoding from the XML declaration of a file if present. - * - * @param string $file - * - * @return string|null - */ - private static function getXmlEncoding(string $file): ?string - { - $encoding = null; - - $xml = file_get_contents($file); - - if (false !== $xml) { - // discard UTF-8 Byte Order Mark - if (pack('CCC', 0xEF, 0xBB, 0xBF) === substr($xml, 0, 3)) { - $xml = substr($xml, 3); - } - - // detect XML declaration - if ('') + 2); - - // detect encoding attribute - if (false !== $pos = strpos($declaration, 'encoding="')) { - $encoding = substr($declaration, $pos + 10, strpos($declaration, '"', $pos + 10) - $pos - 10); - } - } - } - - return $encoding; - } -} diff --git a/tests/Integration/AbstractServerTest.php b/tests/Integration/AbstractServerTest.php new file mode 100644 index 000000000..c31e4b8b8 --- /dev/null +++ b/tests/Integration/AbstractServerTest.php @@ -0,0 +1,210 @@ + [ + 'localhost' => [ + 'host' => '127.0.0.1', + 'port' => 8983, + 'path' => '/', + 'core' => self::$name, + ], + ], + ]; + + self::$client = TestClientFactory::createWithPsr18Adapter(self::$config); + + $coreAdminQuery = self::$client->createCoreAdmin(); + + // create core with unique name using the techproducts configset + $createAction = $coreAdminQuery->createCreate(); + $createAction->setCore(self::$name) + ->setConfigSet('sample_techproducts_configs'); + $coreAdminQuery->setAction($createAction); + $response = self::$client->coreAdmin($coreAdminQuery); + static::assertTrue($response->getWasSuccessful()); + } + + public static function tearDownAfterClass(): void + { + $coreAdminQuery = self::$client->createCoreAdmin(); + + // now we unload the core we created in setUpBeforeClass() + $unloadAction = $coreAdminQuery->createUnload(); + $unloadAction->setCore(self::$name) + ->setDeleteDataDir(true) + ->setDeleteIndex(true) + ->setDeleteInstanceDir(true); + $coreAdminQuery->setAction($unloadAction); + $response = self::$client->coreAdmin($coreAdminQuery); + static::assertTrue($response->getWasSuccessful()); + } + + public function testCanReloadCore() + { + $coreAdminQuery = self::$client->createCoreAdmin(); + $reloadAction = $coreAdminQuery->createReload(); + $reloadAction->setCore(self::$name); + $coreAdminQuery->setAction($reloadAction); + + $result = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($result->getWasSuccessful()); + + // reloading a non existing core should not be successful + $this->expectException(HttpException::class); + $reloadAction2 = $coreAdminQuery->createReload(); + $reloadAction2->setCore('nonExistingCore'); + $coreAdminQuery->setAction($reloadAction2); + self::$client->coreAdmin($coreAdminQuery); + } + + public function testCoreAdminStatus() + { + $coreAdminQuery = self::$client->createCoreAdmin(); + $statusAction = $coreAdminQuery->createStatus(); + $statusAction->setCore(self::$name); + + $coreAdminQuery->setAction($statusAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $json = json_decode($response->getResponse()->getBody()); + $this->assertTrue($response->getWasSuccessful()); + $this->assertGreaterThanOrEqual(0, $json->responseHeader->QTime); + $this->assertNotNull($response->getStatusResult()->getUptime()); + $this->assertGreaterThan(0, $response->getStatusResult()->getStartTime()->format('U')); + // lastModified is either null for a very fresh core or a valid DateTime + $this->assertThat($response->getStatusResult()->getLastModified(), $this->logicalOr( + $this->isNull(), + $this->isInstanceOf(\DateTime::class) + )); + $this->assertSame(self::$name, $response->getStatusResult()->getCoreName()); + + $statusAction = $coreAdminQuery->createStatus(); + $statusAction->setCore('unknowncore'); + + $coreAdminQuery->setAction($statusAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + $this->assertSame(0, $response->getStatusResult()->getUptime()); + $this->assertNull($response->getStatusResult()->getLastModified()); + $this->assertNull($response->getStatusResult()->getStartTime()); + } + + public function testSplitAndMerge() + { + $coreAdminQuery = self::$client->createCoreAdmin(); + // create core *_a + $createAction = $coreAdminQuery->createCreate(); + $createAction->setCore(self::$name.'_a'); + $createAction->setConfigSet('sample_techproducts_configs'); + $coreAdminQuery->setAction($createAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + + // create core *_b + $createAction = $coreAdminQuery->createCreate(); + $createAction->setCore(self::$name.'_b'); + $createAction->setConfigSet('sample_techproducts_configs'); + $coreAdminQuery->setAction($createAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + + // split the original core into *_a and *_b + $splitAction = $coreAdminQuery->createSplit(); + $splitAction->setCore(self::$name); + $splitAction->setTargetCore([self::$name.'_a', self::$name.'_b']); + $coreAdminQuery->setAction($splitAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + + // reload core *_a + $reloadAction = $coreAdminQuery->createReload(); + $reloadAction->setCore(self::$name.'_a'); + $coreAdminQuery->setAction($reloadAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + + // reload core *_b + $reloadAction = $coreAdminQuery->createReload(); + $reloadAction->setCore(self::$name.'_b'); + $coreAdminQuery->setAction($reloadAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + + // check that we have 32 documents in the original core, 16 in *_a and 16 in *_b + $statusAction = $coreAdminQuery->createStatus(); + $statusAction->setCore(self::$name); + $coreAdminQuery->setAction($statusAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + $this->assertSame(32, $response->getStatusResult()->getNumberOfDocuments()); + + $statusAction = $coreAdminQuery->createStatus(); + $statusAction->setCore(self::$name.'_a'); + $coreAdminQuery->setAction($statusAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + $this->assertSame(16, $response->getStatusResult()->getNumberOfDocuments()); + + $statusAction = $coreAdminQuery->createStatus(); + $statusAction->setCore(self::$name.'_b'); + $coreAdminQuery->setAction($statusAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + $this->assertSame(16, $response->getStatusResult()->getNumberOfDocuments()); + // now we cleanup the created cores + $unloadAction = $coreAdminQuery->createUnload(); + $unloadAction->setCore(self::$name.'_a'); + $unloadAction->setDeleteDataDir(true)->setDeleteIndex(true)->setDeleteInstanceDir(true); + $coreAdminQuery->setAction($unloadAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + + $unloadAction = $coreAdminQuery->createUnload(); + $unloadAction->setCore(self::$name.'_b'); + $unloadAction->setDeleteDataDir(true)->setDeleteIndex(true)->setDeleteInstanceDir(true); + $coreAdminQuery->setAction($unloadAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + } + + public function testGetStatusFromAllCoresWhenNoCoreNameWasSet() + { + $coreAdminQuery = self::$client->createCoreAdmin(); + + // create new core using the techproducts config set + $createAction = $coreAdminQuery->createCreate(); + $createAction->setCore(self::$name.'_new'); + $createAction->setConfigSet('sample_techproducts_configs'); + $coreAdminQuery->setAction($createAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + + // we now have two cores and when we retrieve the status for all we should have three status objects + // (the core we created in setUpBeforeClass() and the one we created just now) + $statusAction = $coreAdminQuery->createStatus(); + $coreAdminQuery->setAction($statusAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + + $statusResults = $response->getStatusResults(); + $this->assertCount(2, $statusResults); + $this->assertGreaterThan(0, $statusResults[0]->getUptime(), 'Can not get uptime of first core'); + + // now we unload the created core again + $unloadAction = $coreAdminQuery->createUnload(); + $unloadAction->setCore(self::$name.'_new'); + $unloadAction->setDeleteDataDir(true)->setDeleteIndex(true)->setDeleteInstanceDir(true); + $coreAdminQuery->setAction($unloadAction); + $response = self::$client->coreAdmin($coreAdminQuery); + $this->assertTrue($response->getWasSuccessful()); + } + +} diff --git a/tests/Integration/AbstractTechproductsTest.php b/tests/Integration/AbstractTechproductsTest.php index 3e8e1ca36..16e60b77a 100644 --- a/tests/Integration/AbstractTechproductsTest.php +++ b/tests/Integration/AbstractTechproductsTest.php @@ -8,6 +8,22 @@ use Solarium\Component\Result\Terms\Result; use Solarium\Core\Client\ClientInterface; use Solarium\Core\Client\Request; +use Solarium\Exception\HttpException; +use Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Add as AddStopwords; +use Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Config as ConfigStopwords; +use Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Create as CreateStopwords; +use Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Delete as DeleteStopwords; +use Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Exists as ExistsStopwords; +use Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Remove as RemoveStopwords; +use Solarium\QueryType\ManagedResources\Query\Stopwords\InitArgs as InitArgsStopwords; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Add as AddSynonyms; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Config as ConfigSynonyms; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Create as CreateSynonyms; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Delete as DeleteSynonyms; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Exists as ExistsSynonyms; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Remove as RemoveSynonyms; +use Solarium\QueryType\ManagedResources\Query\Synonyms\InitArgs as InitArgsSynonyms; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Synonyms; use Solarium\QueryType\Select\Query\Query as SelectQuery; use Solarium\QueryType\Select\Result\Document; @@ -16,23 +32,86 @@ abstract class AbstractTechproductsTest extends TestCase /** * @var ClientInterface */ - protected $client; + protected static $client; + + /** + * @var string + */ + protected static $name; + + /** + * @var array + */ + protected static $config; + + abstract protected static function createTechproducts(): void; + + public static function setUpBeforeClass(): void + { + self::$name = uniqid(); + + static::createTechproducts(); + + $ping = self::$client->createPing(); + self::$client->ping($ping); + + try { + // index techproducts sample data + foreach (glob(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'techproducts'.DIRECTORY_SEPARATOR.'*.xml') as $file) { + $update = self::$client->createUpdate(); + + if (null !== $encoding = self::getXmlEncoding($file)) { + $update->setInputEncoding($encoding); + } + + $update->addRawXmlFile($file); + self::$client->update($update); + } + + $update = self::$client->createUpdate(); + $update->addCommit(true, true); + self::$client->update($update); + + // check that everything was indexed properly + $select = self::$client->createSelect(); + $select->setFields('id'); + $result = self::$client->select($select); + static::assertSame(32, $result->getNumFound()); + + $select->setQuery('êâîôû'); + $result = self::$client->select($select); + static::assertCount(1, $result); + static::assertSame([ + 'id' => 'UTF8TEST', + ], $result->getIterator()->current()->getFields()); + + $select->setQuery('这是一个功能'); + $result = self::$client->select($select); + static::assertCount(1, $result); + static::assertSame([ + 'id' => 'GB18030TEST', + ], $result->getIterator()->current()->getFields()); + } catch (\Exception $e) { + self::tearDownAfterClass(); + static::markTestSkipped('Solr techproducts sample data not indexed properly.'); + } + } /** * The ping test succeeds if no exception is thrown. */ public function testPing() { - $ping = $this->client->createPing(); - $result = $this->client->ping($ping); + $ping = self::$client->createPing(); + $result = self::$client->ping($ping); $this->assertSame(0, $result->getStatus()); } public function testSelect() { - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); $select->setSorts(['id' => SelectQuery::SORT_ASC]); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(32, $result->getNumFound()); $this->assertCount(10, $result); @@ -57,12 +136,12 @@ public function testSelect() public function testRangeQueries() { - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); $select->setQuery( $select->getHelper()->rangeQuery('price', null, 80) ); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(6, $result->getNumFound()); $this->assertCount(6, $result); @@ -70,35 +149,35 @@ public function testRangeQueries() $select->setQuery( $select->getHelper()->rangeQuery('price', 70.23, 80) ); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(1, $result->getNumFound()); $this->assertCount(1, $result); $select->setQuery( $select->getHelper()->rangeQuery('price', 74.99, null) ); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(11, $result->getNumFound()); $this->assertCount(10, $result); $select->setQuery( $select->getHelper()->rangeQuery('price', 74.99, null, false) ); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(10, $result->getNumFound()); $this->assertCount(10, $result); $select->setQuery( $select->getHelper()->rangeQuery('store', '-90,-90', '90,90', true, false) ); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(2, $result->getNumFound()); $this->assertCount(2, $result); $select->setQuery( $select->getHelper()->rangeQuery('store', '-90,-180', '90,180', true, false) ); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(14, $result->getNumFound()); $this->assertCount(10, $result); } @@ -106,11 +185,11 @@ public function testRangeQueries() /** * @todo this test should pass on Solr Cloud! * - * @group solr_no_cloud + * @group skip_for_solr_cloud */ public function testFacetHighlightSpellcheckComponent() { - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); // In the techproducts example, the request handler "select" doesn't neither contain a spellcheck component nor // a highlighter or facets. But the "browse" request handler does. $select->setHandler('browse'); @@ -121,7 +200,7 @@ public function testFacetHighlightSpellcheckComponent() // Some spellcheck dictionaries needs to build first, but not on every request! $spellcheck->setBuild(true); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(0, $result->getNumFound()); $this->assertSame( @@ -144,7 +223,7 @@ public function testFacetHighlightSpellcheckComponent() $spellcheck->setDictionary(['default', 'wordbreak']); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(0, $result->getNumFound()); $this->assertSame( @@ -161,7 +240,7 @@ public function testFacetHighlightSpellcheckComponent() $facetSet = $select->getFacetSet(); $facetSet->createFacetField('stock')->setField('inStock'); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(1, $result->getNumFound()); foreach ($result as $document) { @@ -195,7 +274,7 @@ public function testFacetHighlightSpellcheckComponent() public function testQueryElevation() { - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); // In the techproducts example, the request handler "select" doesn't contain a query elevation component. // But the "elevate" request handler does. $select->setHandler('elevate'); @@ -207,7 +286,7 @@ public function testQueryElevation() $elevate->setElevateIds(['VS1GB400C3', 'VDBDB1A16']); $elevate->setExcludeIds(['SP2514N', '6H500F0']); - $result = $this->client->select($select); + $result = self::$client->select($select); // The techproducts example contains 14 'electronics', 2 of them are excluded. $this->assertSame(12, $result->getNumFound()); // The first two results are elevated and ignore the sort order. @@ -227,30 +306,30 @@ public function testQueryElevation() public function testSpatial() { - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); $select->setQuery( $select->getHelper()->geofilt('store', 40, -100, 100000) ); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(14, $result->getNumFound()); $this->assertCount(10, $result); $select->setQuery( $select->getHelper()->geofilt('store', 40, -100, 1000) ); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(10, $result->getNumFound()); $this->assertCount(10, $result); } public function testSpellcheck() { - $spellcheck = $this->client->createSpellcheck(); + $spellcheck = self::$client->createSpellcheck(); $spellcheck->setQuery('power cort'); // Some spellcheck dictionaries needs to build first, but not on every request! $spellcheck->setBuild(true); - $result = $this->client->spellcheck($spellcheck); + $result = self::$client->spellcheck($spellcheck); $words = []; foreach ($result as $term => $suggestions) { $this->assertSame('cort', $term); @@ -267,13 +346,13 @@ public function testSpellcheck() public function testSuggester() { - $suggester = $this->client->createSuggester(); + $suggester = self::$client->createSuggester(); // The techproducts example doesn't provide a default suggester, but 'mySuggester'. $suggester->setDictionary('mySuggester'); $suggester->setQuery('electronics'); // A suggester dictionary needs to build first, but not on every request! $suggester->setBuild(true); - $result = $this->client->suggester($suggester); + $result = self::$client->suggester($suggester); $phrases = []; foreach ($result as $dictionary => $terms) { $this->assertSame('mySuggester', $dictionary); @@ -291,15 +370,15 @@ public function testSuggester() public function testTerms() { - $terms = $this->client->createTerms(); + $terms = self::$client->createTerms(); $terms->setFields('name'); // Setting distrib to true in a non cloud setup causes exceptions. - if (isset($this->collection)) { + if ($this instanceof AbstractCloudTest) { $terms->setDistrib(true); } - $result = $this->client->terms($terms); + $result = self::$client->terms($terms); $this->assertEquals([ 'one' => 5, @@ -317,17 +396,17 @@ public function testTerms() public function testTermsComponent() { - $this->client->registerQueryType('test', '\Solarium\Tests\Integration\TestQuery'); - $select = $this->client->createQuery('test'); + self::$client->registerQueryType('test', '\Solarium\Tests\Integration\TestQuery'); + $select = self::$client->createQuery('test'); // Setting distrib to true in a non cloud setup causes exceptions. - if (isset($this->collection)) { + if ($this instanceof AbstractCloudTest) { $select->setDistrib(true); } $terms = $select->getTerms(); $terms->setFields('name'); - $result = $this->client->select($select); + $result = self::$client->select($select); /** @var Result $termsComponentResult */ $termsComponentResult = $result->getComponent(ComponentAwareQueryInterface::COMPONENT_TERMS); @@ -379,7 +458,7 @@ public function testTermsComponent() public function testUpdate() { - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); $select->setQuery('cat:solarium-test'); $select->addSort('id', $select::SORT_ASC); $select->setFields('id,name,price'); @@ -397,11 +476,11 @@ public function testUpdate() 'updateHandler.autoSoftCommit.maxTime' => -1, ], ])); - $response = $this->client->executeRequest($request); + $response = self::$client->executeRequest($request); $this->assertSame(0, json_decode($response->getBody())->responseHeader->status); // add, but don't commit - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $doc1 = $update->createDocument(); $doc1->setField('id', 'solarium-test-1'); $doc1->setField('name', 'Solarium Test 1'); @@ -413,15 +492,15 @@ public function testUpdate() $doc2->setField('cat', 'solarium-test'); $doc2->setField('price', 42.0); $update->addDocuments([$doc1, $doc2]); - $this->client->update($update); - $result = $this->client->select($select); + self::$client->update($update); + $result = self::$client->select($select); $this->assertCount(0, $result); // commit - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->addCommit(true, true); - $this->client->update($update); - $result = $this->client->select($select); + self::$client->update($update); + $result = self::$client->select($select); $this->assertCount(2, $result); $iterator = $result->getIterator(); $this->assertSame([ @@ -437,11 +516,11 @@ public function testUpdate() ], $iterator->current()->getFields()); // delete by id and commit - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->addDeleteById('solarium-test-1'); $update->addCommit(true, true); - $this->client->update($update); - $result = $this->client->select($select); + self::$client->update($update); + $result = self::$client->select($select); $this->assertCount(1, $result); $this->assertSame([ 'id' => 'solarium-test-2', @@ -450,44 +529,44 @@ public function testUpdate() ], $result->getIterator()->current()->getFields()); // delete by query and commit - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->addDeleteQuery('cat:solarium-test'); $update->addCommit(true, true); - $this->client->update($update); - $result = $this->client->select($select); + self::$client->update($update); + $result = self::$client->select($select); $this->assertCount(0, $result); // optimize - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->addOptimize(true, false); - $response = $this->client->update($update); + $response = self::$client->update($update); $this->assertSame(0, $response->getStatus()); // rollback is currently not supported in SolrCloud mode (SOLR-4895) - if ($this instanceof AbstractCoreTest) { + if ($this instanceof AbstractServerTest) { // add, rollback, commit - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $doc1 = $update->createDocument(); $doc1->setField('id', 'solarium-test-1'); $doc1->setField('name', 'Solarium Test 1'); $doc1->setField('cat', 'solarium-test'); $doc1->setField('price', 3.14); $update->addDocument($doc1); - $this->client->update($update); - $update = $this->client->createUpdate(); + self::$client->update($update); + $update = self::$client->createUpdate(); $update->addRollback(); $update->addCommit(true, true); - $this->client->update($update); - $result = $this->client->select($select); + self::$client->update($update); + $result = self::$client->select($select); $this->assertCount(0, $result); } // raw add and raw commit - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->addRawXmlCommand('solarium-test-1Solarium Test 1solarium-test3.14'); $update->addRawXmlCommand(''); - $this->client->update($update); - $result = $this->client->select($select); + self::$client->update($update); + $result = self::$client->select($select); $this->assertCount(1, $result); $this->assertSame([ 'id' => 'solarium-test-1', @@ -496,11 +575,11 @@ public function testUpdate() ], $result->getIterator()->current()->getFields()); // grouped mixed raw commands - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->addRawXmlCommand('solarium-test-2Solarium Test 2solarium-test42'); $update->addRawXmlCommand('solarium-test-1'); - $this->client->update($update); - $result = $this->client->select($select); + self::$client->update($update); + $result = self::$client->select($select); $this->assertCount(1, $result); $this->assertSame([ 'id' => 'solarium-test-2', @@ -509,29 +588,29 @@ public function testUpdate() ], $result->getIterator()->current()->getFields()); // raw delete and regular commit - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->addRawXmlCommand('cat:solarium-test'); $update->addCommit(true, true); - $this->client->update($update); - $result = $this->client->select($select); + self::$client->update($update); + $result = self::$client->select($select); $this->assertCount(0, $result); // add from UTF-8 encoded files without and with Byte Order Mark and XML declaration - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); foreach (glob(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'testxml[1234]-add*.xml') as $file) { $update->addRawXmlFile($file); } $update->addCommit(true, true); - $this->client->update($update); + self::$client->update($update); // add from non-UTF-8 encoded file - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->setInputEncoding('ISO-8859-1'); $update->addRawXmlFile(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'testxml5-add-iso-8859-1.xml'); $update->addCommit(true, true); - $this->client->update($update); + self::$client->update($update); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertCount(5, $result); $iterator = $result->getIterator(); $this->assertSame([ @@ -565,11 +644,11 @@ public function testUpdate() ], $iterator->current()->getFields()); // delete from file with grouped delete commands - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->addRawXmlFile(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'testxml6-delete.xml'); $update->addCommit(true, true); - $this->client->update($update); - $result = $this->client->select($select); + self::$client->update($update); + $result = self::$client->select($select); $this->assertCount(0, $result); // reset automatic commits to the configuration in solrconfig.xml @@ -581,16 +660,16 @@ public function testUpdate() 'updateHandler.autoSoftCommit.maxTime', ], ])); - $response = $this->client->executeRequest($request); + $response = self::$client->executeRequest($request); $this->assertSame(0, json_decode($response->getBody())->responseHeader->status); } public function testReRankQuery() { - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); $select->setQuery('inStock:true'); $select->setRows(2); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(17, $result->getNumFound()); $this->assertCount(2, $result); @@ -602,7 +681,7 @@ public function testReRankQuery() $reRankQuery = $select->getReRankQuery(); $reRankQuery->setQuery('popularity:10'); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertSame(17, $result->getNumFound()); $this->assertCount(2, $result); @@ -621,8 +700,8 @@ public function testReRankQuery() public function testPrefetchIterator() { - $select = $this->client->createSelect(); - $prefetch = $this->client->getPlugin('prefetchiterator'); + $select = self::$client->createSelect(); + $prefetch = self::$client->getPlugin('prefetchiterator'); $prefetch->setPrefetch(2); $prefetch->setQuery($select); @@ -636,10 +715,10 @@ public function testPrefetchIterator() public function testPrefetchIteratorWithCursormark() { - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); $select->setCursormark('*'); $select->addSort('id', SelectQuery::SORT_ASC); - $prefetch = $this->client->getPlugin('prefetchiterator'); + $prefetch = self::$client->getPlugin('prefetchiterator'); $prefetch->setPrefetch(2); $prefetch->setQuery($select); @@ -653,9 +732,9 @@ public function testPrefetchIteratorWithCursormark() public function testPrefetchIteratorWithoutAndWithCursormark() { - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); $select->addSort('id', SelectQuery::SORT_ASC); - $prefetch = $this->client->getPlugin('prefetchiterator'); + $prefetch = self::$client->getPlugin('prefetchiterator'); $prefetch->setPrefetch(2); $prefetch->setQuery($select); @@ -664,7 +743,7 @@ public function testPrefetchIteratorWithoutAndWithCursormark() $without = $document->id; } - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); $select->setCursormark('*'); $select->addSort('id', SelectQuery::SORT_ASC); $prefetch->setQuery($select); @@ -679,7 +758,7 @@ public function testPrefetchIteratorWithoutAndWithCursormark() public function testExtractIntoDocument() { - $extract = $this->client->createExtract(); + $extract = self::$client->createExtract(); $extract->setUprefix('attr_'); $extract->setFile(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'testpdf.pdf'); $extract->setCommit(true); @@ -691,12 +770,12 @@ public function testExtractIntoDocument() $doc->id = 'extract-test'; $extract->setDocument($doc); - $this->client->extract($extract); + self::$client->extract($extract); // now get the document and check the content - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); $select->setQuery('id:extract-test'); - $selectResult = $this->client->select($select); + $selectResult = self::$client->select($select); $iterator = $selectResult->getIterator(); /** @var Document $document */ @@ -704,53 +783,53 @@ public function testExtractIntoDocument() $this->assertSame('PDF Test', trim($document['content'][0]), 'Written document does not contain extracted result'); // now cleanup the document the have the initial index state - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->addDeleteById('extract-test'); $update->addCommit(true, true); - $this->client->update($update); + self::$client->update($update); } public function testExtractTextOnly() { - $query = $this->client->createExtract(); + $query = self::$client->createExtract(); $fileName = 'testpdf.pdf'; $query->setFile(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.$fileName); $query->setExtractOnly(true); $query->addParam('extractFormat', 'text'); - $response = $this->client->extract($query); + $response = self::$client->extract($query); $this->assertSame('PDF Test', trim($response->getData()['testpdf.pdf']), 'Can not extract the plain content from the file'); } public function testV2Api() { - $query = $this->client->createApi([ + $query = self::$client->createApi([ 'version' => Request::API_V1, 'handler' => 'admin/info/system', ]); - $response = $this->client->execute($query); + $response = self::$client->execute($query); if (version_compare($response->getData()['lucene']['solr-spec-version'], '7', '>=')) { - $query = $this->client->createApi([ + $query = self::$client->createApi([ 'version' => Request::API_V2, 'handler' => 'node/system', ]); - $response = $this->client->execute($query); + $response = self::$client->execute($query); $this->assertArrayHasKey('lucene', $response->getData()); $this->assertArrayHasKey('jvm', $response->getData()); $this->assertArrayHasKey('system', $response->getData()); - $query = $this->client->createApi([ + $query = self::$client->createApi([ 'version' => Request::API_V2, 'handler' => 'node/properties', ]); - $response = $this->client->execute($query); + $response = self::$client->execute($query); $this->assertArrayHasKey('system.properties', $response->getData()); - $query = $this->client->createApi([ + $query = self::$client->createApi([ 'version' => Request::API_V2, 'handler' => 'node/logging', ]); - $response = $this->client->execute($query); + $response = self::$client->execute($query); $this->assertArrayHasKey('levels', $response->getData()); $this->assertArrayHasKey('loggers', $response->getData()); } else { @@ -760,12 +839,12 @@ public function testV2Api() public function testInputEncoding() { - $select = $this->client->createSelect(); + $select = self::$client->createSelect(); $select->addSort('id', $select::SORT_ASC); $select->setFields('id,name,price'); // input encoding: UTF-8 (default) - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $doc = $update->createDocument(); $doc->setField('id', 'solarium-test-1'); $doc->setField('name', 'Sølåríùm Tëst 1'); @@ -773,12 +852,12 @@ public function testInputEncoding() $doc->setField('price', 3.14); $update->addDocument($doc); $update->addCommit(true, true); - $this->client->update($update); + self::$client->update($update); // input encoding: UTF-8 (default) // output encoding: UTF-8 (always) $select->setQuery('cat:áéíóú'); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertCount(1, $result); $this->assertSame([ 'id' => 'solarium-test-1', @@ -790,7 +869,7 @@ public function testInputEncoding() // output encoding: UTF-8 (always) $select->setQuery('cat:'.utf8_decode('áéíóú')); $select->setInputEncoding('ISO-8859-1'); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertCount(1, $result); $this->assertSame([ 'id' => 'solarium-test-1', @@ -799,7 +878,7 @@ public function testInputEncoding() ], $result->getIterator()->current()->getFields()); // input encoding: ISO-8859-1 - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->setInputEncoding('ISO-8859-1'); $doc = $update->createDocument(); $doc->setField('id', utf8_decode('solarium-test-2')); @@ -808,13 +887,13 @@ public function testInputEncoding() $doc->setField('price', 42.0); $update->addDocument($doc); $update->addCommit(true, true); - $this->client->update($update); + self::$client->update($update); // input encoding: UTF-8 (explicit) // output encoding: UTF-8 (always) $select->setQuery('cat:áéíóú'); $select->setInputEncoding('UTF-8'); - $result = $this->client->select($select); + $result = self::$client->select($select); $this->assertCount(2, $result); $iterator = $result->getIterator(); $this->assertSame([ @@ -829,13 +908,291 @@ public function testInputEncoding() 'price' => 42.0, ], $iterator->current()->getFields()); - $update = $this->client->createUpdate(); + $update = self::$client->createUpdate(); $update->addDeleteQuery('cat:solarium-test'); $update->addCommit(true, true); - $this->client->update($update); - $result = $this->client->select($select); + self::$client->update($update); + $result = self::$client->select($select); $this->assertCount(0, $result); } + + public function testManagedStopwords() + { + $query = self::$client->createManagedStopwords(); + $query->setName('english'); + $term = 'managed_stopword_test'; + + // Add stopwords + $add = new AddStopwords(); + $add->setStopwords([$term]); + $query->setCommand($add); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if single stopword exists + $exists = new ExistsStopwords(); + $exists->setTerm($term); + $query->setCommand($exists); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // We need to remove the current command in order to have no command. Having no command lists the items. + $query->removeCommand(); + + // List stopwords + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + $items = $result->getItems(); + $this->assertContains($term, $items); + + // Delete stopword + $delete = new DeleteStopwords(); + $delete->setTerm($term); + $query->setCommand($delete); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if stopword is gone + $this->expectException(HttpException::class); + $exists = new ExistsStopwords(); + $exists->setTerm($term); + $query->setCommand($exists); + self::$client->execute($query); + } + + public function testManagedStopwordsCreation() + { + $query = self::$client->createManagedStopwords(); + $query->setName(uniqid()); + $term = 'managed_stopword_test'; + + // Create a new stopword list + $create = new CreateStopwords(); + $query->setCommand($create); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Whatever happens next ... + try { + // Configure the new list to be case sensitive + $initArgs = new InitArgsStopwords(); + $initArgs->setIgnoreCase(false); + $config = new ConfigStopwords(); + $config->setInitArgs($initArgs); + $query->setCommand($config); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check the configuration + $query->removeCommand(); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + $this->assertFalse($result->isIgnoreCase()); + + // Check if we can add to it + $add = new AddStopwords(); + $add->setStopwords([$term]); + $query->setCommand($add); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if stopword exists in its original lowercase form + $exists = new ExistsStopwords(); + $exists->setTerm($term); + $query->setCommand($exists); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if stopword DOESN'T exist in uppercase form + $this->expectException(HttpException::class); + $exists->setTerm(strtoupper($term)); + $query->setCommand($exists); + self::$client->execute($query); + } + // ... we have to remove the created resource! + finally { + // Remove the stopword list + $remove = new RemoveStopwords(); + $query->setCommand($remove); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if stopword list is gone + $this->expectException(HttpException::class); + $query->removeCommand(); + self::$client->execute($query); + } + } + + public function testManagedSynonyms() + { + $query = self::$client->createManagedSynonyms(); + $query->setName('english'); + $term = 'managed_synonyms_test'; + + // Add synonyms + $add = new AddSynonyms(); + $synonyms = new Synonyms(); + $synonyms->setTerm($term); + $synonyms->setSynonyms(['managed_synonym', 'synonym_test']); + $add->setSynonyms($synonyms); + $query->setCommand($add); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if single synonym exists + $exists = new ExistsSynonyms(); + $exists->setTerm($term); + $query->setCommand($exists); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + $this->assertSame(['managed_synonyms_test' => ['managed_synonym', 'synonym_test']], $result->getData()); + + // We need to remove the current command in order to have no command. Having no command lists the items. + $query->removeCommand(); + + // List synonyms + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + $items = $result->getItems(); + $success = false; + foreach ($items as $item) { + if ('managed_synonyms_test' === $item->getTerm()) { + $success = true; + } + } + if (!$success) { + $this->fail('Couldn\'t find synonym.'); + } + + // Delete synonyms + $delete = new DeleteSynonyms(); + $delete->setTerm($term); + $query->setCommand($delete); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if synonyms are gone + $this->expectException(HttpException::class); + $exists = new ExistsSynonyms(); + $exists->setTerm($term); + $query->setCommand($exists); + self::$client->execute($query); + } + + public function testManagedSynonymsCreation() + { + $query = self::$client->createManagedSynonyms(); + $query->setName(uniqid()); + $term = 'managed_synonyms_test'; + + // Create a new synonym map + $create = new CreateSynonyms(); + $query->setCommand($create); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Whatever happens next ... + try { + // Configure the new map to be case sensitive and use the 'solr' format + $initArgs = new InitArgsSynonyms(); + $initArgs->setIgnoreCase(false); + $initArgs->setFormat(InitArgsSynonyms::FORMAT_SOLR); + $config = new ConfigSynonyms(); + $config->setInitArgs($initArgs); + $query->setCommand($config); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check the configuration + $query->removeCommand(); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + $this->assertFalse($result->isIgnoreCase()); + $this->assertEquals(InitArgsSynonyms::FORMAT_SOLR, $result->getFormat()); + + // Check if we can add to it + $add = new AddSynonyms(); + $synonyms = new Synonyms(); + $synonyms->setTerm($term); + $synonyms->setSynonyms(['managed_synonym', 'synonym_test']); + $add->setSynonyms($synonyms); + $query->setCommand($add); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if synonym exists in its original lowercase form + $exists = new ExistsSynonyms(); + $exists->setTerm($term); + $query->setCommand($exists); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + $this->assertSame(['managed_synonyms_test' => ['managed_synonym', 'synonym_test']], $result->getData()); + + // Check if synonym DOESN'T exist in uppercase form + $this->expectException(HttpException::class); + $exists->setTerm(strtoupper($term)); + $query->setCommand($exists); + self::$client->execute($query); + } + // ... we have to remove the created resource! + finally { + // Remove the synonym map + $remove = new RemoveSynonyms(); + $query->setCommand($remove); + $result = self::$client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if synonym map is gone + $this->expectException(HttpException::class); + $query->removeCommand(); + self::$client->execute($query); + } + } + + public function testManagedResources() + { + // Check if we can find the 2 default managed resources + // (and account for additional resources we might have created while testing) + $query = self::$client->createManagedResources(); + $result = self::$client->execute($query); + $items = $result->getItems(); + $this->assertGreaterThanOrEqual(2, count($items)); + } + + /** + * Extracts the encoding from the XML declaration of a file if present. + * + * @param string $file + * + * @return string|null + */ + private static function getXmlEncoding(string $file): ?string + { + $encoding = null; + + $xml = file_get_contents($file); + + if (false !== $xml) { + // discard UTF-8 Byte Order Mark + if (pack('CCC', 0xEF, 0xBB, 0xBF) === substr($xml, 0, 3)) { + $xml = substr($xml, 3); + } + + // detect XML declaration + if ('') + 2); + + // detect encoding attribute + if (false !== $pos = strpos($declaration, 'encoding="')) { + $encoding = substr($declaration, $pos + 10, strpos($declaration, '"', $pos + 10) - $pos - 10); + } + } + } + + return $encoding; + } + } class TestQuery extends SelectQuery diff --git a/tests/Integration/Fixtures/docker/solr7_cloud/docker-compose.yml b/tests/Integration/Fixtures/docker/solr7_cloud/docker-compose.yml new file mode 100644 index 000000000..3fdef674d --- /dev/null +++ b/tests/Integration/Fixtures/docker/solr7_cloud/docker-compose.yml @@ -0,0 +1,7 @@ +version: '3' +services: + solr7: + image: solr:7 + ports: + - "8983:8983" + command: bash -c "docker-entrypoint.sh solr start -c; solr zk upconfig -z localhost:9983 -n techproducts -d server/solr/configsets/sample_techproducts_configs/conf; mkdir /opt/solr/server/solr/data2; cp /opt/solr/server/solr/solr.xml /opt/solr/server/solr/data2; solr start -c -s /opt/solr/server/solr/data2 -p 8987 -z localhost:9983 -f" diff --git a/tests/Integration/Fixtures/docker/solr7_server/docker-compose.yml b/tests/Integration/Fixtures/docker/solr7_server/docker-compose.yml new file mode 100644 index 000000000..d9250bd2c --- /dev/null +++ b/tests/Integration/Fixtures/docker/solr7_server/docker-compose.yml @@ -0,0 +1,7 @@ +version: '3' +services: + solr7: + image: solr:7 + ports: + - "8983:8983" + command: bash -c "cp -R /opt/solr/server/solr/configsets /var/solr/data/configsets; docker-entrypoint.sh solr start -f" diff --git a/tests/Integration/Fixtures/docker/solr8_cloud/docker-compose.yml b/tests/Integration/Fixtures/docker/solr8_cloud/docker-compose.yml new file mode 100644 index 000000000..1fed9d7a4 --- /dev/null +++ b/tests/Integration/Fixtures/docker/solr8_cloud/docker-compose.yml @@ -0,0 +1,7 @@ +version: '3' +services: + solr8: + image: solr:8 + ports: + - "8983:8983" + command: bash -c "docker-entrypoint.sh solr start -c; solr zk upconfig -z localhost:9983 -n techproducts -d server/solr/configsets/sample_techproducts_configs/conf; mkdir /var/solr/data2; cp /var/solr/data/solr.xml /var/solr/data2/; solr start -c -s /var/solr/data2 -p 8987 -z localhost:9983 -f" diff --git a/tests/Integration/Fixtures/docker/solr8_server/docker-compose.yml b/tests/Integration/Fixtures/docker/solr8_server/docker-compose.yml new file mode 100644 index 000000000..105f0be54 --- /dev/null +++ b/tests/Integration/Fixtures/docker/solr8_server/docker-compose.yml @@ -0,0 +1,7 @@ +version: '3' +services: + solr8: + image: solr:8 + ports: + - "8983:8983" + command: bash -c "cp -R /opt/solr/server/solr/configsets /var/solr/data/configsets; docker-entrypoint.sh solr start -f" diff --git a/tests/Integration/SolrCloud/CollectionsPsr18Test.php b/tests/Integration/SolrCloud/CollectionsPsr18Test.php deleted file mode 100644 index 6ab29dd2c..000000000 --- a/tests/Integration/SolrCloud/CollectionsPsr18Test.php +++ /dev/null @@ -1,14 +0,0 @@ -setTimeout(CURLOPT_TIMEOUT); - $this->client->setAdapter($adapter); + self::$client->setAdapter($adapter); } } diff --git a/tests/Integration/SolrCloud/CollectionsHttpTest.php b/tests/Integration/SolrCloud/HttpTest.php similarity index 54% rename from tests/Integration/SolrCloud/CollectionsHttpTest.php rename to tests/Integration/SolrCloud/HttpTest.php index 05bc17c0a..1626ff537 100644 --- a/tests/Integration/SolrCloud/CollectionsHttpTest.php +++ b/tests/Integration/SolrCloud/HttpTest.php @@ -3,18 +3,18 @@ namespace Solarium\Tests\Integration\SolrCloud; use Solarium\Core\Client\Adapter\Http; -use Solarium\Tests\Integration\AbstractCollectionsTest; +use Solarium\Tests\Integration\AbstractCloudTest; /** * @group integration - * @group solr_cloud + * @group skip_for_solr_server * @coversNothing */ -class CollectionsHttpTest extends AbstractCollectionsTest +class HttpTest extends AbstractCloudTest { public function setUp(): void { parent::setUp(); - $this->client->setAdapter(new Http()); + self::$client->setAdapter(new Http()); } } diff --git a/tests/Integration/SolrCloud/Psr18Test.php b/tests/Integration/SolrCloud/Psr18Test.php new file mode 100644 index 000000000..099fc9fcf --- /dev/null +++ b/tests/Integration/SolrCloud/Psr18Test.php @@ -0,0 +1,14 @@ +setTimeout(CURLOPT_TIMEOUT); - $this->client->setAdapter($adapter); + self::$client->setAdapter($adapter); } } diff --git a/tests/Integration/SolrServer/HttpTest.php b/tests/Integration/SolrServer/HttpTest.php new file mode 100644 index 000000000..73dae61ff --- /dev/null +++ b/tests/Integration/SolrServer/HttpTest.php @@ -0,0 +1,20 @@ +setAdapter(new Http()); + } +} diff --git a/tests/Integration/SolrServer/Psr18Test.php b/tests/Integration/SolrServer/Psr18Test.php new file mode 100644 index 000000000..b38551ff6 --- /dev/null +++ b/tests/Integration/SolrServer/Psr18Test.php @@ -0,0 +1,14 @@ +client->setAdapter(new Http()); - } -} diff --git a/tests/Integration/TechproductsAdapters/TechproductsPsr18Test.php b/tests/Integration/TechproductsAdapters/TechproductsPsr18Test.php deleted file mode 100644 index eca27b342..000000000 --- a/tests/Integration/TechproductsAdapters/TechproductsPsr18Test.php +++ /dev/null @@ -1,14 +0,0 @@ -