# Path: apiritif/http.py
# class _EventRecorder(object):
#     local = threading.local()
# 
#     def __init__(self):
#         self.log = log.getChild('recorder')
#         self.log.debug("Creating recorder")
# 
#     def get_recording(self):
#         rec = getattr(self.local, 'recording', None)
#         if rec is None:
#             self.local.recording = []
#         return self.local.recording
# 
#     def pop_events(self, from_ts, to_ts):
#         recording = self.get_recording()
#         collected = []
#         new_recording = []
#         for event in recording:
#             if from_ts <= event.timestamp <= to_ts:
#                 collected.append(event)
#             else:
#                 new_recording.append(event)
#         del recording[:]
#         recording.extend(new_recording)
#         return collected
# 
#     def record_event(self, event):
#         self.log.debug("Recording event %r", event)
#         recording = self.get_recording()
#         recording.append(event)
# 
#     def record_transaction_start(self, tran):
#         self.record_event(TransactionStarted(tran))
#         if isinstance(tran, transaction_logged):
#             self.log.info(u"Transaction started:: start_time=%.3f,name=%s", tran.start_time(), tran.name)
# 
#     def record_transaction_end(self, tran):
#         self.record_event(TransactionEnded(tran))
#         if isinstance(tran, transaction_logged):
#             self.log.info(u"Transaction ended:: duration=%.3f,name=%s", tran.duration(), tran.name)
# 
#     def record_http_request(self, method, address, request, response, session):
#         self.record_event(Request(method, address, request, response, session))
# 
#     def record_http_request_failure(self, method, address, request, exception, session):
#         failure = RequestFailure(method, address, request, exception, session)
#         self.record_event(failure)
# 
#     def record_assertion(self, assertion_name, target_response, extras):
#         self.record_event(Assertion(assertion_name, target_response, extras))
# 
#     def record_assertion_failure(self, assertion_name, target_response, failure_message):
#         self.record_event(AssertionFailure(assertion_name, target_response, failure_message))
# 
#     @staticmethod
#     def assertion_decorator(assertion_method):
#         @wraps(assertion_method)
#         def _impl(self, *method_args, **method_kwargs):
#             assertion_name = getattr(assertion_method, '__name__', 'assertion')
#             extras = {"args": list(method_args), "kwargs": method_kwargs}
#             recorder.record_assertion(assertion_name, self, extras)
#             try:
#                 return assertion_method(self, *method_args, **method_kwargs)
#             except BaseException as exc:
#                 recorder.record_assertion_failure(assertion_name, self, str(exc))
#                 raise
# 
#         return _impl
# 
# class Event(object):
#     def __init__(self, response=None):
#         self.timestamp = time.time()
#         self.response = response
# 
#     def to_dict(self):  # supposed to be overridden by extenders
#         return {}


import threading
import time
import sys
from unittest import TestCase
from apiritif.http import _EventRecorder, Event



class EventGenerator(threading.Thread):
    def __init__(self, recorder, index, events_count):
        self.recorder = recorder
        self.index = index
        self.events_count = events_count
        self.events = [Event(response=self.index * (i + 1)) for i in range(self.events_count)]

        super(EventGenerator, self).__init__(target=self._record_events)

    def _record_events(self):
        for event in self.events:
            self.recorder.record_event(event)
            time.sleep(0.1)

        self.result_events = self.recorder.pop_events(from_ts=-1, to_ts=sys.maxsize)


class TestRecorder(TestCase):

    # _EventRecorder class have to store separate events for separate thread.
    # Here each fake thread (EventGenerator) generate an event for common recorder.
    # Then each thread read this event from this recorder with some delay.
    # As the result written and read events should be the same.
    def test_recorder_events_per_thread(self):

# Path: apiritif/http.py
# class _EventRecorder(object):
#     local = threading.local()
# 
#     def __init__(self):
#         self.log = log.getChild('recorder')
#         self.log.debug("Creating recorder")
# 
#     def get_recording(self):
#         rec = getattr(self.local, 'recording', None)
#         if rec is None:
#             self.local.recording = []
#         return self.local.recording
# 
#     def pop_events(self, from_ts, to_ts):
#         recording = self.get_recording()
#         collected = []
#         new_recording = []
#         for event in recording:
#             if from_ts <= event.timestamp <= to_ts:
#                 collected.append(event)
#             else:
#                 new_recording.append(event)
#         del recording[:]
#         recording.extend(new_recording)
#         return collected
# 
#     def record_event(self, event):
#         self.log.debug("Recording event %r", event)
#         recording = self.get_recording()
#         recording.append(event)
# 
#     def record_transaction_start(self, tran):
#         self.record_event(TransactionStarted(tran))
#         if isinstance(tran, transaction_logged):
#             self.log.info(u"Transaction started:: start_time=%.3f,name=%s", tran.start_time(), tran.name)
# 
#     def record_transaction_end(self, tran):
#         self.record_event(TransactionEnded(tran))
#         if isinstance(tran, transaction_logged):
#             self.log.info(u"Transaction ended:: duration=%.3f,name=%s", tran.duration(), tran.name)
# 
#     def record_http_request(self, method, address, request, response, session):
#         self.record_event(Request(method, address, request, response, session))
# 
#     def record_http_request_failure(self, method, address, request, exception, session):
#         failure = RequestFailure(method, address, request, exception, session)
#         self.record_event(failure)
# 
#     def record_assertion(self, assertion_name, target_response, extras):
#         self.record_event(Assertion(assertion_name, target_response, extras))
# 
#     def record_assertion_failure(self, assertion_name, target_response, failure_message):
#         self.record_event(AssertionFailure(assertion_name, target_response, failure_message))
# 
#     @staticmethod
#     def assertion_decorator(assertion_method):
#         @wraps(assertion_method)
#         def _impl(self, *method_args, **method_kwargs):
#             assertion_name = getattr(assertion_method, '__name__', 'assertion')
#             extras = {"args": list(method_args), "kwargs": method_kwargs}
#             recorder.record_assertion(assertion_name, self, extras)
#             try:
#                 return assertion_method(self, *method_args, **method_kwargs)
#             except BaseException as exc:
#                 recorder.record_assertion_failure(assertion_name, self, str(exc))
#                 raise
# 
#         return _impl
# 
# class Event(object):
#     def __init__(self, response=None):
#         self.timestamp = time.time()
#         self.response = response
# 
#     def to_dict(self):  # supposed to be overridden by extenders
#         return {}


# Path: tests/unit/test_recorder.py
import threading
import time
import sys
from unittest import TestCase
from apiritif.http import _EventRecorder, Event




class EventGenerator(threading.Thread):
    def __init__(self, recorder, index, events_count):
        self.recorder = recorder
        self.index = index
        self.events_count = events_count
        self.events = [Event(response=self.index * (i + 1)) for i in range(self.events_count)]

        super(EventGenerator, self).__init__(target=self._record_events)

    def _record_events(self):
        for event in self.events:
            self.recorder.record_event(event)
            time.sleep(0.1)

        self.result_events = self.recorder.pop_events(from_ts=-1, to_ts=sys.maxsize)


class TestRecorder(TestCase):

    # _EventRecorder class have to store separate events for separate thread.
    # Here each fake thread (EventGenerator) generate an event for common recorder.
    # Then each thread read this event from this recorder with some delay.
    # As the result written and read events should be the same.
    def test_recorder_events_per_thread(self):

        recorder = _EventRecorder()