Commit 0bf5c251 authored by Sam Thursfield's avatar Sam Thursfield

functional-tests: Validate SPARQL as part of extractor tests

The existing tests served to check that correct metadata was
extracted. But if an extract module produced invalid SPARQL that
would not be detected, until now.

Fixes tracker#196
parent 1fc425db
Pipeline #220082 passed with stages
in 8 minutes and 12 seconds
......@@ -21,13 +21,12 @@
from gi.repository import GLib
import configparser
import errno
import json
import logging
import os
import shutil
import tempfile
import sys
if 'TRACKER_FUNCTIONAL_TEST_CONFIG' not in os.environ:
......@@ -67,6 +66,12 @@ def cli_subcommands_dir():
return config['TEST_CLI_SUBCOMMANDS_DIR']
def nepomuk_path():
parser = configparser.ConfigParser()
parser.read(config['TEST_DOMAIN_ONTOLOGY_RULE'])
return parser.get('DomainOntology', 'OntologyLocation')
# This path is used for test data for tests which expect filesystem monitoring
# to work. For this reason we must avoid it being on a tmpfs filesystem. Note
# that this MUST NOT be a hidden directory, as Tracker is hardcoded to ignore
......
......@@ -85,8 +85,8 @@ class FlacCuesheetTest(fixtures.TrackerExtractTestCase):
audio_path = pathlib.Path(tmpdir).joinpath('cuesheet-test.flac')
datagenerator.create_test_flac(audio_path, duration=6*60)
result = fixtures.get_tracker_extract_jsonld_output(
cfg.test_environment(tmpdir), audio_path)
result = fixtures.get_tracker_extract_output(
cfg.test_environment(tmpdir), audio_path, output_format='json-ld')
self.assert_extract_result_matches_spec(
self.spec(audio_path), result, audio_path, __file__)
......
......@@ -23,6 +23,11 @@ metadata is extracted. Load dynamically the test information from a data
directory (containing xxx.expected files)
"""
import gi
gi.require_version('Tracker', '3.0')
from gi.repository import Gio
from gi.repository import Tracker
import json
import os
import shutil
......@@ -64,6 +69,21 @@ class GenericExtractionTestCase(fixtures.TrackerExtractTestCase):
def __get_bugnumber(self):
return self.spec['test'].get('Bugzilla')
def validate_sparql_update(self, sparql):
"""Create a temporary database and run the given SPARQL update.
This gives us a smoke test to detect any situation where the
extractor generates invalid SPARQL.
"""
cancellable = None
ontology_path = Gio.File.new_for_uri(cfg.nepomuk_path())
db = Tracker.SparqlConnection.new(Tracker.SparqlConnectionFlags.NONE,
None, # create in-memory database,
ontology_path,
cancellable)
db.update(sparql, cancellable)
def generic_test_extraction(self):
abs_description = os.path.abspath(self.descfile)
......@@ -76,8 +96,15 @@ class GenericExtractionTestCase(fixtures.TrackerExtractTestCase):
tmpdir = tempfile.mkdtemp(prefix='tracker-extract-test-')
try:
extra_env = cfg.test_environment(tmpdir)
result = fixtures.get_tracker_extract_jsonld_output(extra_env, self.file_to_extract)
self.__assert_extraction_ok(result)
jsonld = fixtures.get_tracker_extract_output(extra_env,
self.file_to_extract,
output_format='json-ld')
self.__assert_extraction_ok(jsonld)
sparql = fixtures.get_tracker_extract_output(extra_env,
self.file_to_extract,
output_format='sparql')
self.validate_sparql_update(sparql)
finally:
shutil.rmtree(tmpdir, ignore_errors=True)
......
......@@ -245,13 +245,14 @@ class TrackerMinerFTSTest (TrackerMinerTest):
return int(result[0][0])
def get_tracker_extract_jsonld_output(extra_env, filename, mime_type=None):
def get_tracker_extract_output(extra_env, filename, output_format='json-ld', mime_type=None):
"""
Runs `tracker-extract --file` to extract metadata from a file.
"""
tracker_extract = os.path.join(cfg.TRACKER_EXTRACT_PATH)
command = [tracker_extract, '--output-format=json-ld', '--file', str(filename)]
command = [tracker_extract, '--output-format', output_format, '--file',
str(filename)]
if mime_type is not None:
command.extend(['--mime', mime_type])
......@@ -285,19 +286,20 @@ def get_tracker_extract_jsonld_output(extra_env, filename, mime_type=None):
error_output = stderr.decode('utf-8').strip()
log.debug("Error output from tracker-extract:\n%s", error_output)
try:
output = stdout.decode('utf-8')
if len(output.strip()) == 0:
raise RuntimeError("tracker-extract didn't return any data.\n"
"Error output was: %s" % error_output)
output = stdout.decode('utf-8')
data = json.loads(output)
except ValueError as e:
raise RuntimeError("tracker-extract did not return valid JSON data: %s\n"
"Output was: %s" % (e, output))
if len(output.strip()) == 0:
raise RuntimeError("tracker-extract didn't return any data.\n"
"Error output was: %s" % error_output)
return data
if output_format == 'json-ld':
try:
return json.loads(output)
except ValueError as e:
raise RuntimeError("tracker-extract did not return valid JSON data: %s\n"
"Output was: %s" % (e, output))
else:
return output
class TrackerExtractTestCase(ut.TestCase):
......@@ -326,7 +328,7 @@ class TrackerExtractTestCase(ut.TestCase):
"""
Checks tracker-extract json-ld output against the expected result.
Use get_tracker_extract_jsonld_output() to get the extractor output.
Use get_tracker_extract_output() to get the extractor output.
Look in test-extraction-data/*/*.expected.json for examples of the spec
format.
......
......@@ -40,7 +40,7 @@ class WritebackAudioTest(fixtures.TrackerWritebackTest):
self.wait_for_file_change(path, initial_mtime)
results = fixtures.get_tracker_extract_jsonld_output({}, path)
results = fixtures.get_tracker_extract_output({}, path, output_format='json-ld')
self.assertIn(TEST_VALUE, results[prop])
def test_writeback_mp3(self):
......
......@@ -85,7 +85,7 @@ class WritebackKeepDateTest (fixtures.TrackerWritebackTest):
self.wait_for_file_change(jpeg_path, initial_mtime)
# Check the value is written in the file
metadata = fixtures.get_tracker_extract_jsonld_output(self.extra_env, jpeg_path, "")
metadata = fixtures.get_tracker_extract_output(self.extra_env, jpeg_path, output_format='json-ld')
tags = metadata.get('nao:hasTag', [])
tag_names = [tag['nao:prefLabel'] for tag in tags]
......
......@@ -63,7 +63,7 @@ class WritebackImagesTest(fixtures.TrackerWritebackTest):
self.wait_for_file_change(path, initial_mtime)
log.debug("Got the change")
results = fixtures.get_tracker_extract_jsonld_output({}, path, mimetype)
results = fixtures.get_tracker_extract_output({}, path, mime_type=mimetype, output_format='json-ld')
keyDict = expectedKey or prop
self.assertIn(TEST_VALUE, results[keyDict])
......@@ -87,7 +87,7 @@ class WritebackImagesTest(fixtures.TrackerWritebackTest):
self.wait_for_file_change(path, initial_mtime)
results = fixtures.get_tracker_extract_jsonld_output(self.extra_env, filename, mimetype)
results = fixtures.get_tracker_extract_output(self.extra_env, filename, mime_type=mimetype, output_format='json-ld')
self.assertIn("testTag", results["nao:hasTag"])
# JPEG test
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment