aboutsummaryrefslogtreecommitdiffstats
path: root/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/IndexedSchemaClusterChangeValidatorTest.java
blob: fb4e9f1a00b2474dd4de6432433eae6632b8b9b8 (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
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.application.validation.change;

import com.yahoo.config.application.api.ValidationId;
import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.config.model.api.ServiceInfo;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.content.utils.ApplicationPackageBuilder;
import com.yahoo.vespa.model.content.utils.ContentClusterBuilder;
import com.yahoo.vespa.model.content.utils.SchemaBuilder;
import org.junit.jupiter.api.Test;

import java.util.List;

import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.assertEqualActions;
import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.newRefeedAction;
import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.newRestartAction;
import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.normalizeServicesInActions;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class IndexedSchemaClusterChangeValidatorTest {

    static class Fixture {
        VespaModel currentModel;
        VespaModel nextModel;
        IndexedSearchClusterChangeValidator validator;

        public Fixture(VespaModel currentModel, VespaModel nextModel) {
            this.currentModel = currentModel;
            this.nextModel = nextModel;
            validator = new IndexedSearchClusterChangeValidator();
        }

        public static Fixture newOneDocFixture(String currentSd, String nextSd) {
            return new Fixture(newOneDocModel(currentSd), newOneDocModel(nextSd));
        }

        public static VespaModel newOneDocModel(String sdContent) {
            return new ApplicationPackageBuilder().
                    addCluster(new ContentClusterBuilder().name("foo").docTypes("d1"))
                                                  .addSchemas(new SchemaBuilder().name("d1").content(sdContent).build())
                                                  .buildCreator().create();
        }

        public static Fixture newTwoDocFixture(String currentSd, String nextSd) {
            return new Fixture(newTwoDocModel(currentSd, currentSd), newTwoDocModel(nextSd, nextSd));
        }

        public static VespaModel newTwoDocModel(String d1Content, String d2Content) {
            return new ApplicationPackageBuilder().
                    addCluster(new ContentClusterBuilder().name("foo").docTypes("d1", "d2"))
                                                  .addSchemas(new SchemaBuilder().name("d1").content(d1Content).build())
                                                  .addSchemas(new SchemaBuilder().name("d2").content(d2Content).build()).
                    buildCreator().create();
        }

        public static Fixture newTwoClusterFixture(String currentSd, String nextSd) {
            return new Fixture(newTwoClusterModel(currentSd, currentSd), newTwoClusterModel(nextSd, nextSd));
        }

        public static VespaModel newTwoClusterModel(String d1Content, String d2Content) {
            return new ApplicationPackageBuilder().
                    addCluster(new ContentClusterBuilder().name("foo").docTypes("d1")).
                    addCluster(new ContentClusterBuilder().name("bar").docTypes("d2"))
                                                  .addSchemas(new SchemaBuilder().name("d1").content(d1Content).build())
                                                  .addSchemas(new SchemaBuilder().name("d2").content(d2Content).build()).
                    buildCreator().create();
        }

        private List<ConfigChangeAction> validate() {
            return normalizeServicesInActions(validator.validate(currentModel, nextModel,
                                                                 new DeployState.Builder().build()));
        }

        public void assertValidation() {
            assertTrue(validate().isEmpty());
        }

        public void assertValidation(ConfigChangeAction exp) {
            assertValidation(List.of(exp));
        }

        public void assertValidation(List<ConfigChangeAction> exp) {
            assertEqualActions(exp, validate());
        }
    }

    static String STRING_FIELD = "field f1 type string { indexing: summary }";
    static String ATTRIBUTE_FIELD = "field f1 type string { indexing: attribute | summary }";
    static String ATTRIBUTE_CHANGE_MSG = "Field 'f1' changed: add attribute aspect";
    static String INT_FIELD = "field f1 type int { indexing: summary }";
    static String FIELD_TYPE_CHANGE_MSG = "Field 'f1' changed: data type: 'string' -> 'int'";
    private static final List<ServiceInfo> FOO_SERVICE = List.of(
            new ServiceInfo("searchnode", "null", null, null, "foo/search/cluster.foo/0", "null"));
    private static final List<ServiceInfo> BAR_SERVICE = List.of(
            new ServiceInfo("searchnode2", "null", null, null, "bar/search/cluster.bar/0", "null"));

    @Test
    void requireThatDocumentDatabaseChangeIsDiscovered() {
        Fixture.newOneDocFixture(STRING_FIELD, ATTRIBUTE_FIELD).
                assertValidation(newRestartAction(ClusterSpec.Id.from("test"),
                "Document type 'd1': " + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE));
    }

    @Test
    void requireThatChangeInSeveralDocumentDatabasesAreDiscovered() {
        Fixture.newTwoDocFixture(STRING_FIELD, ATTRIBUTE_FIELD).
                assertValidation(List.of(newRestartAction(ClusterSpec.Id.from("test"),
                "Document type 'd1': " + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE),
                newRestartAction(ClusterSpec.Id.from("test"),
                        "Document type 'd2': " + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE)));
    }

    @Test
    void requireThatChangeInSeveralContentClustersAreDiscovered() {
        Fixture.newTwoClusterFixture(STRING_FIELD, ATTRIBUTE_FIELD).
                assertValidation(List.of(newRestartAction(ClusterSpec.Id.from("test"),
                "Document type 'd1': " + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE),
                newRestartAction(ClusterSpec.Id.from("test"),
                        "Document type 'd2': " + ATTRIBUTE_CHANGE_MSG, BAR_SERVICE)));
    }

    @Test
    void requireThatAddingDocumentDatabaseIsOk() {
        new Fixture(Fixture.newOneDocModel(STRING_FIELD), Fixture.newTwoDocModel(STRING_FIELD, STRING_FIELD)).assertValidation();
    }

    @Test
    void requireThatRemovingDocumentDatabaseIsOk() {
        new Fixture(Fixture.newTwoDocModel(STRING_FIELD, STRING_FIELD), Fixture.newOneDocModel(STRING_FIELD)).assertValidation();
    }

    @Test
    void requireThatAddingContentClusterIsOk() {
        new Fixture(Fixture.newOneDocModel(STRING_FIELD), Fixture.newTwoClusterModel(STRING_FIELD, STRING_FIELD)).assertValidation();
    }

    @Test
    void requireThatRemovingContentClusterIsOk() {
        new Fixture(Fixture.newTwoClusterModel(STRING_FIELD, STRING_FIELD), Fixture.newOneDocModel(STRING_FIELD)).assertValidation();
    }

    @Test
    void requireThatChangingFieldTypeIsDiscovered() {
        Fixture f = Fixture.newOneDocFixture(STRING_FIELD, INT_FIELD);
        f.assertValidation(List.of(newRefeedAction(ClusterSpec.Id.from("test"),
                ValidationId.fieldTypeChange,
                "Document type 'd1': " + FIELD_TYPE_CHANGE_MSG, FOO_SERVICE, "d1")));
    }

}