aboutsummaryrefslogtreecommitdiffstats
path: root/config-model/src/test/java/com/yahoo/vespa/model/routing/test/RoutingTestCase.java
blob: e57b8ee4eb10f2d83bce94818abeb6a9fb5da7a3 (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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.routing.test;

import com.yahoo.config.ConfigInstance;
import com.yahoo.documentapi.messagebus.protocol.DocumentrouteselectorpolicyConfig;
import com.yahoo.io.IOUtils;
import com.yahoo.messagebus.MessagebusConfig;
import com.yahoo.documentapi.messagebus.protocol.DocumentProtocolPoliciesConfig;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithFilePkg;
import org.junit.jupiter.api.Test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static helpers.CompareConfigTestHelper.assertSerializedConfigEquals;
import static org.junit.jupiter.api.Assertions.*;

/**
 * @author Simon Thoresen Hult
 */
public class RoutingTestCase {

    private static final boolean WRITE_FILES = false;

    @Test
    void testRoutingContent() throws IOException {
        assertApplication(new File("src/test/cfg/routing/contentsimpleconfig"));
        assertApplication(new File("src/test/cfg/routing/content_two_clusters"));
    }

    @Test
    void testRouting() throws IOException {
        assertApplication(new File("src/test/cfg/routing/unexpectedrecipient"));
        assertApplication(new File("src/test/cfg/routing/servicenotfound"));
        assertApplication(new File("src/test/cfg/routing/routenotfoundinroute"));
        assertApplication(new File("src/test/cfg/routing/routenotfound"));
        assertApplication(new File("src/test/cfg/routing/routeconfig"));
        assertApplication(new File("src/test/cfg/routing/replaceroute"));
        assertApplication(new File("src/test/cfg/routing/replacehop"));
        assertApplication(new File("src/test/cfg/routing/mismatchedrecipient"));
        assertApplication(new File("src/test/cfg/routing/hopnotfound"));
        assertApplication(new File("src/test/cfg/routing/hoperrorinroute"));
        assertApplication(new File("src/test/cfg/routing/hoperrorinrecipient"));
        assertApplication(new File("src/test/cfg/routing/hoperror"));
        assertApplication(new File("src/test/cfg/routing/hopconfig"));
        assertApplication(new File("src/test/cfg/routing/emptyroute"));
        assertApplication(new File("src/test/cfg/routing/emptyhop"));
        assertApplication(new File("src/test/cfg/routing/duplicateroute"));
        assertApplication(new File("src/test/cfg/routing/duplicatehop"));
        assertApplication(new File("src/test/cfg/routing/defaultconfig"));
    }

    /**
     * Tests whether or not the given application produces the expected output. When creating new tests, create an
     * application directory containing the necessary setup files, and call this method with a TRUE create flag.
     *
     * @param application The application directory.
     */
    private static void assertApplication(File application) throws IOException {
        assertTrue(application.isDirectory());
        String applicationName = application.getName();
        Map<String, File> files = new HashMap<>();
        for (File file : application.listFiles(new ContentFilter())) {
            files.put(file.getName(), file);
        }
        String path = null;
        try {
            path = application.getCanonicalPath();
        } catch (IOException e) {
            fail("Could not resolve path for application '" + applicationName + "'.");
        }
        VespaModelCreatorWithFilePkg creator = new VespaModelCreatorWithFilePkg(path);

        VespaModel model = creator.create();
        List<String> errors = model.getRouting().getErrors();
        if (errors.isEmpty()) {
            if (files.containsKey("errors.txt")) {
                if (WRITE_FILES) {
                    files.remove("errors.txt").delete();
                } else {
                    fail("Route verification did not fail.");
                }
            }
            MessagebusConfig.Builder mBusB = new MessagebusConfig.Builder();
            model.getConfig(mBusB, "");
            MessagebusConfig mBus = new MessagebusConfig(mBusB);
            assertConfigFileContains(application, files, "messagebus.cfg", mBus);

            DocumentrouteselectorpolicyConfig.Builder drB = new DocumentrouteselectorpolicyConfig.Builder();
            model.getConfig(drB, "");
            DocumentrouteselectorpolicyConfig dr = new DocumentrouteselectorpolicyConfig(drB);
            assertConfigFileContains(application, files, "documentrouteselectorpolicy.cfg", dr);

            DocumentProtocolPoliciesConfig.Builder policies = new DocumentProtocolPoliciesConfig.Builder();
            model.getConfig(policies, "");
            assertConfigFileContains(application, files, "document-protocol-policies.cfg", policies.build());
        } else {
            StringBuilder msg = new StringBuilder();
            for (String error : errors) {
                msg.append(error).append("\n");
            }
            assertFileContains(application, files, "errors.txt", msg.toString());
        }
    }

    /**
     * Tests whether or not a given file exists and contains some expected content.
     *
     * @param application     The application directory.
     * @param files           The filtered list of files within the application.
     * @param fileName        The name of the file whose content to check.
     * @param expectedContent The content required in the file being checked.
     */
    private static void assertFileContains(File application, Map<String, File> files,
                                           String fileName, String expectedContent) {
        if (WRITE_FILES) {
            files.put(fileName, writeFile(application, fileName, expectedContent.trim() + "\n"));
        }
        if (!files.containsKey(fileName)) {
            fail("Expected file '" + fileName + "' not found.\nExpected content: " + expectedContent);
            return;
        }
        StringBuilder content = new StringBuilder();

        try {
            BufferedReader reader = new BufferedReader(new FileReader(files.get(fileName)));
            String line = reader.readLine();
            while (line != null) {
                content.append(line).append("\n");
                line = reader.readLine();
            }
            reader.close();
        } catch (FileNotFoundException e) {
            fail("File '" + fileName + "' not found.");
        } catch (IOException e) {
            fail("Failed to read content of file '" + fileName + ".");
        }

        assertEquals(content.toString().trim(), expectedContent.replace("\r", "").trim());
    }
    /**
     * Tests whether or not a given file exists and contains some expected content.
     *
     * @param application     The application directory.
     * @param files           The filtered list of files within the application.
     * @param fileName        The name of the file whose content to check.
     * @param config          The config required in the file being checked.
     * @throws IOException 
     */
    private static void assertConfigFileContains(File application, Map<String, File> files,
                                                 String fileName, ConfigInstance config) throws IOException {
        String configString = config.toString();
        if (WRITE_FILES) {
            files.put(fileName, writeFile(application, fileName, configString.trim() + "\n"));
        }
        if (!files.containsKey(fileName)) {
            fail("Expected file '" + fileName + "' not found.");
            return;
        }
        assertSerializedConfigEquals(IOUtils.readFile(files.get(fileName)), configString, false);
    }

    /**
     * Writes content to a specific file.
     *
     * @param application The application directory.
     * @param name        The name of the file to write.
     * @param content     The content to write.
     * @return The file written.
     */
    private static File writeFile(File application, String name, String content) {
        File ret = null;
        try {
            name = application.getCanonicalPath() + "/" + name;
            System.out.println("\tWriting file '" + name + "'.");

            PrintWriter writer = new PrintWriter(new FileWriter(name));
            writer.print(content);
            writer.close();

            ret = new File(name);
        } catch (IOException e) {
            fail(e.getMessage());
        }
        return ret;
    }

    /**
     * Helper class to filter what files within an application directory gets added to the files index.
     */
    private static class ContentFilter implements FilenameFilter {
        public boolean accept(File file, String name) {
            return !name.equals(".git") && !name.equals(".svn");
        }
    }

}