1 /*
2  * Copyright (C) 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 com.android.server.net
18 
19 import android.util.SystemConfigFileCommitEventLogger
20 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
21 import com.android.testutils.DevSdkIgnoreRunner
22 import com.android.testutils.SC_V2
23 import com.android.testutils.assertThrows
24 import org.junit.After
25 import org.junit.Before
26 import org.junit.Test
27 import org.junit.runner.RunWith
28 import java.io.File
29 import java.io.IOException
30 import java.nio.file.Files
31 import java.nio.file.Path
32 import java.nio.file.attribute.PosixFilePermission
33 import java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE
34 import java.nio.file.attribute.PosixFilePermission.OWNER_READ
35 import java.nio.file.attribute.PosixFilePermission.OWNER_WRITE
36 import java.util.Random
37 import kotlin.test.assertEquals
38 
39 @RunWith(DevSdkIgnoreRunner::class)
40 @IgnoreUpTo(SC_V2)
41 class PersistentIntTest {
42     val tempFilesCreated = mutableSetOf<Path>()
43     lateinit var tempDir: Path
44 
45     @Before
setUpnull46     fun setUp() {
47         tempDir = Files.createTempDirectory("tmp.PersistentIntTest.")
48     }
49 
50     @After
tearDownnull51     fun tearDown() {
52         var permissions = setOf(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE)
53         Files.setPosixFilePermissions(tempDir, permissions)
54 
55         for (file in tempFilesCreated) {
56             Files.deleteIfExists(file)
57         }
58         Files.delete(tempDir)
59     }
60 
61     @Test
testNormalReadWritenull62     fun testNormalReadWrite() {
63         // New, initialized to 0.
64         val pi = createPersistentInt()
65         assertEquals(0, pi.get())
66         pi.set(12345)
67         assertEquals(12345, pi.get())
68 
69         // Existing.
70         val pi2 = createPersistentInt(pathOf(pi))
71         assertEquals(12345, pi2.get())
72     }
73 
74     @Test
testReadOrWriteFailsInCreatenull75     fun testReadOrWriteFailsInCreate() {
76         setWritable(tempDir, false)
77         assertThrows(IOException::class.java) {
78             createPersistentInt()
79         }
80     }
81 
82     @Test
testReadOrWriteFailsAfterCreatenull83     fun testReadOrWriteFailsAfterCreate() {
84         val pi = createPersistentInt()
85         pi.set(42)
86         assertEquals(42, pi.get())
87 
88         val path = pathOf(pi)
89         setReadable(path, false)
90         assertThrows(IOException::class.java) { pi.get() }
91         pi.set(77)
92 
93         setReadable(path, true)
94         setWritable(path, false)
95         setWritable(tempDir, false) // Writing creates a new file+renames, make this fail.
96         assertThrows(IOException::class.java) { pi.set(99) }
97         assertEquals(77, pi.get())
98     }
99 
addOrRemovePermissionnull100     fun addOrRemovePermission(p: Path, permission: PosixFilePermission, add: Boolean) {
101         val permissions = Files.getPosixFilePermissions(p)
102         if (add) {
103             permissions.add(permission)
104         } else {
105             permissions.remove(permission)
106         }
107         Files.setPosixFilePermissions(p, permissions)
108     }
109 
setReadablenull110     fun setReadable(p: Path, readable: Boolean) {
111         addOrRemovePermission(p, OWNER_READ, readable)
112     }
113 
setWritablenull114     fun setWritable(p: Path, writable: Boolean) {
115         addOrRemovePermission(p, OWNER_WRITE, writable)
116     }
117 
pathOfnull118     fun pathOf(pi: PersistentInt): Path {
119         return File(pi.path).toPath()
120     }
121 
createPersistentIntnull122     fun createPersistentInt(path: Path = randomTempPath()): PersistentInt {
123         tempFilesCreated.add(path)
124         return PersistentInt(path.toString(),
125                 SystemConfigFileCommitEventLogger("PersistentIntTest"))
126     }
127 
randomTempPathnull128     fun randomTempPath(): Path {
129         return tempDir.resolve(Integer.toHexString(Random().nextInt())).also {
130             tempFilesCreated.add(it)
131         }
132     }
133 }
134