def testEchoedExtraRequestDataWithJsonFormat(self):
        component = SruTermDrilldown()

        result = "".join(
            list(
                component.echoedExtraRequestData(sruArguments={
                    'x-term-drilldown': ['field0/field1,field2', 'field3'],
                    'version':
                    '1.1',
                    'x-drilldown-format': ['json']
                },
                                                 version='1.1')))

        self.assertEqualsWS(_DRILLDOWN_HEADER % _DRILLDOWN_XSD_2013 + """
            <dd:request>
                <dd:x-term-drilldown>field0/field1</dd:x-term-drilldown>
                <dd:x-term-drilldown>field2</dd:x-term-drilldown>
                <dd:x-term-drilldown>field3</dd:x-term-drilldown>
                <dd:x-drilldown-format>json</dd:x-drilldown-format>
            </dd:request>""" +\
            DRILLDOWN_FOOTER, result)

        xsdFilename = self._getXsdFilename(result)
        assertValid(result, join(schemasPath, xsdFilename))
        with open(join(schemasPath, xsdFilename)) as fp:
            assertValid(fp.read(), join(schemasPath, 'XMLSchema.xsd'))
    def testSruTermDrilldown(self):
        sruTermDrilldown = SruTermDrilldown()

        drilldownData = [
                {'fieldname': 'field0', 'terms': [{'term': 'value0_0', 'count': 14}]},
                {'fieldname': 'field1', 'terms': [{'term': 'value1_0', 'count': 13}, {'term': 'value1_1', 'count': 11}]},
                {'fieldname': 'field2', 'terms': [{'term': 'value2_0', 'count': 3}, {'term': 'value2_1', 'count': 2}, {'term': 'value2_2', 'count': 1}]}
        ]

        response = ''.join(compose(sruTermDrilldown.extraResponseData(drilldownData, sruArguments={})))

        self.assertEqualsWS(DRILLDOWN_HEADER + """<dd:term-drilldown><dd:navigator name="field0">
    <dd:item count="14">value0_0</dd:item>
</dd:navigator>
<dd:navigator name="field1">
    <dd:item count="13">value1_0</dd:item>
    <dd:item count="11">value1_1</dd:item>
</dd:navigator>
<dd:navigator name="field2">
    <dd:item count="3">value2_0</dd:item>
    <dd:item count="2">value2_1</dd:item>
    <dd:item count="1">value2_2</dd:item>
</dd:navigator></dd:term-drilldown></dd:drilldown>""", response)

        xsdFilename = self._getXsdFilename(response)
        assertValid(response, join(schemasPath, xsdFilename))
    def testQueryTimeInExtraResponse(self):
        handler = SruHandler(includeQueryTimes=True)
        observer = CallTrace('observer', emptyGeneratorMethods=['echoedExtraRequestData', 'extraResponseData'])

        times = [1, 2.5, 3.5]
        def timeNow():
            return times.pop(0)
        handler._timeNow = timeNow

        def executeQuery(**kwargs):
            response = Response(total=0, hits=[])
            response.queryTime=5
            raise StopIteration(response)
            yield
        observer.methods['executeQuery'] = executeQuery
        handler.addObserver(observer)
        arguments = dict(startRecord=11, maximumRecords=15, query='query', recordPacking='string', recordSchema='schema')
        result = "".join(compose(handler.searchRetrieve(sruArguments=arguments, **arguments)))
        sruResponse = parse(StringIO(result))
        extraResponseData = sruResponse.xpath('/srw:searchRetrieveResponse/srw:extraResponseData', namespaces={'srw':"http://www.loc.gov/zing/srw/"})[0]
        self.assertEqualsWS("""<srw:extraResponseData %(xmlns_srw)s %(xmlns_diag)s %(xmlns_xcql)s %(xmlns_dc)s %(xmlns_meresco_srw)s>
        <querytimes xmlns="http://meresco.org/namespace/timing">
            <sruHandling>PT2.500S</sruHandling>
            <sruQueryTime>PT1.500S</sruQueryTime>
            <index>PT0.005S</index>
        </querytimes>
</srw:extraResponseData>""" % namespaces, lxmltostring(extraResponseData))
        queryTimes = lxmltostring(extraResponseData.xpath('//ti:querytimes', namespaces={'ti':"http://meresco.org/namespace/timing"})[0])
        assertValid(queryTimes, join(schemasPath, 'timing-20120827.xsd'))
        self.assertEquals(['executeQuery', 'echoedExtraRequestData', 'extraResponseData', 'handleQueryTimes'], observer.calledMethodNames())
        self.assertEquals({'sru': Decimal("2.500"), 'queryTime': Decimal("1.500"), 'index': Decimal("0.005")}, observer.calledMethods[3].kwargs)
    def testValidXml(self):
        component = SruParser()
        sruHandler = SruHandler()
        component.addObserver(sruHandler)
        observer = CallTrace('observer')
        sruHandler.addObserver(observer)
        response = Response(total=2, hits=[Hit('id0'), Hit('id1')])
        def executeQuery(**kwargs):
            raise StopIteration(response)
            yield
        def retrieveData(**kwargs):
            raise StopIteration('<bike/>')
            yield
        observer.methods['executeQuery'] = executeQuery
        observer.returnValues['echoedExtraRequestData'] = (f for f in [])
        observer.returnValues['extraResponseData'] = (f for f in [])
        observer.methods['extraRecordData'] = lambda hit: (f for f in [])
        observer.methods['retrieveData'] = retrieveData

        result = ''.join(compose(component.handleRequest(arguments={'version':['1.1'], 'query': ['aQuery'], 'operation':['searchRetrieve']})))
        header, body = result.split('\r\n'*2)
        assertValid(body, join(schemasPath, 'srw-types1.2.xsd'))
        self.assertTrue('<bike/>' in body, body)

        result = ''.join(compose(component.handleRequest(arguments={'version':['1.1'], 'operation':['searchRetrieve']})))
        header, body = result.split('\r\n'*2)
        assertValid(body, join(schemasPath, 'srw-types1.2.xsd'))
        self.assertTrue('diagnostic' in body, body)
    def testSruTermDrilldown(self):
        sruTermDrilldown = SruTermDrilldown()

        drilldownData = [{
            'fieldname': 'field0',
            'terms': [{
                'term': 'value0_0',
                'count': 14
            }]
        }, {
            'fieldname':
            'field1',
            'terms': [{
                'term': 'value1_0',
                'count': 13
            }, {
                'term': 'value1_1',
                'count': 11
            }]
        }, {
            'fieldname':
            'field2',
            'terms': [{
                'term': 'value2_0',
                'count': 3
            }, {
                'term': 'value2_1',
                'count': 2
            }, {
                'term': 'value2_2',
                'count': 1
            }]
        }]

        response = ''.join(
            compose(
                sruTermDrilldown.extraResponseData(drilldownData,
                                                   sruArguments={})))

        self.assertEqualsWS(
            DRILLDOWN_HEADER +
            """<dd:term-drilldown><dd:navigator name="field0">
    <dd:item count="14">value0_0</dd:item>
</dd:navigator>
<dd:navigator name="field1">
    <dd:item count="13">value1_0</dd:item>
    <dd:item count="11">value1_1</dd:item>
</dd:navigator>
<dd:navigator name="field2">
    <dd:item count="3">value2_0</dd:item>
    <dd:item count="2">value2_1</dd:item>
    <dd:item count="1">value2_2</dd:item>
</dd:navigator></dd:term-drilldown></dd:drilldown>""", response)

        xsdFilename = self._getXsdFilename(response)
        assertValid(response, join(schemasPath, xsdFilename))
    def testEchoedExtraRequestDataWithJsonFormat(self):
        component = SruTermDrilldown()

        result = "".join(list(component.echoedExtraRequestData(sruArguments={'x-term-drilldown': ['field0/field1,field2','field3'], 'version': '1.1', 'x-drilldown-format': ['json']}, version='1.1')))

        self.assertEqualsWS(_DRILLDOWN_HEADER % _DRILLDOWN_XSD_2013 + """
            <dd:request>
                <dd:x-term-drilldown>field0/field1</dd:x-term-drilldown>
                <dd:x-term-drilldown>field2</dd:x-term-drilldown>
                <dd:x-term-drilldown>field3</dd:x-term-drilldown>
                <dd:x-drilldown-format>json</dd:x-drilldown-format>
            </dd:request>""" +\
            DRILLDOWN_FOOTER, result)

        xsdFilename = self._getXsdFilename(result)
        assertValid(result, join(schemasPath, xsdFilename))
        assertValid(open(join(schemasPath, xsdFilename)).read(), join(schemasPath, 'XMLSchema.xsd'))
    def testSruTermDrilldownWithSubTerms(self):
        sruTermDrilldown = SruTermDrilldown(defaultFormat=FORMAT_XML)

        drilldownData = [
                {
                    'fieldname': 'field0',
                    'terms': [
                        {
                            'term': 'value0',
                            'count': 1,
                            'subterms': [
                                {
                                    'term': 'value0_0',
                                    'count': 10,
                                },
                                {
                                    'term': 'value0_1',
                                    'count': 20
                                }
                            ]
                        },
                        {
                            'term': 'value1',
                            'count': 2
                        }
                    ]
                }
            ]

        response = ''.join(compose(sruTermDrilldown.extraResponseData(drilldownData, sruArguments={})))

        self.assertEqualsWS(_DRILLDOWN_HEADER % _DRILLDOWN_XSD_2013 + """<dd:term-drilldown><dd:navigator name="field0">
    <dd:item count="1" value="value0">
        <dd:navigator name="subterms">
            <dd:item count="10" value="value0_0"/>
            <dd:item count="20" value="value0_1"/>
        </dd:navigator>
    </dd:item>
    <dd:item count="2" value="value1"/>
</dd:navigator></dd:term-drilldown></dd:drilldown>""", response)
        xsdFilename = self._getXsdFilename(response)
        assertValid(response, join(schemasPath, xsdFilename))
    def testSruTermDrilldownWithSubTerms(self):
        sruTermDrilldown = SruTermDrilldown(defaultFormat=FORMAT_XML)

        drilldownData = [{
            'fieldname':
            'field0',
            'terms': [{
                'term':
                'value0',
                'count':
                1,
                'subterms': [{
                    'term': 'value0_0',
                    'count': 10,
                }, {
                    'term': 'value0_1',
                    'count': 20
                }]
            }, {
                'term': 'value1',
                'count': 2
            }]
        }]

        response = ''.join(
            compose(
                sruTermDrilldown.extraResponseData(drilldownData,
                                                   sruArguments={})))

        self.assertEqualsWS(
            _DRILLDOWN_HEADER % _DRILLDOWN_XSD_2013 +
            """<dd:term-drilldown><dd:navigator name="field0">
    <dd:item count="1" value="value0">
        <dd:navigator name="subterms">
            <dd:item count="10" value="value0_0"/>
            <dd:item count="20" value="value0_1"/>
        </dd:navigator>
    </dd:item>
    <dd:item count="2" value="value1"/>
</dd:navigator></dd:term-drilldown></dd:drilldown>""", response)
        xsdFilename = self._getXsdFilename(response)
        assertValid(response, join(schemasPath, xsdFilename))
    def testSruTermDrilldownWithPivotsInJson(self):
        sruTermDrilldown = SruTermDrilldown(defaultFormat=FORMAT_JSON)

        drilldownData = [{
            'fieldname':
            'field0',
            'terms': [{
                'term': 'value0',
                'count': 1,
                'pivot': {
                    'fieldname':
                    'field1',
                    'terms': [{
                        'term': 'value0_0',
                        'count': 10,
                    }, {
                        'term': 'value0 & 1',
                        'count': 20
                    }]
                }
            }, {
                'term': 'value1',
                'count': 2
            }]
        }]

        response = ''.join(
            compose(
                sruTermDrilldown.extraResponseData(
                    drilldownData,
                    sruArguments={'x-drilldown-format': ['json']})))
        self.assertEqual(
            drilldownData,
            loads(
                xpathFirst(
                    XML(response),
                    '//drilldown:term-drilldown/drilldown:json/text()')))

        xsdFilename = self._getXsdFilename(response)
        assertValid(response, join(schemasPath, xsdFilename))
    def testSruTermDrilldownWithPivotsInJson(self):
        sruTermDrilldown = SruTermDrilldown(defaultFormat=FORMAT_JSON)

        drilldownData = [
                {
                    'fieldname': 'field0',
                    'terms': [
                        {
                            'term': 'value0',
                            'count': 1,
                            'pivot': {
                                'fieldname': 'field1',
                                'terms': [
                                    {
                                        'term': 'value0_0',
                                        'count': 10,
                                    },
                                    {
                                        'term': 'value0 & 1',
                                        'count': 20
                                    }
                                ]
                            }
                        },
                        {
                            'term': 'value1',
                            'count': 2
                        }
                    ]
                }
            ]

        response = ''.join(compose(sruTermDrilldown.extraResponseData(drilldownData, sruArguments={'x-drilldown-format': ['json']})))
        self.assertEquals(drilldownData, loads(xpathFirst(XML(response), '//drilldown:term-drilldown/drilldown:json/text()')))

        xsdFilename = self._getXsdFilename(response)
        assertValid(response, join(schemasPath, xsdFilename))