# Copyright 2026 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

import unittest
import os
import tempfile
import shutil
import sys

# Import the script to test
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
import discovery_utils

class TestDiscoveryUtils(unittest.TestCase):
    def setUp(self):
        self.test_dir = tempfile.mkdtemp()
        self.app_path = os.path.join(self.test_dir, "app")
        os.makedirs(self.app_path)
        self.boards_dir = os.path.join(self.app_path, "boards")

    def tearDown(self):
        shutil.rmtree(self.test_dir)

    def test_check_filesystem_overrides_no_boards_dir(self):
        self.assertFalse(discovery_utils.check_filesystem_overrides(self.app_path, "board1"))

    def test_check_filesystem_overrides_empty_boards_dir(self):
        os.makedirs(self.boards_dir)
        self.assertFalse(discovery_utils.check_filesystem_overrides(self.app_path, "board1"))

    def test_check_filesystem_overrides_match_conf(self):
        os.makedirs(self.boards_dir)
        with open(os.path.join(self.boards_dir, "board1.conf"), 'w') as f:
            f.write("")
        self.assertTrue(discovery_utils.check_filesystem_overrides(self.app_path, "board1"))

    def test_check_filesystem_overrides_match_overlay(self):
        os.makedirs(self.boards_dir)
        with open(os.path.join(self.boards_dir, "board1.overlay"), 'w') as f:
            f.write("")
        self.assertTrue(discovery_utils.check_filesystem_overrides(self.app_path, "board1"))

    def test_check_filesystem_overrides_match_with_qualifier(self):
        os.makedirs(self.boards_dir)
        with open(os.path.join(self.boards_dir, "board1_qual.conf"), 'w') as f:
            f.write("")
        self.assertTrue(discovery_utils.check_filesystem_overrides(self.app_path, "board1/qual"))

    def test_check_filesystem_overrides_match_fallback(self):
        os.makedirs(self.boards_dir)
        with open(os.path.join(self.boards_dir, "board1.conf"), 'w') as f:
            f.write("")
        self.assertTrue(discovery_utils.check_filesystem_overrides(self.app_path, "board1/qual"))

    def test_check_filesystem_overrides_no_match_with_qualifier(self):
        os.makedirs(self.boards_dir)
        with open(os.path.join(self.boards_dir, "board2.conf"), 'w') as f:
            f.write("")
        self.assertFalse(discovery_utils.check_filesystem_overrides(self.app_path, "board1/qual"))

    def test_check_filesystem_overrides_match_qemu_xtensa(self):
        os.makedirs(self.boards_dir)
        with open(os.path.join(self.boards_dir, "qemu_xtensa_dc233c.conf"), 'w') as f:
            f.write("")
        self.assertTrue(discovery_utils.check_filesystem_overrides(self.app_path, "qemu_xtensa/dc233c"))

if __name__ == '__main__':
    unittest.main()
