ReplicaQuerySQLRouterTest.java 11.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

18
package org.apache.shardingsphere.replicaquery.route.engine;
19

L
Liang Zhang 已提交
20 21
import org.apache.shardingsphere.infra.binder.LogicSQL;
import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
22
import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties;
23
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
L
Liang Zhang 已提交
24
import org.apache.shardingsphere.infra.metadata.resource.ShardingSphereResource;
25
import org.apache.shardingsphere.infra.metadata.rule.ShardingSphereRuleMetaData;
26
import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
27
import org.apache.shardingsphere.infra.route.SQLRouter;
28 29 30
import org.apache.shardingsphere.infra.route.context.RouteContext;
import org.apache.shardingsphere.infra.route.context.RouteMapper;
import org.apache.shardingsphere.infra.route.context.RouteUnit;
31
import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
L
Liang Zhang 已提交
32
import org.apache.shardingsphere.infra.spi.ordered.OrderedSPIRegistry;
33 34 35 36
import org.apache.shardingsphere.replicaquery.api.config.ReplicaQueryRuleConfiguration;
import org.apache.shardingsphere.replicaquery.api.config.rule.ReplicaQueryDataSourceRuleConfiguration;
import org.apache.shardingsphere.replicaquery.route.engine.impl.PrimaryVisitedManager;
import org.apache.shardingsphere.replicaquery.rule.ReplicaQueryRule;
T
tristaZero 已提交
37 38 39
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.LockSegment;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
40
import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLSelectStatement;
41 42 43 44 45 46
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
47

L
Liang Zhang 已提交
48
import java.util.Collections;
49
import java.util.Iterator;
L
Liang Zhang 已提交
50
import java.util.Optional;
51
import java.util.Properties;
52 53 54

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
L
Liang Zhang 已提交
55
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
Z
zhyee 已提交
56
import static org.mockito.Mockito.mock;
57 58 59
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
60
public final class ReplicaQuerySQLRouterTest {
61 62 63
    
    private static final String DATASOURCE_NAME = "ds";
    
64
    private static final String NONE_REPLICA_QUERY_DATASOURCE_NAME = "noneReplicaQueryDatasource";
65
    
66
    private static final String PRIMARY_DATASOURCE = "primary";
67
    
68
    private static final String REPLICA_DATASOURCE = "query";
69
    
70
    private ReplicaQueryRule rule;
71 72
    
    @Mock
73
    private SQLStatementContext<SQLStatement> sqlStatementContext;
74
    
75
    private ReplicaQuerySQLRouter sqlRouter;
76
    
77
    static {
78
        ShardingSphereServiceLoader.register(SQLRouter.class);
79
    }
80
    
81
    @Before
82
    public void setUp() {
83 84 85
        rule = new ReplicaQueryRule(new ReplicaQueryRuleConfiguration(Collections.singleton(
                new ReplicaQueryDataSourceRuleConfiguration(DATASOURCE_NAME, PRIMARY_DATASOURCE, Collections.singletonList(REPLICA_DATASOURCE), null)), Collections.emptyMap()));
        sqlRouter = (ReplicaQuerySQLRouter) OrderedSPIRegistry.getRegisteredServices(Collections.singleton(rule), SQLRouter.class).get(rule);
86 87 88 89
    }
    
    @After
    public void tearDown() {
90
        PrimaryVisitedManager.clear();
91 92 93
    }
    
    @Test
94
    public void assertCreateRouteContextToPrimaryWithoutRouteUnits() {
L
Liang Zhang 已提交
95
        LogicSQL logicSQL = new LogicSQL(mock(SQLStatementContext.class), "", Collections.emptyList());
96
        ShardingSphereRuleMetaData ruleMetaData = new ShardingSphereRuleMetaData(Collections.emptyList(), Collections.singleton(rule));
97
        ShardingSphereMetaData metaData = new ShardingSphereMetaData("logic_schema", mock(ShardingSphereResource.class, RETURNS_DEEP_STUBS), ruleMetaData, mock(ShardingSphereSchema.class));
98
        RouteContext actual = sqlRouter.createRouteContext(logicSQL, metaData, rule, new ConfigurationProperties(new Properties()));
99
        Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
100
        assertThat(routedDataSourceNames.next(), is(PRIMARY_DATASOURCE));
101 102
    }
    
L
Liang Zhang 已提交
103
    @Test
104 105
    public void assertDecorateRouteContextToPrimaryDataSource() {
        RouteContext actual = mockRouteContext();
L
Liang Zhang 已提交
106
        LogicSQL logicSQL = new LogicSQL(mock(SQLStatementContext.class), "", Collections.emptyList());
107
        ShardingSphereRuleMetaData ruleMetaData = new ShardingSphereRuleMetaData(Collections.emptyList(), Collections.singleton(rule));
108
        ShardingSphereMetaData metaData = new ShardingSphereMetaData("logic_schema", mock(ShardingSphereResource.class, RETURNS_DEEP_STUBS), ruleMetaData, mock(ShardingSphereSchema.class));
109
        sqlRouter.decorateRouteContext(actual, logicSQL, metaData, rule, new ConfigurationProperties(new Properties()));
110
        Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
111
        assertThat(routedDataSourceNames.next(), is(NONE_REPLICA_QUERY_DATASOURCE_NAME));
112
        assertThat(routedDataSourceNames.next(), is(PRIMARY_DATASOURCE));
L
Liang Zhang 已提交
113 114
    }
    
115
    @Test
116
    public void assertCreateRouteContextToReplicaDataSource() {
117 118
        MySQLSelectStatement selectStatement = mock(MySQLSelectStatement.class);
        when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
L
Liang Zhang 已提交
119
        when(selectStatement.getLock()).thenReturn(Optional.empty());
L
Liang Zhang 已提交
120
        LogicSQL logicSQL = new LogicSQL(sqlStatementContext, "", Collections.emptyList());
121
        ShardingSphereRuleMetaData ruleMetaData = new ShardingSphereRuleMetaData(Collections.emptyList(), Collections.singleton(rule));
122
        ShardingSphereMetaData metaData = new ShardingSphereMetaData("logic_schema", mock(ShardingSphereResource.class, RETURNS_DEEP_STUBS), ruleMetaData, mock(ShardingSphereSchema.class));
123
        RouteContext actual = sqlRouter.createRouteContext(logicSQL, metaData, rule, new ConfigurationProperties(new Properties()));
124
        Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
125
        assertThat(routedDataSourceNames.next(), is(REPLICA_DATASOURCE));
126
    }
L
Liang Zhang 已提交
127 128
    
    @Test
129 130
    public void assertDecorateRouteContextToReplicaDataSource() {
        RouteContext actual = mockRouteContext();
131 132
        MySQLSelectStatement selectStatement = mock(MySQLSelectStatement.class);
        when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
L
Liang Zhang 已提交
133
        when(selectStatement.getLock()).thenReturn(Optional.empty());
L
Liang Zhang 已提交
134
        LogicSQL logicSQL = new LogicSQL(sqlStatementContext, "", Collections.emptyList());
135
        ShardingSphereRuleMetaData ruleMetaData = new ShardingSphereRuleMetaData(Collections.emptyList(), Collections.singleton(rule));
136
        ShardingSphereMetaData metaData = new ShardingSphereMetaData("logic_schema", mock(ShardingSphereResource.class, RETURNS_DEEP_STUBS), ruleMetaData, mock(ShardingSphereSchema.class));
137
        sqlRouter.decorateRouteContext(actual, logicSQL, metaData, rule, new ConfigurationProperties(new Properties()));
138
        Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
139
        assertThat(routedDataSourceNames.next(), is(NONE_REPLICA_QUERY_DATASOURCE_NAME));
140
        assertThat(routedDataSourceNames.next(), is(REPLICA_DATASOURCE));
L
Liang Zhang 已提交
141 142
    }
    
Z
zhyee 已提交
143
    @Test
144
    public void assertCreateRouteContextToPrimaryDataSourceWithLock() {
145 146
        MySQLSelectStatement selectStatement = mock(MySQLSelectStatement.class);
        when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
Z
zhyee 已提交
147
        when(selectStatement.getLock()).thenReturn(Optional.of(mock(LockSegment.class)));
L
Liang Zhang 已提交
148
        LogicSQL logicSQL = new LogicSQL(sqlStatementContext, "", Collections.emptyList());
149
        ShardingSphereRuleMetaData ruleMetaData = new ShardingSphereRuleMetaData(Collections.emptyList(), Collections.singleton(rule));
150
        ShardingSphereMetaData metaData = new ShardingSphereMetaData("logic_schema", mock(ShardingSphereResource.class, RETURNS_DEEP_STUBS), ruleMetaData, mock(ShardingSphereSchema.class));
151
        RouteContext actual = sqlRouter.createRouteContext(logicSQL, metaData, rule, new ConfigurationProperties(new Properties()));
152
        Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
153
        assertThat(routedDataSourceNames.next(), is(PRIMARY_DATASOURCE));
Z
zhyee 已提交
154
    }
155
    
L
Liang Zhang 已提交
156
    @Test
157 158
    public void assertDecorateRouteContextToPrimaryDataSourceWithLock() {
        RouteContext actual = mockRouteContext();
159 160
        MySQLSelectStatement selectStatement = mock(MySQLSelectStatement.class);
        when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
L
Liang Zhang 已提交
161
        when(selectStatement.getLock()).thenReturn(Optional.of(mock(LockSegment.class)));
L
Liang Zhang 已提交
162
        LogicSQL logicSQL = new LogicSQL(sqlStatementContext, "", Collections.emptyList());
163
        ShardingSphereRuleMetaData ruleMetaData = new ShardingSphereRuleMetaData(Collections.emptyList(), Collections.singleton(rule));
164
        ShardingSphereMetaData metaData = new ShardingSphereMetaData("logic_schema", mock(ShardingSphereResource.class, RETURNS_DEEP_STUBS), ruleMetaData, mock(ShardingSphereSchema.class));
165
        sqlRouter.decorateRouteContext(actual, logicSQL, metaData, rule, new ConfigurationProperties(new Properties()));
166
        Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
167
        assertThat(routedDataSourceNames.next(), is(NONE_REPLICA_QUERY_DATASOURCE_NAME));
168
        assertThat(routedDataSourceNames.next(), is(PRIMARY_DATASOURCE));
L
Liang Zhang 已提交
169 170
    }
    
171
    @Test
172
    public void assertCreateRouteContextToPrimaryDataSource() {
173
        when(sqlStatementContext.getSqlStatement()).thenReturn(mock(InsertStatement.class));
L
Liang Zhang 已提交
174
        LogicSQL logicSQL = new LogicSQL(sqlStatementContext, "", Collections.emptyList());
175
        ShardingSphereRuleMetaData ruleMetaData = new ShardingSphereRuleMetaData(Collections.emptyList(), Collections.singleton(rule));
176
        ShardingSphereMetaData metaData = new ShardingSphereMetaData("logic_schema", mock(ShardingSphereResource.class, RETURNS_DEEP_STUBS), ruleMetaData, mock(ShardingSphereSchema.class));
177
        RouteContext actual = sqlRouter.createRouteContext(logicSQL, metaData, rule, new ConfigurationProperties(new Properties()));
178
        Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
179
        assertThat(routedDataSourceNames.next(), is(PRIMARY_DATASOURCE));
180 181
    }
    
182 183
    private RouteContext mockRouteContext() {
        RouteContext result = new RouteContext();
L
Liang Zhang 已提交
184
        RouteUnit routeUnit = new RouteUnit(new RouteMapper(DATASOURCE_NAME, DATASOURCE_NAME), Collections.singletonList(new RouteMapper("table", "table_0")));
185
        result.getRouteUnits().add(routeUnit);
186
        result.getRouteUnits().add(new RouteUnit(new RouteMapper(NONE_REPLICA_QUERY_DATASOURCE_NAME, NONE_REPLICA_QUERY_DATASOURCE_NAME), Collections.emptyList()));
187
        return result;
188
    }
189
}