Completed
Push — dev2 ( 507d7b...9f9038 )
by Gordon
11:12
created

ElasticsearchBaseTest::publishSiteTree()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2
Metric Value
dl 0
loc 7
ccs 6
cts 6
cp 1
rs 9.4286
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
use SilverStripe\Elastica\ElasticaUtil;
3
use SilverStripe\Elastica\ReindexTask;
4
use SilverStripe\Elastica\ElasticaService;
5
6
class ElasticsearchBaseTest extends SapphireTest {
7
8
	public static $ignoreFixtureFileFor = array();
9
10
	protected $extraDataObjects = array(
11
		'SearchableTestPage','FlickrPhotoTO','FlickrAuthorTO','FlickrSetTO','FlickrTagTO',
12
		'SearchableTestFatherPage','SearchableTestGrandFatherPage','AutoCompleteOption'
13
	);
14
15
16
	public function setUpOnce() {
17
		ElasticaUtil::setPrinterOutput(false);
18
19
		// add Searchable extension where appropriate
20
		FlickrSetTO::add_extension('SilverStripe\Elastica\Searchable');
21
		FlickrPhotoTO::add_extension('SilverStripe\Elastica\Searchable');
22
		FlickrTagTO::add_extension('SilverStripe\Elastica\Searchable');
23
		FlickrAuthorTO::add_extension('SilverStripe\Elastica\Searchable');
24
		SearchableTestPage::add_extension('SilverStripe\Elastica\Searchable');
25
26
27
		$config = Config::inst();
28
		$config->remove('Injector', 'SilverStripe\Elastica\ElasticaService');
29
		$constructor = array('constructor' => array('%$Elastica\Client', 'elastica_ss_module_test'));
30
		$config->update('Injector', 'SilverStripe\Elastica\ElasticaService', $constructor);
31
		parent::setUpOnce();
32
	}
33
34
35 10
	public function setUp() {
0 ignored issues
show
Coding Style introduced by
setUp uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
36 10
		error_log('++++ EL BASE SET UP T1');
37
		// no need to index here as it's done when fixtures are loaded during setup method
38 10
		$cache = SS_Cache::factory('elasticsearch');
39 10
		$cache->clean(Zend_Cache::CLEANING_MODE_ALL);
40 10
		SS_Cache::set_cache_lifetime('elasticsearch', 3600, 1000);
41 10
		error_log('++++ EL BASE SET UP T2');
42
43
		// this needs to be called in order to create the list of searchable
44
		// classes and fields that are available.  Simulates part of a build
45 10
		$classes = array('SearchableTestPage','SiteTree','Page','FlickrPhotoTO','FlickrSetTO',
46 10
			'FlickrTagTO', 'FlickrAuthorTO');
47 10
		$this->requireDefaultRecordsFrom = $classes;
48
49 10
		error_log('++++ EL BASE SET UP T3');
50
51
		// clear the index
52 10
		$this->service = Injector::inst()->create('SilverStripe\Elastica\ElasticaService');
53 10
		$this->service->setTestMode(true);
54
55 10
		error_log('++++ EL BASE SET UP T4');
56
57 10
		$elasticException = false;
58
59
		try {
60
			// A previous test may have deleted the index and then failed, so check for this
61 10
			if (!$this->service->getIndex()->exists()) {
62 1
				error_log('++++ EL BASE SET UP T4a');
63
64 1
				$this->service->getIndex()->create();
65 1
			}
66 10
			error_log('++++ EL BASE SET UP T4b');
67 10
			$this->service->reset();
68 10
			error_log('++++ EL BASE SET UP T4c');
69
			// FIXME - use request getVar instead?
70 10
			$_GET['progress'] = 20;
71
			// load fixtures
72
73 10
			$orig_fixture_file = static::$fixture_file;
74 10
			error_log('++++ EL BASE SET UP T5');
75
76 10 View Code Duplication
			foreach (static::$ignoreFixtureFileFor as $testPattern) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
77
				$pattern = '/'.$testPattern.'/';
78
				if (preg_match($pattern, $this->getName())) {
79
					static::$fixture_file = null;
80
				}
81 10
			}
82
83 10
			error_log('++++ EL BASE SET UP T6');
84 10
		} catch (Exception $e) {
85
			error_log("**** EXCEPTION T1 ".$e->getMessage());
86
			$elasticException = true;
87
		}
88 10
			error_log('++++ EL BASE SET UP T7');
89
90
91
		// this needs to run otherwise nested injector errors show up
92 10
		parent::setUp();
93
94 10
		if ($elasticException) {
95
			$this->fail('T1 An error has occurred trying to contact Elasticsearch server');
0 ignored issues
show
Bug introduced by
The method fail() does not seem to exist on object<ElasticsearchBaseTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
96
		}
97
98
		try {
99 10
			static::$fixture_file = $orig_fixture_file;
0 ignored issues
show
Bug introduced by
The variable $orig_fixture_file does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
100
101 10
			$this->publishSiteTree();
102 10
			$this->service->reset();
103
104
			// index loaded fixtures
105 10
			$task = new ReindexTask($this->service);
106
			// null request is fine as no parameters used
107
108 10
			$task->run(null);
109 10
		} catch (Exception $e) {
110
			error_log("**** EXCEPTION T2 ".$e->getMessage());
111
			$elasticException = true;
112
		}
113
114 10
		if ($elasticException) {
115
			$this->fail('T2 An error has occurred trying to contact Elasticsearch server');
0 ignored issues
show
Bug introduced by
The method fail() does not seem to exist on object<ElasticsearchBaseTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
116
		}
117
118 10
	}
119
120
121
	protected function devBuild() {
122
		$task = new \BuildTask();
123
		// null request is fine as no parameters used
124
		$task->run(null);
125
	}
126
127
128 10
	private function publishSiteTree() {
129 10
		foreach (SiteTree::get()->getIterator() as $page) {
130
			// temporarily disable Elasticsearch indexing, it will be done in a batch
131 10
			$page->IndexingOff = true;
132 10
			$page->publish('Stage','Live');
133 10
		}
134 10
	}
135
136
137 View Code Duplication
	public function generateAssertionsFromArray($toAssert) {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
138
		echo '$expected = array('."\n";
139
		foreach ($toAssert as $key => $value) {
140
			$escValue = str_replace("'", '\\\'', $value);
141
			echo "'$key' => '$escValue',\n";
142
		}
143
		echo ");\n";
144
		echo '$this->assertEquals($expected, $somevar);'."\n";
145
	}
146
147
148 View Code Duplication
	public function generateAssertionsFromArray1D($toAssert) {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
149
		echo '$expected = array('."\n";
150
		foreach ($toAssert as $key => $value) {
151
			$escValue = str_replace("'", '\\\'', $value);
152
			echo "'$escValue',";
153
		}
154
		echo ");\n";
155
		echo '$this->assertEquals($expected, $somevar);'."\n";
156
	}
157
158
159
	public function generateAssertionsFromArrayRecurse($toAssert) {
160
		echo '$expected = ';
161
			$this->recurseArrayAssertion($toAssert,1, 'FIXME');
162
		echo '$this->assertEquals($expected, $somevar);'."\n";
163
	}
164
165
166
	private function recurseArrayAssertion($toAssert, $depth, $parentKey) {
167
		$prefix = str_repeat("\t",$depth);
168
		echo "\t{$prefix}'$parentKey' => array(\n";
169
		$ctr = 0;
170
		$len = sizeof(array_keys($toAssert));
171
		foreach ($toAssert as $key => $value) {
172
			if (is_array($value)) {
173
				$this->recurseArrayAssertion($value, $depth+1, $key);
174
			} else {
175
				$escValue = str_replace("'", '\\\'', $value);
176
				$comma = ',';
177
				if ($ctr == $len-1) {
178
					$comma = '';
179
				}
180
				echo "\t\t$prefix'$key' => '$escValue'$comma\n";
181
			}
182
183
			$ctr++;
184
185
		}
186
		echo "\t$prefix),\n";
187
188
	}
189
190
191
	/*
192
	Helper methods for testing CMS fields
193
	 */
194 1
	public function checkTabExists($fields, $tabName) {
195
		$tab = $fields->findOrMakeTab("Root.{$tabName}");
196
		$actualTabName = $tab->getName();
197
		$splits = explode('.', $tabName);
198
		$size = sizeof($splits);
199 1
		$nameToCheck = end($splits);
200
		$this->assertEquals($actualTabName, $nameToCheck);
201
		if ($size == 1) {
202
			$this->assertEquals("Root_${tabName}", $tab->id());
203
		} else {
204
			$expected = "Root_{$splits[0]}_set_{$splits[1]}";
205
			$this->assertEquals($expected, $tab->id());
206
		}
207
208
		return $tab;
209
	}
210
211
212
	public function checkFieldExists($tab,$fieldName) {
213
		$fields = $tab->Fields();
0 ignored issues
show
Unused Code introduced by
$fields is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
214
		$field = $tab->fieldByName($fieldName);
215
		$this->assertTrue($field != null);
216
		return $field;
217
	}
218
219
220
	/**
221
	 * From https://jtreminio.com/2013/03/unit-testing-tutorial-part-3-testing-protected-private-methods-coverage-reports-and-crap/
222
	 * Call protected/private method of a class.
223
	 *
224
	 * @param object &$object    Instantiated object that we will run method on.
225
	 * @param string $methodName Method name to call
226
	 * @param array  $parameters Array of parameters to pass into method.
227
	 *
228
	 * @return mixed Method return.
229
	 */
230
	public function invokeMethod(&$object, $methodName, array $parameters = array())
231
	{
232
	    $reflection = new \ReflectionClass(get_class($object));
233
	    $method = $reflection->getMethod($methodName);
234
	    $method->setAccessible(true);
235
236
	    return $method->invokeArgs($object, $parameters);
237
	}
238
239
240
	public function checkNumberOfIndexedDocuments($expectedAmount) {
241
		$index = $this->service->getIndex();
242
		$status = $index->getStatus()->getData();
243
244
		$numberDocsInIndex = -1; // flag value for not yet indexed
0 ignored issues
show
Unused Code introduced by
$numberDocsInIndex is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
245
		error_log('CHECKING NUMBER OF INDEXED DOCUMENTS, SHOULD BE ' . $expectedAmount);
246
		error_log(print_r($status,1));
247
248
		if (isset($status['indices']['elastica_ss_module_test_en_us']['docs'])) {
249
			$numberDocsInIndex = $status['indices']['elastica_ss_module_test_en_us']['docs']['num_docs'];
250
			error_log('DOCUMENTS FOUND:'.$numberDocsInIndex);
251
		} else {
252
			$numberDocsInIndex = 0;
253
		}
254
255
		$this->assertEquals($expectedAmount,$numberDocsInIndex);
256
	}
257
258
	/*
259
	Get the number of documents in an index.  It is assumed the index exists, if not the test will fail
260
	 */
261
	public function getNumberOfIndexedDocuments() {
262
		$index = $this->service->getIndex();
263
		$status = $index->getStatus()->getData();
264
265
		$numberDocsInIndex = -1; // flag value for not yet indexed
266
		if (isset($status['indices']['elastica_ss_module_test_en_us']['docs'])) {
267
			$numberDocsInIndex = $status['indices']['elastica_ss_module_test_en_us']['docs']['num_docs'];
268
		}
269
270
		$this->assertGreaterThan(-1, $numberDocsInIndex);
271
		return $numberDocsInIndex;
272
	}
273
}
274