1 /*
<lambda>null2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.datastore
18 
19 import androidx.datastore.core.InterProcessCoordinator
20 import androidx.datastore.core.Storage
21 import androidx.datastore.core.okio.OkioStorage
22 import kotlin.reflect.KClass
23 import okio.FileSystem
24 import okio.IOException
25 import okio.Path
26 
27 open class OkioTestIO(private val fileSystem: FileSystem = FileSystem.SYSTEM) :
28     TestIO<OkioPath, IOException>(
29         getTmpDir = {
30             OkioPath(fileSystem = fileSystem, path = FileSystem.SYSTEM_TEMPORARY_DIRECTORY)
31         }
32     ) {
getStoragenull33     override fun getStorage(
34         serializerConfig: TestingSerializerConfig,
35         coordinatorProducer: () -> InterProcessCoordinator,
36         futureFile: () -> OkioPath
37     ): Storage<Byte> {
38         return OkioStorage(
39             fileSystem = fileSystem,
40             serializer = TestingOkioSerializer(serializerConfig),
41             coordinatorProducer = { _, _ -> coordinatorProducer() }
42         ) {
43             futureFile().path
44         }
45     }
46 
ioExceptionnull47     override fun ioException(message: String): IOException {
48         return IOException(message)
49     }
50 
ioExceptionClassnull51     override fun ioExceptionClass(): KClass<IOException> = IOException::class
52 }
53 
54 class OkioPath(private val fileSystem: FileSystem, val path: Path) : TestFile<OkioPath>() {
55     override val name: String
56         get() = path.name
57 
58     override fun path(): String {
59         return path.normalized().toString()
60     }
61 
62     override fun delete(): Boolean {
63         if (!fileSystem.exists(path)) {
64             // to be consistent with the TestFile API.
65             return false
66         }
67         fileSystem.delete(path)
68         return !fileSystem.exists(path)
69     }
70 
71     override fun exists(): Boolean {
72         return fileSystem.exists(path)
73     }
74 
75     override fun mkdirs(mustCreate: Boolean) {
76         if (exists()) {
77             check(fileSystem.metadataOrNull(path)?.isDirectory == true) {
78                 "$path already exists but it is not a directory"
79             }
80             check(!mustCreate) { "Directory $path already exists" }
81         }
82         fileSystem.createDirectories(path, mustCreate = mustCreate)
83     }
84 
85     override fun isRegularFile(): Boolean {
86         return fileSystem.metadataOrNull(path)?.isRegularFile == true
87     }
88 
89     override fun isDirectory(): Boolean {
90         return fileSystem.metadataOrNull(path)?.isDirectory == true
91     }
92 
93     override fun protectedResolve(relative: String): OkioPath {
94         return OkioPath(fileSystem, path / relative)
95     }
96 
97     override fun parentFile(): OkioPath? {
98         return path.parent?.let { OkioPath(fileSystem = fileSystem, path = it) }
99     }
100 
101     override fun protectedWrite(body: ByteArray) {
102         fileSystem.write(path) {
103             write(body)
104             flush()
105         }
106     }
107 
108     override fun protectedReadBytes(): ByteArray {
109         return fileSystem.read(path) { readByteArray() }
110     }
111 }
112