aboutsummaryrefslogtreecommitdiffstats
path: root/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/role/PathGroupTest.java
blob: 4a8e9785c881acb4f8e1b7219656636219fde8bb (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
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.api.role;

import org.junit.jupiter.api.Test;

import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

/**
 * @author jonmv
 * @author mpolden
 */
public class PathGroupTest {

    @Test
    void uniqueMatches() {
        // Ensure that each path group contains at most one match for any given path, to avoid undefined context extraction.
        Set<String> checkedAgainstSelf = new HashSet<>();
        for (PathGroup group1 : PathGroup.values())
            for (PathGroup group2 : PathGroup.values())
                for (String path1 : group1.pathSpecs)
                    for (String path2 : group2.pathSpecs) {
                        if (path1.equals(path2)) {
                            if (checkedAgainstSelf.add(path1)) continue;
                            fail("Path '" + path1 + "' appears in both '" + group1 + "' and '" + group2 + "'.");
                        }

                        String[] parts1 = path1.split("/");
                        String[] parts2 = path2.split("/");

                        int end = Math.min(parts1.length, parts2.length);
                        // If one path has more parts than the other ...
                        // and the other doesn't end with a wildcard matcher ...
                        // and the longest one isn't just one wildcard longer ...
                        // then one is strictly longer than the other, and it's not a match.
                        if (end < parts1.length && (end == 0 || !parts2[end - 1].equals("{*}")) && !parts1[end].equals("{*}")) continue;
                        if (end < parts2.length && (end == 0 || !parts1[end - 1].equals("{*}")) && !parts2[end].equals("{*}")) continue;

                        int i;
                        for (i = 0; i < end; i++)
                            if (   !  parts1[i].equals(parts2[i])
                                    && !(parts1[i].startsWith("{") && parts1[i].endsWith("}"))
                                    && !(parts2[i].startsWith("{") && parts2[i].endsWith("}"))) break;

                        if (i == end) fail("Paths '" + path1 + "' and '" + path2 + "' overlap.");
                    }

        assertEquals(PathGroup.all().stream().mapToInt(group -> group.pathSpecs.size()).sum(),
                checkedAgainstSelf.size());
    }

    @Test
    void contextMatches() {
        for (PathGroup group : PathGroup.values())
            for (String spec : group.pathSpecs) {
                for (PathGroup.Matcher matcher : PathGroup.Matcher.values()) {
                    if (group.matchers.contains(matcher)) {
                        if (!spec.contains(matcher.pattern))
                            fail("Spec '" + spec + "' in '" + group.name() + "' should contain matcher '" + matcher.pattern + "'.");
                        if (spec.replaceFirst(Pattern.quote(matcher.pattern), "").contains(matcher.pattern))
                            fail("Spec '" + spec + "' in '" + group.name() + "' contains more than one instance of '" + matcher.pattern + "'.");
                    }
                    else if (spec.contains(matcher.pattern))
                        fail("Spec '" + spec + "' in '" + group.name() + "' should not contain matcher '" + matcher.pattern + "'.");
                }
            }
    }

}