blob: 35de3920001c24634f6a499ea1ae4e2c6b020696 [file]
/*
* Copyright (c) 2025 Project CHIP 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
*
* http://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.
*/
// module headers
#import <Matter/Matter.h>
#import "MTRTestCase+ServerAppRunner.h"
#import "MTRTestCase.h"
#import "MTRTestDeclarations.h"
static const uint64_t kDeviceId = 0x12344321;
static MTRDeviceController * sDeviceController = nil;
static const uint16_t kTimeoutInSeconds = 10;
static NSString * shortLogContent = @"This is a short log\n";
static NSString * longLogContent = nil;
@interface MTRDiagnosticLogDownloadTests : MTRTestCase
@end
@implementation MTRDiagnosticLogDownloadTests
+ (void)setUp
{
[super setUp];
// TODO: Once we have a way to startCommissionedAppWithName with explicit
// per-suite scope, do that in the instance setUp method, with a "have we
// already done it?" guard.
// Ensure that our long log content is long enough that it can't fit in a
// 1280-byte packet, so has to be sent via BDX. In particular, ensure we
// have at least 2KB of log.
NSUInteger neededSize = 2048;
NSUInteger expectedCopies = (neededSize - 1) / shortLogContent.length + 1;
NSUInteger expectedSize = expectedCopies * shortLogContent.length;
NSMutableString * mutableLongLogContent = [NSMutableString stringWithCapacity:expectedSize];
while (mutableLongLogContent.length < neededSize) {
[mutableLongLogContent appendString:shortLogContent];
}
longLogContent = mutableLongLogContent;
NSString * endUserSupportLog = [self _createLogFile:shortLogContent];
NSString * networkDiagnosticsLog = [self _createLogFile:longLogContent];
NSString * crashLog = [self _createLogFile:longLogContent];
sDeviceController = [self startCommissionedAppWithName:@"all-clusters"
arguments:@[
@("--end_user_support_log"),
endUserSupportLog,
@("--network_diagnostics_log"),
networkDiagnosticsLog,
@("--crash_log"),
crashLog
]
nodeID:@(kDeviceId)];
XCTAssertNotNil(sDeviceController);
}
+ (NSString *)_createLogFile:(NSString *)logContent
{
NSString * uniqueName = [[NSUUID UUID] UUIDString];
NSString * logFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:uniqueName];
BOOL created = [[NSFileManager defaultManager] createFileAtPath:logFilePath
contents:[logContent dataUsingEncoding:NSUTF8StringEncoding]
attributes:nil];
XCTAssertTrue(created);
return logFilePath;
}
- (void)setUp
{
[super setUp];
[self setContinueAfterFailure:NO];
}
- (void)_testDownloadLogWithContent:(NSString *)expectedLogContent type:(MTRDiagnosticLogType)type testName:(NSString *)testName
{
XCTestExpectation * expectation =
[self expectationWithDescription:@"Downloaded the end user support log"];
MTRDevice * device = [MTRDevice deviceWithNodeID:@(kDeviceId) controller:sDeviceController];
XCTAssertNotNil(device, "%@", testName);
dispatch_queue_t queue = dispatch_get_main_queue();
[device downloadLogOfType:type
timeout:kTimeoutInSeconds
queue:queue
completion:^(NSURL * _Nullable url, NSError * _Nullable error) {
NSLog(@"downloadLogOfType: url: %@, error: %@", url, error);
XCTAssertNil(error, "%@", testName);
XCTAssertNotNil(url, "%@", testName);
NSError * readError;
NSString * fileContent = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&readError];
XCTAssertNil(readError, "%@", testName);
XCTAssertEqualObjects(fileContent, expectedLogContent, "%@", testName);
[expectation fulfill];
}];
[self waitForExpectations:@[ expectation ] timeout:kTimeoutInSeconds];
// TODO: BDXDiagnosticLogsProvider.cpp has a 50ms lag between receiving the
// BlockAckEOF message and actually treating the transfer as done, because
// it does the 50ms poll thing. Wait 100ms to make sure it has time to
// process the message.
usleep(100 * 1000);
}
- (void)test001_UserSupportLog
{
[self _testDownloadLogWithContent:shortLogContent type:MTRDiagnosticLogTypeEndUserSupport testName:@("test001_UserSupportLog")];
}
- (void)test002_NetworkDiagnosticsLog
{
[self _testDownloadLogWithContent:longLogContent type:MTRDiagnosticLogTypeNetworkDiagnostics testName:@("test002_NetworkDiagnosticsLog")];
}
- (void)test003_CrashLog
{
[self _testDownloadLogWithContent:longLogContent type:MTRDiagnosticLogTypeCrash testName:@("test003_CrashLog")];
}
- (void)test004_CanceledDownload
{
XCTestExpectation * expectation =
[self expectationWithDescription:@"Canceled download completed"];
MTRDevice * device = [MTRDevice deviceWithNodeID:@(kDeviceId) controller:sDeviceController];
XCTAssertNotNil(device);
dispatch_queue_t queue = dispatch_get_main_queue();
[device downloadLogOfType:MTRDiagnosticLogTypeEndUserSupport
timeout:kTimeoutInSeconds
queue:queue
completion:^(NSURL * _Nullable url, NSError * _Nullable error) {
XCTAssertNil(url);
XCTAssertNotNil(error);
XCTAssertEqual(error.domain, MTRErrorDomain);
XCTAssertEqual(error.code, MTRErrorCodeCancelled);
[expectation fulfill];
}];
[self _testDownloadLogWithContent:shortLogContent type:MTRDiagnosticLogTypeEndUserSupport testName:@("test004_CanceledDownload")];
[self waitForExpectations:@[ expectation ] timeout:kTimeoutInSeconds];
}
@end