"""
Tests covering the YAML linter.
"""

from yamlschema import lint_buffer

import pytest


@pytest.mark.parametrize('schema, obj', [
    ({"type": "number"},
     "---\n1.0"),
    ({"type": "integer"},
     "---\n3"),
    ({"type": "string"},
     "---\nfoo bar baz"),
    ({"type": "string",
      "maxLength": 15},
     "---\nfoo bar baz"),
    ({"type": "string",
      "minLength": 10},
     "---\nfoo bar baz"),
    ({"type": "string",
      "pattern": "^foo.*"},
     "---\nfoo bar baz"),
    ({"type": "object",
      "additionalProperties": True},
     "---\nfoo: bar\nbaz: qux"),
    ({"type": "object",
      "properties": {"foo": {"type": "string"}}},
     "---\nfoo: bar\nbaz: qux"),
    ({"type": "object",
      "properties": {"foo": {"type": "string"}},
      "additionalProperties": False},
     "---\nfoo: bar"),
    ({"type": "object",
      "properties": {"foo": {"type": "object"}}},
     "---\nfoo: {}"),
    ({"type": "object",
      "properties": {"foo": {
          "type": "array",
          "items": {"type": "object"}}}},
     "---\nfoo: [{}, {}, {foo: bar}]"),
])
def test_lint_document_ok(schema, obj):
    assert not list(lint_buffer(schema, obj))


@pytest.mark.parametrize('msg, schema, obj', [
    # Numerics
    ("Floats are not ints",
     {"type": "integer"},
     "---\n1.0"),
    ("Ints are not floats",
     {"type": "number"},
     "---\n1"),

    # Numerics - range limits. Integer edition
    ("1 is the limit of the range",
     {"type": "integer",
      "exclusiveMaximum": 1},
     "---\n1"),
    ("1 is the limit of the range",
     {"type": "integer",
      "exclusiveMinimum": 1},
     "---\n1"),
    ("1 is out of the range",
     {"type": "integer",
      "minimum": 2},
     "---\n1"),
    ("1 is out of the range",
     {"type": "integer",
      "maximum": 0},
     "---\n1"),
    ("1 is out of the range",
     {"type": "integer",
      "exclusiveMinimum": 1},
     "---\n1"),

    # Numerics - range limits. Number/Float edition
    ("1 is the limit of the range",
     {"type": "number",
      "exclusiveMaximum": 1},
     "---\n1.0"),
    ("1 is the limit of the range",
     {"type": "number",
      "exclusiveMinimum": 1},
     "---\n1.0"),
    ("1 is out of the range",
     {"type": "number",
      "minimum": 2},
     "---\n1.0"),
    ("1 is out of the range",
     {"type": "number",
      "maximum": 0},
     "---\n1.0"),
    ("1 is out of the range",
     {"type": "number",
      "exclusiveMinimum": 1},
     "---\n1.0"),

    # String shit
    ("String too short",
     {"type": "string", "minLength": 1},
     "---\n''"),
    ("String too long",
     {"type": "string", "maxLength": 1},
     "---\nfoo"),
    ("String does not match pattern",
     {"type": "string", "pattern": "bar"},
     "---\nfoo"),
    ("String does not fully match pattern",
     {"type": "string", "pattern": "foo"},
     "---\nfooooooooo"),
])
def test_lint_document_fails(msg, schema, obj):
    assert list(lint_buffer(schema, obj)), msg