Promote SchemaSourceRepresentation
[yangtools.git] / parser / yang-parser-impl / src / test / java / org / opendaylight / yangtools / yang / parser / repo / SharedEffectiveModelContextFactoryTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.parser.repo;
9
10 import static java.util.Objects.requireNonNull;
11 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
12 import static org.junit.jupiter.api.Assertions.assertNotNull;
13 import static org.junit.jupiter.api.Assertions.assertThrows;
14 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
15 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
16
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.util.concurrent.ExecutionException;
19 import org.junit.jupiter.api.BeforeEach;
20 import org.junit.jupiter.api.Test;
21 import org.opendaylight.yangtools.yang.ir.YangIRSchemaSource;
22 import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
23 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
24 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
25 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
26 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
27 import org.opendaylight.yangtools.yang.model.spi.source.YangTextSource;
28 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
29
30 public class SharedEffectiveModelContextFactoryTest {
31     private final SharedSchemaRepository repository = new SharedSchemaRepository("test");
32     private final SchemaContextFactoryConfiguration config = SchemaContextFactoryConfiguration.getDefault();
33
34     private SourceIdentifier s1;
35     private SourceIdentifier s2;
36
37     @BeforeEach
38     public void setUp() {
39         final var source1 = YangTextSource.forResource("/ietf/ietf-inet-types@2010-09-24.yang");
40         final var source2 = YangTextSource.forResource("/ietf/iana-timezones@2012-07-09.yang");
41         s1 = new SourceIdentifier("ietf-inet-types", "2010-09-24");
42         s2 = new SourceIdentifier("iana-timezones", "2012-07-09");
43
44         final var transformer = TextToIRTransformer.create(repository, repository);
45         repository.registerSchemaSourceListener(transformer);
46
47         repository.registerSchemaSource(sourceIdentifier -> immediateFluentFuture(source1),
48             PotentialSchemaSource.create(s1, YangTextSource.class, 1));
49
50         repository.registerSchemaSource(sourceIdentifier -> immediateFluentFuture(source2),
51             PotentialSchemaSource.create(s2, YangTextSource.class, 1));
52     }
53
54     @Test
55     public void testCreateSchemaContextWithDuplicateRequiredSources() throws Exception {
56         final var sharedSchemaContextFactory = new SharedEffectiveModelContextFactory(repository, config);
57         final var schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(s1, s1, s2);
58         assertNotNull(schemaContext.get());
59     }
60
61     @Test
62     public void testSourceRegisteredWithDifferentSI() throws Exception {
63         final var source1 = YangTextSource.forResource("/ietf/ietf-inet-types@2010-09-24.yang");
64         final var source2 = YangTextSource.forResource("/ietf/iana-timezones@2012-07-09.yang");
65         s1 = source1.sourceId();
66         s2 = source2.sourceId();
67
68         final var provider = SharedSchemaRepositoryTest.getImmediateYangSourceProviderFromResource(
69             "/no-revision/imported@2012-12-12.yang");
70         provider.setResult();
71         provider.register(repository);
72
73         // Register the same provider under source id without revision
74         final var sIdWithoutRevision = new SourceIdentifier(provider.getId().name());
75         repository.registerSchemaSource(provider, PotentialSchemaSource.create(sIdWithoutRevision,
76             YangIRSchemaSource.class, PotentialSchemaSource.Costs.IMMEDIATE.getValue()));
77
78         final var sharedSchemaContextFactory = new SharedEffectiveModelContextFactory(repository, config);
79         final var schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(
80             sIdWithoutRevision, provider.getId());
81         assertNotNull(schemaContext.get());
82     }
83
84     @Test
85     public void testTransientFailureWhilreRetrievingSchemaSource() throws Exception {
86         final SourceIdentifier s3 = new SourceIdentifier("network-topology", "2013-10-21");
87
88         repository.registerSchemaSource(new TransientFailureProvider(
89             YangTextSource.forResource("/ietf/network-topology@2013-10-21.yang")),
90             PotentialSchemaSource.create(s3, YangTextSource.class, 1));
91
92         final var sharedSchemaContextFactory = new SharedEffectiveModelContextFactory(repository, config);
93
94         var schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(s1, s3);
95
96         final var exception = assertThrows(ExecutionException.class, schemaContext::get);
97         assertInstanceOf(MissingSchemaSourceException.class, exception.getCause());
98
99         // check if future is invalidated and resolution of source is retried after failure
100         schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(s1, s3);
101         assertNotNull(schemaContext.get());
102     }
103
104     /**
105      * Schema source provider that fails on first attempt of getSource() and succeeds on every subsequent call
106      * to simulate transient failures of source retrieval.
107      */
108     private static final class TransientFailureProvider implements SchemaSourceProvider<YangTextSource> {
109         private final YangTextSource schemaSource;
110
111         private boolean shouldFail = true;
112
113         private TransientFailureProvider(final YangTextSource schemaSource) {
114             this.schemaSource = requireNonNull(schemaSource);
115         }
116
117         @Override
118         public ListenableFuture<YangTextSource> getSource(final SourceIdentifier sourceIdentifier) {
119             if (shouldFail) {
120                 shouldFail = false;
121                 return immediateFailedFluentFuture(new Exception("Transient test failure."));
122             }
123
124             return immediateFluentFuture(schemaSource);
125         }
126     }
127 }