# Copyright (C) 2021 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Apple Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


import attr


@attr.s(frozen=True, slots=True)
class Test(object):
    """Data about a test and its expectations.

    Note that this is inherently platform specific, as expectations are platform specific."""
    test_path = attr.ib(type=str)
    expected_text_path = attr.ib(default=None, type=str)
    expected_image_path = attr.ib(default=None, type=str)
    expected_checksum_path = attr.ib(default=None, type=str)
    expected_audio_path = attr.ib(default=None, type=str)
    reference_files = attr.ib(default=None, type=list)
    is_http_test = attr.ib(default=None, type=bool)
    is_websocket_test = attr.ib(default=None, type=bool)
    is_wpt_test = attr.ib(default=None, type=bool)

    @property
    def needs_http_server(self):
        return self.is_http_test or self.is_websocket_test

    @property
    def needs_websocket_server(self):
        return self.is_websocket_test

    @property
    def needs_wpt_server(self):
        return self.is_wpt_test

    @property
    def needs_any_server(self):
        return self.needs_http_server or self.needs_websocket_server or self.needs_wpt_server
