| Current File : /home/jvzmxxx/wiki1/extensions/EventLogging/server/tests/test_schema.py |
# -*- coding: utf-8 -*-
"""
eventlogging unit tests
~~~~~~~~~~~~~~~~~~~~~~~
This module contains tests for :module:`eventlogging.schema`.
This does not test JSON Schema validation per se, since validation
is delegated to :module:`jsonschema`, which comes with its own
comprehensive suite of unit tests. This module specifically tests
schema cache / HTTP retrieval and the handling of complex
('encapsulated') event objects.
"""
from __future__ import unicode_literals
import unittest
import eventlogging
from .fixtures import (
HttpRequestAttempted,
HttpSchemaTestMixin,
SchemaTestMixin,
TEST_SCHEMA_SCID
)
class HttpSchemaTestCase(HttpSchemaTestMixin, unittest.TestCase):
"""Tests for :func:`eventlogging.schema.http_get_schema`."""
def test_valid_resp(self):
"""Test handling of HTTP response containing valid schema."""
self.http_resp = '{"properties":{"value":{"type":"number"}}}'
schema = eventlogging.schema.http_get_schema(TEST_SCHEMA_SCID)
self.assertEqual(schema, {'properties': {'value': {'type': 'number'}}})
def test_invalid_resp(self):
"""Test handling of HTTP response not containing valid schema."""
self.http_resp = '"foo"'
with self.assertRaises(eventlogging.SchemaError):
eventlogging.schema.http_get_schema(TEST_SCHEMA_SCID)
def test_caching(self):
"""Valid HTTP responses containing JSON Schema are cached."""
self.http_resp = '{"properties":{"value":{"type":"number"}}}'
eventlogging.get_schema(TEST_SCHEMA_SCID)
self.assertIn(TEST_SCHEMA_SCID, eventlogging.schema.schema_cache)
class ValidateScidTestCase(unittest.TestCase):
"""Tests for :func:`eventlogging.schema.validate_scid`."""
schema_name, revision_id = TEST_SCHEMA_SCID
def test_valid_scid(self):
"""Valid SCIDs validate."""
scid = self.schema_name, self.revision_id
self.assertIsNone(eventlogging.schema.validate_scid(scid))
def test_invalid_schema_name(self):
"""Invalid schema name triggers SCID validation failure."""
for invalid_schema_name in ('Foo%', 'X' * 64, 123):
scid = invalid_schema_name, self.revision_id
with self.assertRaises(eventlogging.ValidationError):
eventlogging.schema.validate_scid(scid)
def test_invalid_revision_id(self):
"""Invalid revision ID triggers SCID validation failure."""
for invalid_revision_id in (-1, 0, '1'):
scid = self.schema_name, invalid_revision_id
with self.assertRaises(eventlogging.ValidationError):
eventlogging.schema.validate_scid(scid)
class SchemaTestCase(SchemaTestMixin, unittest.TestCase):
"""Tests for :module:`eventlogging.schema`."""
def test_valid_event(self):
"""Valid events validate."""
self.assertIsValid(self.event)
def test_incomplete_scid(self):
"""Missing SCID in capsule object triggers validation failure."""
self.event.pop('schema')
self.assertIsInvalid(self.event)
def test_missing_property(self):
"""Missing property in capsule object triggers validation failure."""
self.event.pop('timestamp')
self.assertIsInvalid(self.event)
def test_missing_nested_property(self):
"""Missing property in nested event triggers validation failure."""
self.event['event'].pop('value')
self.assertIsInvalid(self.event)
def test_extra_property(self):
"""Missing property in nested event triggers validation failure."""
self.event['event']['season'] = 'summer'
self.assertIsInvalid(self.event)
def test_schema_retrieval(self):
"""Schemas missing from the cache are retrieved via HTTP."""
# Pop the schema from the cache.
eventlogging.schema.schema_cache.pop(TEST_SCHEMA_SCID)
with self.assertRaises(HttpRequestAttempted) as context:
eventlogging.validate(self.event)
self.assertEqual(context.exception.rev_id, 123)
def test_encapsulated_schema(self):
"""get_schema() returns encapsulated schema if requested."""
encapsulated = eventlogging.get_schema(eventlogging.CAPSULE_SCID)
encapsulated['event'] = eventlogging.get_schema(TEST_SCHEMA_SCID)
self.assertEqual(eventlogging.get_schema(TEST_SCHEMA_SCID, True),
encapsulated)
def test_capsule_uuid(self):
"""capsule_uuid() generates a unique UUID for capsule objects."""
self.assertEqual(eventlogging.capsule_uuid(self.event),
'babb66f34a0a5de3be0c6513088be33e')
def test_empty_event(self):
"""An empty event with no mandatory properties should validate"""
self.assertIsValid(self.incorrectly_serialized_empty_event)
def test_create_event_error_unparsed(self):
"""
create_event_error() should create a valid
EventError object without schema or revision set.
"""
invalid_raw_event = "Duh this won't validate against any schema."
error_message = "This is just a test."
error_code = "processor"
event_error = eventlogging.create_event_error(
invalid_raw_event,
error_message,
error_code
)
# Test that this event validates against the EventError schema.
self.assertIsValid(event_error)
self.assertEqual(
event_error['schema'],
eventlogging.schema.ERROR_SCID[0]
)
self.assertEqual(
event_error['revision'],
eventlogging.schema.ERROR_SCID[1]
)
self.assertEqual(
event_error['event']['rawEvent'],
invalid_raw_event
)
self.assertEqual(
event_error['event']['message'],
error_message
)
# assert that schema and revision are the defaults, since there's
# there is no parsed_event and these are not even present in this
# raw_event.
self.assertEqual(
event_error['event']['schema'],
'unknown'
)
self.assertEqual(
event_error['event']['revision'],
-1
)
def test_create_event_error_parsed(self):
"""
create_event_error() should create a valid
EventError object with schema and revision set.
"""
invalid_raw_event = "Duh this won't validate against any schema."
error_message = "This is just a test."
error_code = "processor"
parsed_event = {
'schema': 'Nonya',
'revision': 12345
}
event_error = eventlogging.create_event_error(
invalid_raw_event,
error_message,
error_code,
parsed_event
)
# Test that this event validates against the EventError schema.
self.assertIsValid(event_error)
self.assertEqual(
event_error['schema'],
eventlogging.schema.ERROR_SCID[0]
)
self.assertEqual(
event_error['revision'],
eventlogging.schema.ERROR_SCID[1]
)
self.assertEqual(
event_error['event']['rawEvent'],
invalid_raw_event
)
self.assertEqual(
event_error['event']['message'],
error_message
)
# assert that schema and revision the same as in parsed_event
self.assertEqual(
event_error['event']['schema'],
'Nonya'
)
self.assertEqual(
event_error['event']['revision'],
12345
)
def test_create_event_error_raw_schema_and_revision(self):
"""
create_event_error() should create a valid
EventError object with schema and revision set, extracted
via a regex out of the raw_event.
"""
invalid_raw_event = '?%7B%22event%22%3A%7B%22mobileMode%22%3A' \
'%22stable%22%2C%22name%22%3A%22home%22%2C%22destination%22%3A' \
'%22%2Fwiki%2FPagina_principale%22%7D%2C%22revision%22%3A' \
'11568715%2C%22schema%22%3A' \
'%22MobileWebMainMenuClickTracking%22%2C' \
'%22webHost%22%3A%12345terfdit.m.wikipedia.org%22%2C%22wiki%22' \
'%3A%22itwiki%22%7D; cp3013.esams.wmnet 4724275 ' \
'2015-09-21T21:55:27 1.2.3.4 "Mozilla"'
print(invalid_raw_event)
error_message = "This is just a test."
error_code = "processor"
event_error = eventlogging.create_event_error(
invalid_raw_event,
error_message,
error_code,
)
# Test that this event validates against the EventError schema.
self.assertIsValid(event_error)
self.assertEqual(
event_error['schema'],
eventlogging.schema.ERROR_SCID[0]
)
self.assertEqual(
event_error['revision'],
eventlogging.schema.ERROR_SCID[1]
)
self.assertEqual(
event_error['event']['rawEvent'],
invalid_raw_event
)
self.assertEqual(
event_error['event']['message'],
error_message
)
# assert that schema and revision the same as in the invalid raw event
self.assertEqual(
event_error['event']['schema'],
'MobileWebMainMenuClickTracking'
)
self.assertEqual(
event_error['event']['revision'],
11568715
)