// Copyright (c) 2021 Spotify AB. // // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you 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. import Foundation @testable import XCRemoteCache enum FileAccessorFakeError: Error { case itemDoesntExist } class FileAccessorFake: FileAccessor { enum Mode { case normal case strict } private var storage: [String: (content: Data?, mdate: Date)] = [:] private let mode: Mode init(mode: Mode) { self.mode = mode } func contents(atPath path: String) throws -> Data? { return storage[path]?.content } func fileExists(atPath path: String) -> Bool { return storage.keys.contains(path) } func write(toPath path: String, contents: Data?) throws { storage[path] = (contents, Date()) } func removeItem(atPath path: String) throws { if mode == .strict && storage[path] == nil { throw FileAccessorFakeError.itemDoesntExist } storage[path] = nil } func fileMDate(atPath path: String) -> Date? { return storage[path]?.mdate } } extension FileAccessorFake: DirScanner { func itemType(atPath path: String) throws -> ItemType { if storage[path] != nil { return .file } if try !recursiveItems(at: URL(fileURLWithPath: path)).isEmpty { return .dir } return .nonExisting } func items(at dir: URL) throws -> [URL] { storage.keys.map(URL.init(fileURLWithPath:)).filter { $0.deletingLastPathComponent() == dir } } func recursiveItems(at dir: URL) throws -> [URL] { let paths = storage.keys.filter { $0.hasPrefix(dir.path) } return paths.map(URL.init(fileURLWithPath:)) } }