Files
waf-platform/EdgeHttpDNS/sdk/ios/AlicloudHttpDNSTests/HighLevelTest/PresetCacheAndRetrieveTest.m
2026-02-20 17:56:24 +08:00

302 lines
13 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// PresetCacheAndRetrieveTest.m
// AlicloudHttpDNSTests
//
// Created by xuyecan on 2024/5/26.
// Copyright © 2024 alibaba-inc.com. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <OCMock/OCMock.h>
#import "TestBase.h"
#import "HttpdnsHostObject.h"
#import "HttpdnsService.h"
#import "HttpdnsService_Internal.h"
/**
* 由于使用OCMock在连续的测试用例中重复Mock对象(即使每次都已经stopMocking)会有内存错乱的问题,
* 目前还解决不了所以这个类中的测试case需要手动单独执行
*/
@interface PresetCacheAndRetrieveTest : TestBase
@end
@implementation PresetCacheAndRetrieveTest
+ (void)setUp {
[super setUp];
HttpDnsService *httpdns = [[HttpDnsService alloc] initWithAccountID:100000];
[httpdns setLogEnabled:YES];
}
+ (void)tearDown {
[super tearDown];
}
- (void)setUp {
[super setUp];
self.httpdns = [HttpDnsService sharedInstance];
self.currentTimeStamp = [[NSDate date] timeIntervalSince1970];
}
- (void)tearDown {
[super tearDown];
}
// 网络情况为ipv4下的缓存测试
- (void)testSimplyRetrieveCachedResultUnderIpv4Only {
[self presetNetworkEnvAsIpv4];
[self.httpdns cleanAllHostCache];
HttpdnsHostObject *hostObject = [self constructSimpleIpv4AndIpv6HostObject];
[self.httpdns.requestManager mergeLookupResultToManager:hostObject host:ipv4AndIpv6Host cacheKey:ipv4AndIpv6Host underQueryIpType:HttpdnsQueryIPTypeBoth];
// 请求类型为ipv4拿到ipv4结果
HttpdnsResult *result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeIpv4];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
// 请求类型为ipv6拿到ipv6结果
result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeIpv6];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ipv6s count] == 2);
XCTAssertTrue([result.ipv6s[0] isEqualToString:ipv61]);
// both
result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeBoth];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
XCTAssertTrue([result.ipv6s count] == 2);
XCTAssertTrue([result.ipv6s[0] isEqualToString:ipv61]);
// 请求类型为auto只拿到ipv4结果
result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeAuto];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
XCTAssertTrue([result.ipv6s count] == 0);
}
// 网络请求为ipv6下的缓存测试
- (void)testSimplyRetrieveCachedResultUnderIpv6Only {
[self presetNetworkEnvAsIpv6];
[self.httpdns cleanAllHostCache];
HttpdnsHostObject *hostObject = [self constructSimpleIpv4AndIpv6HostObject];
[self.httpdns.requestManager mergeLookupResultToManager:hostObject host:ipv4AndIpv6Host cacheKey:ipv4AndIpv6Host underQueryIpType:HttpdnsQueryIPTypeBoth];
// 请求类型为ipv4拿到ipv4结果
HttpdnsResult *result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeIpv4];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
// 请求类型为ipv6拿到ipv6结果
result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeIpv6];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ipv6s count] == 2);
XCTAssertTrue([result.ipv6s[0] isEqualToString:ipv61]);
// both
result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeBoth];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
XCTAssertTrue([result.ipv6s count] == 2);
XCTAssertTrue([result.ipv6s[0] isEqualToString:ipv61]);
// 请求类型为auto注意我们认为ipv6only只存在理论上比如实验室环境
// 因此ipv4的地址是一定会去解析的auto的作用在于如果发现网络还支持ipv6那就多获取ipv6的结果
// 因此这里得到的也是ipv4+ipv6
result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeAuto];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
XCTAssertTrue([result.ipv6s count] == 2);
XCTAssertTrue([result.ipv6s[0] isEqualToString:ipv61]);
}
// 网络情况为ipv4和ipv6下的缓存测试
- (void)testSimplyRetrieveCachedResultUnderDualStack {
[self presetNetworkEnvAsIpv4AndIpv6];
[self.httpdns cleanAllHostCache];
// 存入ipv4和ipv6的地址
HttpdnsHostObject *hostObject = [self constructSimpleIpv4AndIpv6HostObject];
[self.httpdns.requestManager mergeLookupResultToManager:hostObject host:ipv4AndIpv6Host cacheKey:ipv4AndIpv6Host underQueryIpType:HttpdnsQueryIPTypeBoth];
// 只请求ipv4
HttpdnsResult *result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeIpv4];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
// 只请求ipv6
result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeIpv6];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ipv6s count] == 2);
XCTAssertTrue([result.ipv6s[0] isEqualToString:ipv61]);
// 请求ipv4和ipv6
result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeBoth];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
XCTAssertTrue([result.ipv6s count] == 2);
XCTAssertTrue([result.ipv6s[0] isEqualToString:ipv61]);
// 自动判断类型
result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeAuto];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4AndIpv6Host]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
XCTAssertTrue([result.ipv6s count] == 2);
XCTAssertTrue([result.ipv6s[0] isEqualToString:ipv61]);
}
// ttl、lastLookupTimeipv4和ipv6是分开处理的
- (void)testTTLAndLastLookUpTime {
[self presetNetworkEnvAsIpv4AndIpv6];
[self.httpdns cleanAllHostCache];
// 存入ipv4和ipv6的地址
HttpdnsHostObject *hostObject1 = [self constructSimpleIpv4AndIpv6HostObject];
hostObject1.v4ttl = 200;
hostObject1.v6ttl = 300;
int64_t currentTimestamp = [[NSDate new] timeIntervalSince1970];
hostObject1.lastIPv4LookupTime = currentTimestamp - 1;
hostObject1.lastIPv6LookupTime = currentTimestamp - 2;
// 第一次设置缓存
[self.httpdns.requestManager mergeLookupResultToManager:hostObject1 host:ipv4AndIpv6Host cacheKey:ipv4AndIpv6Host underQueryIpType:HttpdnsQueryIPTypeBoth];
// auto在当前环境下即请求ipv4和ipv6
HttpdnsResult *result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeAuto];
XCTAssertEqual(result.ttl, hostObject1.v4ttl);
XCTAssertEqual(result.lastUpdatedTimeInterval, hostObject1.lastIPv4LookupTime);
XCTAssertEqual(result.v6ttl, hostObject1.v6ttl);
XCTAssertEqual(result.v6LastUpdatedTimeInterval, hostObject1.lastIPv6LookupTime);
HttpdnsHostObject *hostObject2 = [self constructSimpleIpv4HostObject];
hostObject2.hostName = ipv4AndIpv6Host;
hostObject2.v4ttl = 600;
hostObject2.lastIPv4LookupTime = currentTimestamp - 10;
// 单独在缓存更新ipv4地址的相关信息
[self.httpdns.requestManager mergeLookupResultToManager:hostObject2 host:ipv4AndIpv6Host cacheKey:ipv4AndIpv6Host underQueryIpType:HttpdnsQueryIPTypeIpv4];
// v4的信息发生变化v6的信息保持不变
result = [self.httpdns resolveHostSyncNonBlocking:ipv4AndIpv6Host byIpType:HttpdnsQueryIPTypeAuto];
XCTAssertEqual(result.ttl, hostObject2.v4ttl);
XCTAssertEqual(result.lastUpdatedTimeInterval, hostObject2.lastIPv4LookupTime);
XCTAssertEqual(result.v6ttl, hostObject1.v6ttl);
XCTAssertEqual(result.v6LastUpdatedTimeInterval, hostObject1.lastIPv6LookupTime);
}
// 只缓存ipv4单栈的地址按请求双栈类型存入此时会标记该域名没有ipv6地址
// 按预期会判断该域名没有ipv6地址因此不会返回ipv6地址也不会发请求
- (void)testMergeNoIpv6ResultAndGetBoth {
[self presetNetworkEnvAsIpv4AndIpv6];
HttpdnsHostObject *hostObject = [self constructSimpleIpv4HostObject];
// 双栈下解析结果仅有ipv4合并时会标记该host无ipv6
[self.httpdns.requestManager mergeLookupResultToManager:hostObject host:ipv4OnlyHost cacheKey:ipv4OnlyHost underQueryIpType:HttpdnsQueryIPTypeBoth];
[self shouldNotHaveCallNetworkRequestWhenResolving:^{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
HttpdnsResult *result = [self.httpdns resolveHostSync:ipv4OnlyHost byIpType:HttpdnsQueryIPTypeBoth];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4OnlyHost]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
result = [self.httpdns resolveHostSync:ipv4OnlyHost byIpType:HttpdnsQueryIPTypeAuto];
XCTAssertNotNil(result);
XCTAssertTrue([result.host isEqualToString:ipv4OnlyHost]);
XCTAssertTrue([result.ips count] == 2);
XCTAssertTrue([result.ips[0] isEqualToString:ipv41]);
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}];
}
// 缓存ipv4单栈的地址但是请求ipv4类型存入此时不会打标记没有ipv6
// 于是读取时会尝试发请求获取ipv6地址
- (void)testMergeOnlyIpv4ResultAndGetBoth {
[self presetNetworkEnvAsIpv4AndIpv6];
HttpdnsHostObject *hostObject = [self constructSimpleIpv4HostObject];
[self.httpdns.requestManager mergeLookupResultToManager:hostObject host:ipv4OnlyHost cacheKey:ipv4OnlyHost underQueryIpType:HttpdnsQueryIPTypeIpv4];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
// 使用同步接口,要切换到异步线程,否则内部会自己切
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self shouldHaveCalledRequestWhenResolving:^{
HttpdnsResult *result = [self.httpdns resolveHostSync:ipv4OnlyHost byIpType:HttpdnsQueryIPTypeBoth];
XCTAssertNil(result);
dispatch_semaphore_signal(sema);
}];
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
// 缓存ipv6单栈的地址但是请求ipv6类型存入此时不会打标记没有ipv4
// 于是读取时会尝试发请求获取ipv4地址
- (void)testMergeOnlyIpv6ResultAndGetBoth {
[self presetNetworkEnvAsIpv4AndIpv6];
HttpdnsHostObject *hostObject = [self constructSimpleIpv6HostObject];
[self.httpdns.requestManager mergeLookupResultToManager:hostObject host:ipv6OnlyHost cacheKey:ipv6OnlyHost underQueryIpType:HttpdnsQueryIPTypeIpv6];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
// 使用同步接口,要切换到异步线程,否则内部会自己切
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self shouldHaveCalledRequestWhenResolving:^{
HttpdnsResult *result = [self.httpdns resolveHostSync:ipv6OnlyHost byIpType:HttpdnsQueryIPTypeBoth];
XCTAssertNil(result);
dispatch_semaphore_signal(sema);
}];
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
@end