import mock
import pytest

import py_zipkin.storage


@pytest.fixture(autouse=True, scope="module")
def create_zipkin_attrs():
    # The following tests all expect _thread_local.zipkin_attrs to exist: if it
    # doesn't, mock.patch will fail.
    py_zipkin.storage.ThreadLocalStack().get()


def test_get_zipkin_attrs_returns_none_if_no_zipkin_attrs():
    tracer = py_zipkin.storage.get_default_tracer()
    with mock.patch.object(tracer._context_stack, "_storage", []):
        assert not py_zipkin.storage.ThreadLocalStack().get()
        assert not py_zipkin.storage.ThreadLocalStack().get()


def test_get_zipkin_attrs_with_context_returns_none_if_no_zipkin_attrs():
    with mock.patch.object(py_zipkin.storage.log, "warning", autospec=True) as log:
        assert not py_zipkin.storage.Stack([]).get()
        assert log.call_count == 1


def test_storage_stack_still_works_if_you_dont_pass_in_storage():
    # Let's make sure this still works if we don't pass in a custom storage.
    assert not py_zipkin.storage.Stack().get()


def test_get_zipkin_attrs_returns_the_last_of_the_list():
    tracer = py_zipkin.storage.get_default_tracer()
    with mock.patch.object(tracer._context_stack, "_storage", ["foo"]):
        assert "foo" == py_zipkin.storage.ThreadLocalStack().get()


def test_get_zipkin_attrs_with_context_returns_the_last_of_the_list():
    assert "foo" == py_zipkin.storage.Stack(["bar", "foo"]).get()


def test_pop_zipkin_attrs_does_nothing_if_no_requests():
    tracer = py_zipkin.storage.get_default_tracer()
    with mock.patch.object(tracer._context_stack, "_storage", []):
        assert not py_zipkin.storage.ThreadLocalStack().pop()


def test_pop_zipkin_attrs_with_context_does_nothing_if_no_requests():
    assert not py_zipkin.storage.Stack([]).pop()


def test_pop_zipkin_attrs_removes_the_last_zipkin_attrs():
    tracer = py_zipkin.storage.get_default_tracer()
    with mock.patch.object(tracer._context_stack, "_storage", ["foo", "bar"]):
        assert "bar" == py_zipkin.storage.ThreadLocalStack().pop()
        assert "foo" == py_zipkin.storage.ThreadLocalStack().get()


def test_pop_zipkin_attrs_with_context_removes_the_last_zipkin_attrs():
    context_stack = py_zipkin.storage.Stack(["foo", "bar"])
    assert "bar" == context_stack.pop()
    assert "foo" == context_stack.get()


def test_push_zipkin_attrs_adds_new_zipkin_attrs_to_list():
    tracer = py_zipkin.storage.get_default_tracer()
    with mock.patch.object(tracer._context_stack, "_storage", ["foo"]):
        assert "foo" == py_zipkin.storage.ThreadLocalStack().get()
        py_zipkin.storage.ThreadLocalStack().push("bar")
        assert "bar" == py_zipkin.storage.ThreadLocalStack().get()


def test_push_zipkin_attrs_with_context_adds_new_zipkin_attrs_to_list():
    stack = py_zipkin.storage.Stack(["foo"])
    assert "foo" == stack.get()
    stack.push("bar")
    assert "bar" == stack.get()


def test_stack_copy():
    stack = py_zipkin.storage.Stack()
    stack.push("a")
    stack.push("b")

    the_copy = stack.copy()
    the_copy.push("c")

    stack.push("d")

    assert ["a", "b", "c"] == the_copy._storage
    assert ["a", "b", "d"] == stack._storage

[((7, 1, 7, 45), 'pytest.fixture', 'pytest.fixture', (), '', False, 'import pytest\n'), ((16, 9, 16, 65), 'mock.patch.object', 'mock.patch.object', ({(16, 27, 16, 48): 'tracer._context_stack', (16, 50, 16, 60): '"""_storage"""', (16, 62, 16, 64): '[]'}, {}), "(tracer._context_stack, '_storage', [])", False, 'import mock\n'), ((22, 9, 22, 75), 'mock.patch.object', 'mock.patch.object', (), '', False, 'import mock\n'), ((34, 9, 34, 70), 'mock.patch.object', 'mock.patch.object', ({(34, 27, 34, 48): 'tracer._context_stack', (34, 50, 34, 60): '"""_storage"""', (34, 62, 34, 69): "['foo']"}, {}), "(tracer._context_stack, '_storage', ['foo'])", False, 'import mock\n'), ((44, 9, 44, 65), 'mock.patch.object', 'mock.patch.object', ({(44, 27, 44, 48): 'tracer._context_stack', (44, 50, 44, 60): '"""_storage"""', (44, 62, 44, 64): '[]'}, {}), "(tracer._context_stack, '_storage', [])", False, 'import mock\n'), ((54, 9, 54, 77), 'mock.patch.object', 'mock.patch.object', ({(54, 27, 54, 48): 'tracer._context_stack', (54, 50, 54, 60): '"""_storage"""', (54, 62, 54, 76): "['foo', 'bar']"}, {}), "(tracer._context_stack, '_storage', ['foo', 'bar'])", False, 'import mock\n'), ((67, 9, 67, 70), 'mock.patch.object', 'mock.patch.object', ({(67, 27, 67, 48): 'tracer._context_stack', (67, 50, 67, 60): '"""_storage"""', (67, 62, 67, 69): "['foo']"}, {}), "(tracer._context_stack, '_storage', ['foo'])", False, 'import mock\n')]