/*
 * Copyright (C) 2020 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:
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"

#import "PlatformUtilities.h"
#import "Test.h"
#import <WebCore/SQLiteFileSystem.h>
#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKUserContentControllerPrivate.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WebKit.h>
#import <WebKit/_WKProcessPoolConfiguration.h>
#import <WebKit/_WKUserStyleSheet.h>
#import <wtf/RetainPtr.h>

@interface IDBCheckpointWALMessageHandler : NSObject <WKScriptMessageHandler>
@property (nonatomic, assign) bool receivedScriptMessage;
@property (nonatomic, retain) WKScriptMessage *lastScriptMessage;
@end

@implementation IDBCheckpointWALMessageHandler

@synthesize receivedScriptMessage=_receivedScriptMessage;
@synthesize lastScriptMessage=_lastScriptMessage;

- (void)dealloc
{
    [_lastScriptMessage release];
    [super dealloc];
}

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    _receivedScriptMessage = YES;
    self.lastScriptMessage = message;
}

- (bool *)receivedScriptMessagePointer
{
    return &_receivedScriptMessage;
}

@end

long long fileSizeAtPath(NSString *path)
{
    NSDictionary *attrs = [[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES];
    return [attrs[NSFileSize] longLongValue];
}

TEST(IndexedDB, CheckpointsWALAutomatically)
{
    NSString *hash = WebCore::SQLiteFileSystem::computeHashForFileName("test-wal-checkpoint");
    NSString *basePath = [@"~/Library/WebKit/com.apple.WebKit.TestWebKitAPI/WebsiteData/IndexedDB/v1/file__0" stringByExpandingTildeInPath];
    basePath = [basePath stringByAppendingPathComponent:hash];

    if ([[NSFileManager defaultManager] fileExistsAtPath:basePath]) {
        BOOL success = [[NSFileManager defaultManager] removeItemAtPath:basePath error:nil];
        EXPECT_TRUE(success);
    }

    RetainPtr<IDBCheckpointWALMessageHandler> handler = adoptNS([[IDBCheckpointWALMessageHandler alloc] init]);
    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];

    [configuration.get().processPool _terminateNetworkProcess];

    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);

    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"IDBCheckpointWAL" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
    [webView loadRequest:request];

    TestWebKitAPI::Util::run([handler receivedScriptMessagePointer]);

    EXPECT_STREQ([[[handler lastScriptMessage] body] UTF8String], "Success");

    // We inserted a single 5 MB row, which is greater than the WAL auto-checkpoint
    // threshold of 4MB, so the WAL should be of minimal size now.
    NSString *walPath = [basePath stringByAppendingPathComponent:@"IndexedDB.sqlite3-wal"];
    EXPECT_LT(fileSizeAtPath(walPath), 128 * 1024);

    // Since the single 5 MB row was checkpointed to the main DB file, it should be at least that large.
    NSString *dbPath = [basePath stringByAppendingPathComponent:@"IndexedDB.sqlite3"];
    EXPECT_GT(fileSizeAtPath(dbPath), 5 * 1024 * 1024);
}
