/*
 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER 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.
 */


#include "lt_net_netdb.h"

static int AddrInfoTest(void)
{
    // Prerequisite: correct DNS servers must be configured.
    char host_file[] = "127.0.0.2 example.com\n", serv_file[] = "ftp		21/tcp\n";
    char *pathList[] = {"/etc/hosts", "/etc/services"};
    char *streamList[] = {host_file, serv_file};
    int streamLen[] = {sizeof(host_file), sizeof(serv_file)};
    const int file_number = 2;
    int flag = PrepareFileEnv(pathList, streamList, streamLen, file_number);
    if (flag != 0) {
        RecoveryFileEnv(pathList, file_number);
        return -1;
    }

    struct addrinfo *addr = NULL;
    int ret = getaddrinfo("example.com", "ftp", NULL, &addr);
    ICUNIT_ASSERT_EQUAL(ret, 0, ret);

    freeaddrinfo(addr);

    ret = getaddrinfo("local", "ftp", NULL, &addr);
    ICUNIT_ASSERT_EQUAL(ret, EAI_AGAIN, ret);

    ret = getaddrinfo("localhost", "fp", NULL, &addr);
    ICUNIT_ASSERT_EQUAL(ret, EAI_SERVICE, ret);

    const char *p = gai_strerror(EAI_AGAIN);
    ICUNIT_ASSERT_NOT_EQUAL(p, NULL, -1);

    RecoveryFileEnv(pathList, file_number);
    return ICUNIT_SUCCESS;
}
/*
以下是对这段代码的批注：

**一、整体功能**
1. 这段代码主要是对`getaddrinfo`函数以及相关的网络地址信息查询功能进行测试。代码首先创建了一些测试文件的内容（`host_file`和`serv_file`），并将其准备到特定的文件环境（`/etc/hosts`和`/etc/services`）中，然后进行了一系列`getaddrinfo`调用并检查返回值，最后清理测试文件环境。

**二、代码结构与细节**

1. **文件内容准备部分**
   - 在`AddrInfoTest`函数中，定义了两个字符数组`host_file`和`serv_file`，分别用于模拟`/etc/hosts`和`/etc/services`文件中的部分内容。
   - 使用`PrepareFileEnv`函数（假设这是一个自定义函数）来将模拟的文件内容写入到实际的文件环境中。如果这个函数返回非零值，表示准备文件环境失败，此时会调用`RecoveryFileEnv`（也是自定义函数）来恢复文件环境并返回 -1。
   - 这里硬编码文件内容和路径可能在某些情况下不够灵活，如果需要在不同环境下测试，可能需要更动态的方式来指定文件内容和路径。

2. **`getaddrinfo`测试部分**
   - 第一次调用`getaddrinfo`：
     - 调用`getaddrinfo("example.com", "ftp", NULL, &addr);`是一个正常的查询操作，查询域名`example.com`对应的`ftp`服务的地址信息。使用`ICUNIT_ASSERT_EQUAL`（假设是自定义的断言宏）来验证返回值是否为0，表示查询成功。如果成功，应该释放`addrinfo`结构的内存，这里使用`freeaddrinfo(addr)`正确地释放了内存。
   - 第二次调用`getaddrinfo`：
     - 调用`getaddrinfo("local", "ftp", NULL, &addr);`，这里`"local"`可能是一个无效的主机名（根据实际情况），预期返回`EAI_AGAIN`，并使用断言宏进行验证。
   - 第三次调用`getaddrinfo`：
     - 调用`getaddrinfo("localhost", "fp", NULL, &addr);`，这里服务名`"fp"`可能是错误的（应该是`"ftp"`），预期返回`EAI_SERVICE`，同样使用断言宏进行验证。
   - 调用`gai_strerror(EAI_AGAIN)`获取错误信息字符串，并使用`ICUNIT_ASSERT_NOT_EQUAL`断言该字符串不为`NULL`。这是一个合理的检查，确保错误信息能够正确获取。

3. **文件环境恢复部分**
   - 最后，无论测试过程中是否发生错误，都会调用`RecoveryFileEnv`函数来清理测试文件环境，这是一种良好的测试实践，确保测试不会对外部环境造成持久的影响。

**三、可能的改进点**
1. **错误处理和日志记录**
   - 除了使用断言来验证结果外，可以添加更详细的错误处理和日志记录功能。例如，如果`PrepareFileEnv`或`RecoveryFileEnv`失败，可以记录更详细的错误信息，以便在测试失败时更容易定位问题。
2. **可移植性**
   - 硬编码的文件路径（`/etc/hosts`和`/etc/services`）可能在不同的操作系统或环境下不适用。可以考虑使这些路径可配置或者使用操作系统提供的标准方法来获取这些文件的位置。
3. **测试用例的完整性**
   - 可以增加更多的测试用例，例如测试不同的`hints`参数对`getaddrinfo`的影响，或者测试更多的有效和无效的主机名和服务名组合。

void NetNetDbTest002(void)
{
    TEST_ADD_CASE(__FUNCTION__, AddrInfoTest, TEST_POSIX, TEST_TCP, TEST_LEVEL0, TEST_FUNCTION);
}
