aboutsummaryrefslogtreecommitdiffstats
path: root/configserver/src/test/java/com/yahoo/vespa/config/server/filedistribution/FileDirectoryTest.java
blob: 60d2f41e5fe88f0e788d13c1138b0c8bad237828 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

package com.yahoo.vespa.config.server.filedistribution;

import com.yahoo.config.FileReference;
import com.yahoo.io.IOUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

public class FileDirectoryTest {

    private FileDirectory fileDirectory;

    @Rule
    public TemporaryFolder temporaryFolder = new TemporaryFolder();

    @Before
    public void setup() {
        fileDirectory = new FileDirectory(temporaryFolder.getRoot());
    }

    @Test
    public void requireThatFileReferenceWithFilesWorks() throws IOException {
        FileReference foo = createFile("foo");
        FileReference bar = createFile("bar");

        assertTrue(fileDirectory.getFile(foo).get().exists());
        assertEquals("ea315b7acac56246", foo.value());
        assertTrue(fileDirectory.getFile(bar).get().exists());
        assertEquals("2b8e97f15c854e1d", bar.value());
    }

    @Test
    public void requireThatFileReferenceWithSubDirectoriesWorks() throws IOException {
        String subdirName = "subdir";
        File subDirectory = new File(temporaryFolder.getRoot(), subdirName);
        createFileInSubDir(subDirectory, "foo", "some content");
        FileReference fileReference = fileDirectory.addFile(subDirectory);
        File dir = fileDirectory.getFile(fileReference).get();
        assertTrue(dir.exists());
        assertTrue(new File(dir, "foo").exists());
        assertFalse(new File(dir, "doesnotexist").exists());
        assertEquals("bebc5a1aee74223d", fileReference.value());

        // Change contents of a file, file reference value should change
        createFileInSubDir(subDirectory, "foo", "new content");
        FileReference fileReference2 = fileDirectory.addFile(subDirectory);
        dir = fileDirectory.getFile(fileReference2).get();
        assertTrue(new File(dir, "foo").exists());
        assertNotEquals(fileReference + " should not be equal to " + fileReference2, fileReference, fileReference2);
        assertEquals("e5d4b3fe5ee3ede3", fileReference2.value());

        // Add a file, should be available and file reference should have another value
        createFileInSubDir(subDirectory, "bar", "some other content");
        FileReference fileReference3 = fileDirectory.addFile(subDirectory);
        dir = fileDirectory.getFile(fileReference3).get();
        assertTrue(new File(dir, "foo").exists());
        assertTrue(new File(dir, "bar").exists());
        assertEquals("894bced3fc9d199b", fileReference3.value());
    }

    @Test
    public void requireThatExistingDirWithInvalidContentIsDeleted() throws IOException {
        String subdirName = "subdir";
        File subDirectory = new File(temporaryFolder.getRoot(), subdirName);
        createFileInSubDir(subDirectory, "foo", "some content");
        FileReference fileReference = fileDirectory.addFile(subDirectory);
        File dir = fileDirectory.getFile(fileReference).get();
        assertTrue(dir.exists());
        File foo = new File(dir, "foo");
        assertTrue(foo.exists());
        FileTime fooCreatedTimestamp = Files.readAttributes(foo.toPath(), BasicFileAttributes.class).creationTime();
        assertFalse(new File(dir, "doesnotexist").exists());
        assertEquals("bebc5a1aee74223d", fileReference.value());

        // Remove a file, directory should be deleted before adding a new file
        try { Thread.sleep(1000);} catch (InterruptedException e) {/*ignore */} // Needed since we have timestamp resolution of 1 second
        Files.delete(Paths.get(fileDirectory.getPath(fileReference)).resolve("subdir").resolve("foo"));
        fileReference = fileDirectory.addFile(subDirectory);
        dir = fileDirectory.getFile(fileReference).get();
        File foo2 = new File(dir, "foo");
        assertTrue(dir.exists());
        assertTrue(foo2.exists());
        FileTime foo2CreatedTimestamp = Files.readAttributes(foo2.toPath(), BasicFileAttributes.class).creationTime();
        // Check that creation timestamp is newer than the old one to be sure that a new file was written
        assertTrue(foo2CreatedTimestamp.compareTo(fooCreatedTimestamp) > 0);
        assertFalse(new File(dir, "doesnotexist").exists());
        assertEquals("bebc5a1aee74223d", fileReference.value());
    }

    @Test
    public void requireThatNothingIsDoneIfFileReferenceExists() throws IOException {
        String subdirName = "subdir";
        File subDirectory = new File(temporaryFolder.getRoot(), subdirName);
        createFileInSubDir(subDirectory, "foo", "some content");
        FileReference fileReference = fileDirectory.addFile(subDirectory);
        File dir = fileDirectory.getFile(fileReference).get();
        assertTrue(dir.exists());
        File foo = new File(dir, "foo");
        assertTrue(foo.exists());
        FileTime fooCreatedTimestamp = Files.readAttributes(foo.toPath(), BasicFileAttributes.class).creationTime();
        assertFalse(new File(dir, "doesnotexist").exists());
        assertEquals("bebc5a1aee74223d", fileReference.value());

        try { Thread.sleep(1000);} catch (InterruptedException e) { /*ignore */ } // Needed since we have timestamp resolution of 1 second
        // Add a file that already exists, nothing should happen
        createFileInSubDir(subDirectory, "foo", "some content"); // same as before, nothing should happen
        FileReference fileReference3 = fileDirectory.addFile(subDirectory);
        dir = fileDirectory.getFile(fileReference3).get();
        assertTrue(new File(dir, "foo").exists());
        assertEquals("bebc5a1aee74223d", fileReference3.value()); // same hash

        File foo2 = new File(dir, "foo");
        assertTrue(dir.exists());
        assertTrue(foo2.exists());
        FileTime barCreatedTimestamp = Files.readAttributes(foo2.toPath(), BasicFileAttributes.class).creationTime();
        // Check that creation timestamp is newer than the old one to be sure that a new file was written
        assertEquals(barCreatedTimestamp, fooCreatedTimestamp);
    }

    // Content in created file is equal to the filename string
    private FileReference createFile(String filename) throws IOException {
        File file = temporaryFolder.newFile(filename);
        IOUtils.writeFile(file, filename, false);
        return fileDirectory.addFile(file);
    }

    private void createFileInSubDir(File subDirectory, String filename, String fileContent) throws IOException {
        if (!subDirectory.exists())
            subDirectory.mkdirs();
        File file = new File(subDirectory, filename);
        IOUtils.writeFile(file, fileContent, false);
    }

}