Committed by
Gerrit Code Review
[ONOS-2225] Add codecs with unit test for FlowObjective REST API
* Add codec for FilteringObjective * Add codec for ForwardingObjective * Add codec for NextObjective Change-Id: I715aa7f1969697468692459052fd27cc65ca2363
Showing
15 changed files
with
1398 additions
and
0 deletions
... | @@ -43,6 +43,9 @@ import org.onosproject.net.flow.TrafficSelector; | ... | @@ -43,6 +43,9 @@ import org.onosproject.net.flow.TrafficSelector; |
43 | import org.onosproject.net.flow.TrafficTreatment; | 43 | import org.onosproject.net.flow.TrafficTreatment; |
44 | import org.onosproject.net.flow.criteria.Criterion; | 44 | import org.onosproject.net.flow.criteria.Criterion; |
45 | import org.onosproject.net.flow.instructions.Instruction; | 45 | import org.onosproject.net.flow.instructions.Instruction; |
46 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
47 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
48 | +import org.onosproject.net.flowobjective.NextObjective; | ||
46 | import org.onosproject.net.group.Group; | 49 | import org.onosproject.net.group.Group; |
47 | import org.onosproject.net.group.GroupBucket; | 50 | import org.onosproject.net.group.GroupBucket; |
48 | import org.onosproject.net.intent.ConnectivityIntent; | 51 | import org.onosproject.net.intent.ConnectivityIntent; |
... | @@ -109,6 +112,9 @@ public class CodecManager implements CodecService { | ... | @@ -109,6 +112,9 @@ public class CodecManager implements CodecService { |
109 | registerCodec(TableStatisticsEntry.class, new TableStatisticsEntryCodec()); | 112 | registerCodec(TableStatisticsEntry.class, new TableStatisticsEntryCodec()); |
110 | registerCodec(PortStatistics.class, new PortStatisticsCodec()); | 113 | registerCodec(PortStatistics.class, new PortStatisticsCodec()); |
111 | registerCodec(Metric.class, new MetricCodec()); | 114 | registerCodec(Metric.class, new MetricCodec()); |
115 | + registerCodec(FilteringObjective.class, new FilteringObjectiveCodec()); | ||
116 | + registerCodec(ForwardingObjective.class, new ForwardingObjectiveCodec()); | ||
117 | + registerCodec(NextObjective.class, new NextObjectiveCodec()); | ||
112 | log.info("Started"); | 118 | log.info("Started"); |
113 | } | 119 | } |
114 | 120 | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
20 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
21 | +import org.onosproject.codec.CodecContext; | ||
22 | +import org.onosproject.codec.JsonCodec; | ||
23 | +import org.onosproject.core.ApplicationId; | ||
24 | +import org.onosproject.core.CoreService; | ||
25 | +import org.onosproject.net.flow.TrafficTreatment; | ||
26 | +import org.onosproject.net.flow.criteria.Criterion; | ||
27 | +import org.onosproject.net.flowobjective.DefaultFilteringObjective; | ||
28 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
29 | +import org.slf4j.Logger; | ||
30 | + | ||
31 | +import java.util.stream.IntStream; | ||
32 | + | ||
33 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
34 | +import static org.onlab.util.Tools.nullIsIllegal; | ||
35 | +import static org.slf4j.LoggerFactory.getLogger; | ||
36 | + | ||
37 | +/** | ||
38 | + * Filtering Objective Codec. | ||
39 | + */ | ||
40 | +public class FilteringObjectiveCodec extends JsonCodec<FilteringObjective> { | ||
41 | + private final Logger log = getLogger(getClass()); | ||
42 | + | ||
43 | + // JSON field names | ||
44 | + private static final String ID = "id"; | ||
45 | + private static final String TYPE = "type"; | ||
46 | + private static final String KEY = "key"; | ||
47 | + private static final String META = "meta"; | ||
48 | + private static final String OPERATION = "operation"; | ||
49 | + private static final String CONDITIONS = "conditions"; | ||
50 | + | ||
51 | + // messages to be printed out | ||
52 | + private static final String MISSING_MEMBER_MESSAGE = | ||
53 | + " member is required in FilteringObjective"; | ||
54 | + private static final String NOT_NULL_MESSAGE = | ||
55 | + "FilteringObjective cannot be null"; | ||
56 | + private static final String INVALID_TYPE_MESSAGE = | ||
57 | + "The requested type {} is not defined in FilteringObjective."; | ||
58 | + private static final String INVALID_OP_MESSAGE = | ||
59 | + "The requested operation {} is not defined for FilteringObjective."; | ||
60 | + | ||
61 | + public static final String REST_APP_ID = "org.onosproject.rest"; | ||
62 | + | ||
63 | + @Override | ||
64 | + public ObjectNode encode(FilteringObjective filteringObjective, CodecContext context) { | ||
65 | + | ||
66 | + checkNotNull(filteringObjective, NOT_NULL_MESSAGE); | ||
67 | + | ||
68 | + final JsonCodec<Criterion> criterionCodec = context.codec(Criterion.class); | ||
69 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
70 | + | ||
71 | + // encode common properties | ||
72 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
73 | + ObjectNode result = och.encode(filteringObjective, context); | ||
74 | + | ||
75 | + // encode id | ||
76 | + result.put(ID, filteringObjective.id()); | ||
77 | + | ||
78 | + // encode type | ||
79 | + result.put(TYPE, filteringObjective.type().toString()); | ||
80 | + | ||
81 | + // encode key | ||
82 | + if (filteringObjective.key() != null) { | ||
83 | + ObjectNode criterionNode = criterionCodec.encode(filteringObjective.key(), context); | ||
84 | + result.set(KEY, criterionNode); | ||
85 | + } | ||
86 | + | ||
87 | + // encode meta | ||
88 | + if (filteringObjective.meta() != null) { | ||
89 | + ObjectNode trafficTreatmentNode = trafficTreatmentCodec.encode(filteringObjective.meta(), context); | ||
90 | + result.set(META, trafficTreatmentNode); | ||
91 | + } | ||
92 | + | ||
93 | + // encode conditions | ||
94 | + ArrayNode conditions = context.mapper().createArrayNode(); | ||
95 | + filteringObjective.conditions().forEach(c -> { | ||
96 | + ObjectNode criterionJson = criterionCodec.encode(c, context); | ||
97 | + conditions.add(criterionJson); | ||
98 | + }); | ||
99 | + result.set(CONDITIONS, conditions); | ||
100 | + | ||
101 | + return result; | ||
102 | + } | ||
103 | + | ||
104 | + @Override | ||
105 | + public FilteringObjective decode(ObjectNode json, CodecContext context) { | ||
106 | + if (json == null || !json.isObject()) { | ||
107 | + return null; | ||
108 | + } | ||
109 | + | ||
110 | + CoreService coreService = context.getService(CoreService.class); | ||
111 | + | ||
112 | + final JsonCodec<Criterion> criterionCodec = context.codec(Criterion.class); | ||
113 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
114 | + | ||
115 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
116 | + | ||
117 | + DefaultFilteringObjective.Builder baseBuilder = DefaultFilteringObjective.builder(); | ||
118 | + final DefaultFilteringObjective.Builder builder = | ||
119 | + (DefaultFilteringObjective.Builder) och.decode(json, baseBuilder, context); | ||
120 | + | ||
121 | + // application id | ||
122 | + ApplicationId appId = coreService.registerApplication(REST_APP_ID); | ||
123 | + builder.fromApp(appId); | ||
124 | + | ||
125 | + // decode type | ||
126 | + String typeStr = nullIsIllegal(json.get(TYPE), TYPE + MISSING_MEMBER_MESSAGE).asText(); | ||
127 | + | ||
128 | + switch (typeStr) { | ||
129 | + case "PERMIT": | ||
130 | + builder.permit(); | ||
131 | + break; | ||
132 | + case "DENY": | ||
133 | + builder.deny(); | ||
134 | + break; | ||
135 | + default: | ||
136 | + log.warn(INVALID_TYPE_MESSAGE, typeStr); | ||
137 | + return null; | ||
138 | + } | ||
139 | + | ||
140 | + // decode key | ||
141 | + JsonNode keyJson = json.get(KEY); | ||
142 | + if (keyJson != null) { | ||
143 | + Criterion key = criterionCodec.decode((ObjectNode) keyJson, context); | ||
144 | + builder.withKey(key); | ||
145 | + } | ||
146 | + | ||
147 | + // decode conditions | ||
148 | + JsonNode conditionsJson = json.get(CONDITIONS); | ||
149 | + checkNotNull(conditionsJson); | ||
150 | + if (conditionsJson != null) { | ||
151 | + IntStream.range(0, conditionsJson.size()).forEach(i -> { | ||
152 | + ObjectNode conditionJson = get(conditionsJson, i); | ||
153 | + builder.addCondition(criterionCodec.decode(conditionJson, context)); | ||
154 | + }); | ||
155 | + } | ||
156 | + | ||
157 | + // decode meta | ||
158 | + JsonNode metaJson = json.get(META); | ||
159 | + if (metaJson != null) { | ||
160 | + TrafficTreatment trafficTreatment = trafficTreatmentCodec.decode((ObjectNode) metaJson, context); | ||
161 | + builder.withMeta(trafficTreatment); | ||
162 | + } | ||
163 | + | ||
164 | + // decode operation | ||
165 | + String opStr = nullIsIllegal(json.get(OPERATION), OPERATION + MISSING_MEMBER_MESSAGE).asText(); | ||
166 | + FilteringObjective filteringObjective; | ||
167 | + | ||
168 | + switch (opStr) { | ||
169 | + case "ADD": | ||
170 | + filteringObjective = builder.add(); | ||
171 | + break; | ||
172 | + case "REMOVE": | ||
173 | + filteringObjective = builder.remove(); | ||
174 | + break; | ||
175 | + default: | ||
176 | + log.warn(INVALID_OP_MESSAGE, opStr); | ||
177 | + return null; | ||
178 | + } | ||
179 | + | ||
180 | + return filteringObjective; | ||
181 | + } | ||
182 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | +import org.onosproject.codec.CodecContext; | ||
21 | +import org.onosproject.codec.JsonCodec; | ||
22 | +import org.onosproject.core.ApplicationId; | ||
23 | +import org.onosproject.core.CoreService; | ||
24 | +import org.onosproject.net.flow.TrafficSelector; | ||
25 | +import org.onosproject.net.flow.TrafficTreatment; | ||
26 | +import org.onosproject.net.flowobjective.DefaultForwardingObjective; | ||
27 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
28 | +import org.slf4j.Logger; | ||
29 | + | ||
30 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
31 | +import static org.onlab.util.Tools.nullIsIllegal; | ||
32 | +import static org.slf4j.LoggerFactory.getLogger; | ||
33 | + | ||
34 | +/** | ||
35 | + * Forwarding Objective Codec. | ||
36 | + */ | ||
37 | +public class ForwardingObjectiveCodec extends JsonCodec<ForwardingObjective> { | ||
38 | + private final Logger log = getLogger(getClass()); | ||
39 | + | ||
40 | + // JSON field names | ||
41 | + private static final String ID = "id"; | ||
42 | + private static final String SELECTOR = "selector"; | ||
43 | + private static final String FLAG = "flag"; | ||
44 | + private static final String OPERATION = "operation"; | ||
45 | + private static final String NEXT_ID = "nextId"; | ||
46 | + private static final String TREATMENT = "treatment"; | ||
47 | + | ||
48 | + // messages to be printed out | ||
49 | + private static final String MISSING_MEMBER_MESSAGE = | ||
50 | + " member is required in ForwardingObjective"; | ||
51 | + private static final String NOT_NULL_MESSAGE = | ||
52 | + "ForwardingObjective cannot be null"; | ||
53 | + private static final String INVALID_FLAG_MESSAGE = | ||
54 | + "The requested flag {} is not defined in ForwardingObjective."; | ||
55 | + private static final String INVALID_OP_MESSAGE = | ||
56 | + "The requested operation {} is not defined for FilteringObjective."; | ||
57 | + | ||
58 | + public static final String REST_APP_ID = "org.onosproject.rest"; | ||
59 | + | ||
60 | + @Override | ||
61 | + public ObjectNode encode(ForwardingObjective forwardingObjective, CodecContext context) { | ||
62 | + | ||
63 | + checkNotNull(forwardingObjective, NOT_NULL_MESSAGE); | ||
64 | + | ||
65 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
66 | + final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class); | ||
67 | + | ||
68 | + // encode common properties | ||
69 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
70 | + ObjectNode result = och.encode(forwardingObjective, context); | ||
71 | + | ||
72 | + // encode id | ||
73 | + result.put(ID, forwardingObjective.id()); | ||
74 | + | ||
75 | + // encode flag | ||
76 | + result.put(FLAG, forwardingObjective.flag().toString()); | ||
77 | + | ||
78 | + // encode op | ||
79 | + result.put(OPERATION, forwardingObjective.op().toString()); | ||
80 | + | ||
81 | + // encode selector | ||
82 | + ObjectNode trafficSelectorNode = | ||
83 | + trafficSelectorCodec.encode(forwardingObjective.selector(), context); | ||
84 | + result.set(SELECTOR, trafficSelectorNode); | ||
85 | + | ||
86 | + // encode nextId | ||
87 | + if (forwardingObjective.nextId() != null) { | ||
88 | + result.put(NEXT_ID, forwardingObjective.nextId()); | ||
89 | + } | ||
90 | + | ||
91 | + // encode treatment | ||
92 | + if (forwardingObjective.treatment() != null) { | ||
93 | + ObjectNode trafficTreatmentNode = | ||
94 | + trafficTreatmentCodec.encode(forwardingObjective.treatment(), context); | ||
95 | + result.set(TREATMENT, trafficTreatmentNode); | ||
96 | + } | ||
97 | + | ||
98 | + return result; | ||
99 | + } | ||
100 | + | ||
101 | + @Override | ||
102 | + public ForwardingObjective decode(ObjectNode json, CodecContext context) { | ||
103 | + if (json == null || !json.isObject()) { | ||
104 | + return null; | ||
105 | + } | ||
106 | + | ||
107 | + CoreService coreService = context.getService(CoreService.class); | ||
108 | + | ||
109 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
110 | + final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class); | ||
111 | + | ||
112 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
113 | + | ||
114 | + DefaultForwardingObjective.Builder baseBuilder = DefaultForwardingObjective.builder(); | ||
115 | + final DefaultForwardingObjective.Builder builder = | ||
116 | + (DefaultForwardingObjective.Builder) och.decode(json, baseBuilder, context); | ||
117 | + | ||
118 | + // application id | ||
119 | + ApplicationId appId = coreService.registerApplication(REST_APP_ID); | ||
120 | + builder.fromApp(appId); | ||
121 | + | ||
122 | + // decode flag | ||
123 | + String flagStr = nullIsIllegal(json.get(FLAG), FLAG + MISSING_MEMBER_MESSAGE).asText(); | ||
124 | + switch (flagStr) { | ||
125 | + case "SPECIFIC": | ||
126 | + builder.withFlag(ForwardingObjective.Flag.SPECIFIC); | ||
127 | + break; | ||
128 | + case "VERSATILE": | ||
129 | + builder.withFlag(ForwardingObjective.Flag.VERSATILE); | ||
130 | + break; | ||
131 | + default: | ||
132 | + log.warn(INVALID_FLAG_MESSAGE, flagStr); | ||
133 | + return null; | ||
134 | + } | ||
135 | + | ||
136 | + // decode selector | ||
137 | + JsonNode selectorJson = json.get(SELECTOR); | ||
138 | + if (selectorJson != null) { | ||
139 | + TrafficSelector trafficSelector = trafficSelectorCodec.decode((ObjectNode) selectorJson, context); | ||
140 | + builder.withSelector(trafficSelector); | ||
141 | + } | ||
142 | + | ||
143 | + // decode treatment | ||
144 | + JsonNode treatmentJson = json.get(TREATMENT); | ||
145 | + if (treatmentJson != null) { | ||
146 | + TrafficTreatment trafficTreatment = trafficTreatmentCodec.decode((ObjectNode) treatmentJson, context); | ||
147 | + builder.withTreatment(trafficTreatment); | ||
148 | + } | ||
149 | + | ||
150 | + // decode nextId | ||
151 | + JsonNode nextIdJson = json.get(NEXT_ID); | ||
152 | + if (nextIdJson != null) { | ||
153 | + builder.nextStep(nextIdJson.asInt()); | ||
154 | + } | ||
155 | + | ||
156 | + // decode operation | ||
157 | + String opStr = nullIsIllegal(json.get(OPERATION), OPERATION + MISSING_MEMBER_MESSAGE).asText(); | ||
158 | + ForwardingObjective forwardingObjective; | ||
159 | + | ||
160 | + switch (opStr) { | ||
161 | + case "ADD": | ||
162 | + forwardingObjective = builder.add(); | ||
163 | + break; | ||
164 | + case "REMOVE": | ||
165 | + forwardingObjective = builder.remove(); | ||
166 | + break; | ||
167 | + default: | ||
168 | + log.warn(INVALID_OP_MESSAGE, opStr); | ||
169 | + return null; | ||
170 | + } | ||
171 | + | ||
172 | + return forwardingObjective; | ||
173 | + } | ||
174 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
20 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
21 | +import org.onosproject.codec.CodecContext; | ||
22 | +import org.onosproject.codec.JsonCodec; | ||
23 | +import org.onosproject.core.ApplicationId; | ||
24 | +import org.onosproject.core.CoreService; | ||
25 | +import org.onosproject.net.flow.TrafficSelector; | ||
26 | +import org.onosproject.net.flow.TrafficTreatment; | ||
27 | +import org.onosproject.net.flowobjective.DefaultNextObjective; | ||
28 | +import org.onosproject.net.flowobjective.NextObjective; | ||
29 | +import org.slf4j.Logger; | ||
30 | + | ||
31 | +import java.util.stream.IntStream; | ||
32 | + | ||
33 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
34 | +import static org.onlab.util.Tools.nullIsIllegal; | ||
35 | +import static org.slf4j.LoggerFactory.getLogger; | ||
36 | + | ||
37 | +/** | ||
38 | + * Next Objective Codec. | ||
39 | + */ | ||
40 | +public class NextObjectiveCodec extends JsonCodec<NextObjective> { | ||
41 | + | ||
42 | + private final Logger log = getLogger(getClass()); | ||
43 | + | ||
44 | + // JSON field names | ||
45 | + private static final String ID = "id"; | ||
46 | + private static final String TYPE = "type"; | ||
47 | + private static final String OPERATION = "operation"; | ||
48 | + private static final String TREATMENTS = "treatments"; | ||
49 | + private static final String META = "meta"; | ||
50 | + | ||
51 | + // messages to be printed out | ||
52 | + private static final String MISSING_MEMBER_MESSAGE = | ||
53 | + " member is required in NextObjective"; | ||
54 | + private static final String NOT_NULL_MESSAGE = | ||
55 | + "NextObjective cannot be null"; | ||
56 | + private static final String INVALID_TYPE_MESSAGE = | ||
57 | + "The requested flag {} is not defined in NextObjective."; | ||
58 | + private static final String INVALID_OP_MESSAGE = | ||
59 | + "The requested operation {} is not defined for NextObjective."; | ||
60 | + | ||
61 | + public static final String REST_APP_ID = "org.onosproject.rest"; | ||
62 | + | ||
63 | + @Override | ||
64 | + public ObjectNode encode(NextObjective nextObjective, CodecContext context) { | ||
65 | + | ||
66 | + checkNotNull(nextObjective, NOT_NULL_MESSAGE); | ||
67 | + | ||
68 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
69 | + final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class); | ||
70 | + | ||
71 | + // encode common properties | ||
72 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
73 | + ObjectNode result = och.encode(nextObjective, context); | ||
74 | + | ||
75 | + // encode id | ||
76 | + result.put(ID, nextObjective.id()); | ||
77 | + | ||
78 | + // encode type | ||
79 | + result.put(TYPE, nextObjective.type().toString()); | ||
80 | + | ||
81 | + // encode operation | ||
82 | + result.put(OPERATION, nextObjective.op().toString()); | ||
83 | + | ||
84 | + // encode treatments | ||
85 | + ArrayNode treatments = context.mapper().createArrayNode(); | ||
86 | + nextObjective.next().forEach(t -> { | ||
87 | + ObjectNode treatmentJson = trafficTreatmentCodec.encode(t, context); | ||
88 | + treatments.add(treatmentJson); | ||
89 | + }); | ||
90 | + result.set(TREATMENTS, treatments); | ||
91 | + | ||
92 | + // encode meta | ||
93 | + if (nextObjective.meta() != null) { | ||
94 | + ObjectNode trafficSelectorNode = trafficSelectorCodec.encode(nextObjective.meta(), context); | ||
95 | + result.set(META, trafficSelectorNode); | ||
96 | + } | ||
97 | + | ||
98 | + return result; | ||
99 | + } | ||
100 | + | ||
101 | + @Override | ||
102 | + public NextObjective decode(ObjectNode json, CodecContext context) { | ||
103 | + if (json == null || !json.isObject()) { | ||
104 | + return null; | ||
105 | + } | ||
106 | + | ||
107 | + CoreService coreService = context.getService(CoreService.class); | ||
108 | + | ||
109 | + final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class); | ||
110 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
111 | + | ||
112 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
113 | + | ||
114 | + DefaultNextObjective.Builder baseBuilder = DefaultNextObjective.builder(); | ||
115 | + final DefaultNextObjective.Builder builder = | ||
116 | + (DefaultNextObjective.Builder) och.decode(json, baseBuilder, context); | ||
117 | + | ||
118 | + // decode id | ||
119 | + JsonNode idJson = json.get(ID); | ||
120 | + checkNotNull(idJson); | ||
121 | + builder.withId(idJson.asInt()); | ||
122 | + | ||
123 | + // decode application id | ||
124 | + ApplicationId appId = coreService.registerApplication(REST_APP_ID); | ||
125 | + builder.fromApp(appId); | ||
126 | + | ||
127 | + // decode type | ||
128 | + String typeStr = nullIsIllegal(json.get(TYPE), TYPE + MISSING_MEMBER_MESSAGE).asText(); | ||
129 | + | ||
130 | + switch (typeStr) { | ||
131 | + case "HASHED": | ||
132 | + builder.withType(NextObjective.Type.HASHED); | ||
133 | + break; | ||
134 | + case "BROADCAST": | ||
135 | + builder.withType(NextObjective.Type.BROADCAST); | ||
136 | + break; | ||
137 | + case "FAILOVER": | ||
138 | + builder.withType(NextObjective.Type.FAILOVER); | ||
139 | + break; | ||
140 | + case "SIMPLE": | ||
141 | + builder.withType(NextObjective.Type.SIMPLE); | ||
142 | + break; | ||
143 | + default: | ||
144 | + log.warn(INVALID_TYPE_MESSAGE, typeStr); | ||
145 | + return null; | ||
146 | + } | ||
147 | + | ||
148 | + // decode treatments | ||
149 | + JsonNode treatmentsJson = json.get(TREATMENTS); | ||
150 | + checkNotNull(treatmentsJson); | ||
151 | + if (treatmentsJson != null) { | ||
152 | + IntStream.range(0, treatmentsJson.size()).forEach(i -> { | ||
153 | + ObjectNode treatmentJson = get(treatmentsJson, i); | ||
154 | + builder.addTreatment(trafficTreatmentCodec.decode(treatmentJson, context)); | ||
155 | + }); | ||
156 | + } | ||
157 | + | ||
158 | + // decode meta | ||
159 | + JsonNode metaJson = json.get(META); | ||
160 | + if (metaJson != null) { | ||
161 | + TrafficSelector trafficSelector = trafficSelectorCodec.decode((ObjectNode) metaJson, context); | ||
162 | + builder.withMeta(trafficSelector); | ||
163 | + } | ||
164 | + | ||
165 | + // decode operation | ||
166 | + String opStr = nullIsIllegal(json.get(OPERATION), OPERATION + MISSING_MEMBER_MESSAGE).asText(); | ||
167 | + NextObjective nextObjective; | ||
168 | + | ||
169 | + switch (opStr) { | ||
170 | + case "ADD": | ||
171 | + nextObjective = builder.add(); | ||
172 | + break; | ||
173 | + case "REMOVE": | ||
174 | + nextObjective = builder.remove(); | ||
175 | + break; | ||
176 | + default: | ||
177 | + log.warn(INVALID_OP_MESSAGE, opStr); | ||
178 | + return null; | ||
179 | + } | ||
180 | + | ||
181 | + return nextObjective; | ||
182 | + } | ||
183 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
19 | +import org.onosproject.codec.CodecContext; | ||
20 | +import org.onosproject.net.flowobjective.Objective; | ||
21 | + | ||
22 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
23 | + | ||
24 | +/** | ||
25 | + * Objective Codec Helper. | ||
26 | + */ | ||
27 | +public class ObjectiveCodecHelper { | ||
28 | + | ||
29 | + // JSON field names | ||
30 | + private static final String ID = "id"; | ||
31 | + private static final String APP_ID = "appId"; | ||
32 | + private static final String OPERATION = "operation"; | ||
33 | + private static final String PERMANENT = "isPermanent"; | ||
34 | + private static final String PRIORITY = "priority"; | ||
35 | + private static final String TIMEOUT = "timeout"; | ||
36 | + public static final String REST_APP_ID = "org.onosproject.rest"; | ||
37 | + | ||
38 | + public ObjectNode encode(Objective objective, CodecContext context) { | ||
39 | + checkNotNull(objective, "Objective cannot be null"); | ||
40 | + | ||
41 | + ObjectNode result = context.mapper().createObjectNode() | ||
42 | + .put(ID, objective.id()) | ||
43 | + .put(OPERATION, objective.op().toString()) | ||
44 | + .put(PERMANENT, String.valueOf(objective.permanent())) | ||
45 | + .put(PRIORITY, objective.priority()) | ||
46 | + .put(TIMEOUT, objective.timeout()); | ||
47 | + | ||
48 | + if (objective.appId() != null) { | ||
49 | + result.put(APP_ID, objective.appId().toString()); | ||
50 | + } | ||
51 | + | ||
52 | + return result; | ||
53 | + } | ||
54 | + | ||
55 | + public Objective.Builder decode(ObjectNode json, Objective.Builder builder, CodecContext context) { | ||
56 | + if (json == null || !json.isObject()) { | ||
57 | + return null; | ||
58 | + } | ||
59 | + | ||
60 | + // permanent | ||
61 | + boolean permanent = false; | ||
62 | + if (json.get(PERMANENT) != null) { | ||
63 | + permanent = json.get(PERMANENT).asBoolean(); | ||
64 | + } | ||
65 | + | ||
66 | + // timeout | ||
67 | + int timeoutInt = 0; | ||
68 | + if (json.get(TIMEOUT) != null) { | ||
69 | + timeoutInt = json.get(TIMEOUT).asInt(); | ||
70 | + } | ||
71 | + | ||
72 | + // priority | ||
73 | + int priorityInt = 0; | ||
74 | + if (json.get(PRIORITY) != null) { | ||
75 | + priorityInt = json.get(PRIORITY).asInt(); | ||
76 | + } | ||
77 | + | ||
78 | + if (permanent) { | ||
79 | + builder.makePermanent() | ||
80 | + .makeTemporary(timeoutInt) | ||
81 | + .withPriority(priorityInt); | ||
82 | + } else { | ||
83 | + builder.makeTemporary(timeoutInt) | ||
84 | + .withPriority(priorityInt); | ||
85 | + } | ||
86 | + return builder; | ||
87 | + } | ||
88 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | +import org.junit.Before; | ||
21 | +import org.junit.Test; | ||
22 | +import org.onlab.packet.VlanId; | ||
23 | +import org.onosproject.codec.JsonCodec; | ||
24 | +import org.onosproject.core.CoreService; | ||
25 | +import org.onosproject.net.flow.criteria.Criteria; | ||
26 | +import org.onosproject.net.flow.criteria.Criterion; | ||
27 | +import org.onosproject.net.flowobjective.DefaultFilteringObjective; | ||
28 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
29 | + | ||
30 | +import java.io.IOException; | ||
31 | +import java.io.InputStream; | ||
32 | + | ||
33 | +import static org.easymock.EasyMock.createMock; | ||
34 | +import static org.easymock.EasyMock.expect; | ||
35 | +import static org.easymock.EasyMock.replay; | ||
36 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
37 | +import static org.hamcrest.Matchers.is; | ||
38 | +import static org.hamcrest.Matchers.notNullValue; | ||
39 | +import static org.onosproject.codec.impl.FilteringObjectiveJsonMatcher.matchesFilteringObjective; | ||
40 | +import static org.onosproject.net.NetTestTools.APP_ID; | ||
41 | + | ||
42 | +/** | ||
43 | + * Unit tests for FilteringObjective Codec. | ||
44 | + */ | ||
45 | +public class FilteringObjectiveCodecTest { | ||
46 | + | ||
47 | + MockCodecContext context; | ||
48 | + JsonCodec<FilteringObjective> filteringObjectiveCodec; | ||
49 | + final CoreService mockCoreService = createMock(CoreService.class); | ||
50 | + | ||
51 | + /** | ||
52 | + * Sets up for each test. | ||
53 | + * Creates a context and fetches the FilteringObjective codec. | ||
54 | + */ | ||
55 | + @Before | ||
56 | + public void setUp() { | ||
57 | + context = new MockCodecContext(); | ||
58 | + filteringObjectiveCodec = context.codec(FilteringObjective.class); | ||
59 | + assertThat(filteringObjectiveCodec, notNullValue()); | ||
60 | + | ||
61 | + expect(mockCoreService.registerApplication(FilteringObjectiveCodec.REST_APP_ID)) | ||
62 | + .andReturn(APP_ID).anyTimes(); | ||
63 | + replay(mockCoreService); | ||
64 | + context.registerService(CoreService.class, mockCoreService); | ||
65 | + } | ||
66 | + | ||
67 | + /** | ||
68 | + * Tests encoding of a FilteringObjective object. | ||
69 | + */ | ||
70 | + @Test | ||
71 | + public void testFilteringObjectiveEncode() { | ||
72 | + | ||
73 | + Criterion condition1 = Criteria.matchVlanId(VlanId.ANY); | ||
74 | + Criterion condition2 = Criteria.matchEthType((short) 0x8844); | ||
75 | + | ||
76 | + FilteringObjective filteringObj = DefaultFilteringObjective.builder() | ||
77 | + .makePermanent() | ||
78 | + .permit() | ||
79 | + .fromApp(APP_ID) | ||
80 | + .withPriority(60) | ||
81 | + .addCondition(condition1) | ||
82 | + .addCondition(condition2) | ||
83 | + .add(); | ||
84 | + | ||
85 | + // TODO: need to add test case for TrafficTreatment (META in filteringObj) | ||
86 | + | ||
87 | + ObjectNode filteringObjJson = filteringObjectiveCodec.encode(filteringObj, context); | ||
88 | + assertThat(filteringObjJson, matchesFilteringObjective(filteringObj)); | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
92 | + * Test decoding of a FilteringObjective object. | ||
93 | + */ | ||
94 | + @Test | ||
95 | + public void testFilteringObjectiveDecode() throws IOException { | ||
96 | + FilteringObjective filteringObjective = getFilteringObjective("FilteringObjective.json"); | ||
97 | + | ||
98 | + assertThat(filteringObjective.type(), is(FilteringObjective.Type.PERMIT)); | ||
99 | + assertThat(filteringObjective.priority(), is(60)); | ||
100 | + assertThat(filteringObjective.timeout(), is(1)); | ||
101 | + assertThat(filteringObjective.op(), is(FilteringObjective.Operation.ADD)); | ||
102 | + assertThat(filteringObjective.permanent(), is(false)); | ||
103 | + } | ||
104 | + | ||
105 | + /** | ||
106 | + * Reads in a filteringObjective from the given resource and decodes it. | ||
107 | + * | ||
108 | + * @param resourceName resource to use to read the JSON for the rule | ||
109 | + * @return decoded filteringObjective | ||
110 | + * @throws IOException if processing the resource fails | ||
111 | + */ | ||
112 | + private FilteringObjective getFilteringObjective(String resourceName) throws IOException { | ||
113 | + InputStream jsonStream = FilteringObjectiveCodecTest.class.getResourceAsStream(resourceName); | ||
114 | + JsonNode json = context.mapper().readTree(jsonStream); | ||
115 | + assertThat(json, notNullValue()); | ||
116 | + FilteringObjective filteringObjective = filteringObjectiveCodec.decode((ObjectNode) json, context); | ||
117 | + assertThat(filteringObjective, notNullValue()); | ||
118 | + return filteringObjective; | ||
119 | + } | ||
120 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import org.hamcrest.Description; | ||
20 | +import org.hamcrest.TypeSafeDiagnosingMatcher; | ||
21 | +import org.onosproject.net.flow.criteria.Criterion; | ||
22 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
23 | + | ||
24 | +/** | ||
25 | + * Hamcrest matcher for filteringObjective. | ||
26 | + */ | ||
27 | +public final class FilteringObjectiveJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> { | ||
28 | + | ||
29 | + final FilteringObjective filteringObj; | ||
30 | + | ||
31 | + private FilteringObjectiveJsonMatcher(FilteringObjective filteringObjective) { | ||
32 | + this.filteringObj = filteringObjective; | ||
33 | + } | ||
34 | + | ||
35 | + @Override | ||
36 | + protected boolean matchesSafely(JsonNode jsonFilteringObj, Description description) { | ||
37 | + | ||
38 | + ObjectiveJsonMatcher.matchesObjective(filteringObj).matchesSafely(jsonFilteringObj); | ||
39 | + | ||
40 | + // check id | ||
41 | + int jsonId = jsonFilteringObj.get("id").asInt(); | ||
42 | + int id = filteringObj.id(); | ||
43 | + if (jsonId != id) { | ||
44 | + description.appendText("id was " + jsonId); | ||
45 | + return false; | ||
46 | + } | ||
47 | + | ||
48 | + // check type | ||
49 | + String jsonType = jsonFilteringObj.get("type").asText(); | ||
50 | + String type = filteringObj.type().toString(); | ||
51 | + if (!jsonType.equals(type)) { | ||
52 | + description.appendText("type was " + jsonType); | ||
53 | + return false; | ||
54 | + } | ||
55 | + | ||
56 | + // check size of condition array | ||
57 | + JsonNode jsonConditions = jsonFilteringObj.get("conditions"); | ||
58 | + if (jsonConditions.size() != filteringObj.conditions().size()) { | ||
59 | + description.appendText("conditions size was " + jsonConditions.size()); | ||
60 | + return false; | ||
61 | + } | ||
62 | + | ||
63 | + // check conditions | ||
64 | + for (Criterion c : filteringObj.conditions()) { | ||
65 | + boolean conditionFound = false; | ||
66 | + for (int cIndex = 0; cIndex < jsonConditions.size(); cIndex++) { | ||
67 | + CriterionJsonMatcher criterionMatcher = CriterionJsonMatcher.matchesCriterion(c); | ||
68 | + if (criterionMatcher.matches(jsonConditions.get(cIndex))) { | ||
69 | + conditionFound = true; | ||
70 | + break; | ||
71 | + } | ||
72 | + } | ||
73 | + if (!conditionFound) { | ||
74 | + description.appendText("condition not found " + c.toString()); | ||
75 | + return false; | ||
76 | + } | ||
77 | + } | ||
78 | + | ||
79 | + return true; | ||
80 | + } | ||
81 | + | ||
82 | + @Override | ||
83 | + public void describeTo(Description description) { | ||
84 | + description.appendText(filteringObj.toString()); | ||
85 | + } | ||
86 | + | ||
87 | + /** | ||
88 | + * Factory to allocate a filteringObjective matcher. | ||
89 | + * | ||
90 | + * @param filteringObj filteringObjective object we are looking for | ||
91 | + * @return matcher | ||
92 | + */ | ||
93 | + public static FilteringObjectiveJsonMatcher matchesFilteringObjective(FilteringObjective filteringObj) { | ||
94 | + return new FilteringObjectiveJsonMatcher(filteringObj); | ||
95 | + } | ||
96 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | +import org.junit.Before; | ||
21 | +import org.junit.Test; | ||
22 | +import org.onlab.packet.VlanId; | ||
23 | +import org.onosproject.codec.JsonCodec; | ||
24 | +import org.onosproject.core.CoreService; | ||
25 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
26 | +import org.onosproject.net.flow.TrafficSelector; | ||
27 | +import org.onosproject.net.flow.criteria.Criteria; | ||
28 | +import org.onosproject.net.flow.criteria.Criterion; | ||
29 | +import org.onosproject.net.flowobjective.DefaultForwardingObjective; | ||
30 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
31 | + | ||
32 | +import java.io.IOException; | ||
33 | +import java.io.InputStream; | ||
34 | + | ||
35 | +import static org.easymock.EasyMock.createMock; | ||
36 | +import static org.easymock.EasyMock.expect; | ||
37 | +import static org.easymock.EasyMock.replay; | ||
38 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
39 | +import static org.hamcrest.Matchers.is; | ||
40 | +import static org.hamcrest.Matchers.notNullValue; | ||
41 | +import static org.onosproject.codec.impl.ForwardingObjectiveJsonMatcher.matchesForwardingObjective; | ||
42 | +import static org.onosproject.net.NetTestTools.APP_ID; | ||
43 | + | ||
44 | +/** | ||
45 | + * Unit tests for ForwardingObjective Codec. | ||
46 | + */ | ||
47 | +public class ForwardingObjectiveCodecTest { | ||
48 | + | ||
49 | + MockCodecContext context; | ||
50 | + JsonCodec<ForwardingObjective> forwardingObjectiveCodec; | ||
51 | + final CoreService mockCoreService = createMock(CoreService.class); | ||
52 | + | ||
53 | + /** | ||
54 | + * Sets up for each test. | ||
55 | + * Creates a context and fetches the ForwardingObjective codec. | ||
56 | + */ | ||
57 | + @Before | ||
58 | + public void setUp() { | ||
59 | + context = new MockCodecContext(); | ||
60 | + forwardingObjectiveCodec = context.codec(ForwardingObjective.class); | ||
61 | + assertThat(forwardingObjectiveCodec, notNullValue()); | ||
62 | + | ||
63 | + expect(mockCoreService.registerApplication(ForwardingObjectiveCodec.REST_APP_ID)) | ||
64 | + .andReturn(APP_ID).anyTimes(); | ||
65 | + replay(mockCoreService); | ||
66 | + context.registerService(CoreService.class, mockCoreService); | ||
67 | + } | ||
68 | + | ||
69 | + /** | ||
70 | + * Tests encoding of a ForwardingObjective object. | ||
71 | + */ | ||
72 | + @Test | ||
73 | + public void testForwardingObjectiveEncode() { | ||
74 | + | ||
75 | + Criterion criterion1 = Criteria.matchVlanId(VlanId.ANY); | ||
76 | + Criterion criterion2 = Criteria.matchEthType((short) 0x8844); | ||
77 | + TrafficSelector selector = DefaultTrafficSelector.builder() | ||
78 | + .add(criterion1) | ||
79 | + .add(criterion2) | ||
80 | + .build(); | ||
81 | + | ||
82 | + ForwardingObjective forwardingObj = DefaultForwardingObjective.builder() | ||
83 | + .makePermanent() | ||
84 | + .fromApp(APP_ID) | ||
85 | + .withPriority(60) | ||
86 | + .withFlag(ForwardingObjective.Flag.SPECIFIC) | ||
87 | + .nextStep(1) | ||
88 | + .withSelector(selector) | ||
89 | + .add(); | ||
90 | + | ||
91 | + ObjectNode forwardingObjJson = forwardingObjectiveCodec.encode(forwardingObj, context); | ||
92 | + assertThat(forwardingObjJson, matchesForwardingObjective(forwardingObj)); | ||
93 | + } | ||
94 | + | ||
95 | + /** | ||
96 | + * Test decoding of a ForwardingObjective object. | ||
97 | + */ | ||
98 | + @Test | ||
99 | + public void testForwardingObjectiveDecode() throws IOException { | ||
100 | + ForwardingObjective forwardingObjective = getForwardingObjective("ForwardingObjective.json"); | ||
101 | + | ||
102 | + assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC)); | ||
103 | + assertThat(forwardingObjective.priority(), is(60)); | ||
104 | + assertThat(forwardingObjective.timeout(), is(1)); | ||
105 | + assertThat(forwardingObjective.op(), is(ForwardingObjective.Operation.ADD)); | ||
106 | + assertThat(forwardingObjective.permanent(), is(false)); | ||
107 | + } | ||
108 | + | ||
109 | + /** | ||
110 | + * Reads in a forwardingObjectiveJsonCodec from the given resource and decodes it. | ||
111 | + * | ||
112 | + * @param resourceName resource to use to read the JSON for the rule | ||
113 | + * @return decoded forwardingObjectiveJsonCodec | ||
114 | + * @throws IOException if processing the resource fails | ||
115 | + */ | ||
116 | + private ForwardingObjective getForwardingObjective(String resourceName) throws IOException { | ||
117 | + InputStream jsonStream = ForwardingObjectiveCodecTest.class.getResourceAsStream(resourceName); | ||
118 | + JsonNode json = context.mapper().readTree(jsonStream); | ||
119 | + assertThat(json, notNullValue()); | ||
120 | + ForwardingObjective forwardingObjective = forwardingObjectiveCodec.decode((ObjectNode) json, context); | ||
121 | + assertThat(forwardingObjective, notNullValue()); | ||
122 | + return forwardingObjective; | ||
123 | + } | ||
124 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import org.hamcrest.Description; | ||
20 | +import org.hamcrest.TypeSafeDiagnosingMatcher; | ||
21 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
22 | + | ||
23 | +/** | ||
24 | + * Hamcrest matcher for forwardingObjective. | ||
25 | + */ | ||
26 | +public final class ForwardingObjectiveJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> { | ||
27 | + | ||
28 | + final ForwardingObjective forwardingObjective; | ||
29 | + | ||
30 | + private ForwardingObjectiveJsonMatcher(ForwardingObjective forwardingObjective) { | ||
31 | + this.forwardingObjective = forwardingObjective; | ||
32 | + } | ||
33 | + | ||
34 | + @Override | ||
35 | + protected boolean matchesSafely(JsonNode jsonForwardingObj, Description description) { | ||
36 | + | ||
37 | + ObjectiveJsonMatcher.matchesObjective(forwardingObjective).matchesSafely(jsonForwardingObj); | ||
38 | + | ||
39 | + // check id | ||
40 | + int jsonId = jsonForwardingObj.get("id").asInt(); | ||
41 | + int id = forwardingObjective.id(); | ||
42 | + if (jsonId != id) { | ||
43 | + description.appendText("id was " + jsonId); | ||
44 | + return false; | ||
45 | + } | ||
46 | + | ||
47 | + // check nextId | ||
48 | + int jsonNextId = jsonForwardingObj.get("nextId").asInt(); | ||
49 | + int nextId = forwardingObjective.nextId(); | ||
50 | + if (jsonNextId != nextId) { | ||
51 | + description.appendText("nextId was " + jsonNextId); | ||
52 | + return false; | ||
53 | + } | ||
54 | + | ||
55 | + // check flag | ||
56 | + String jsonFlag = jsonForwardingObj.get("flag").asText(); | ||
57 | + String flag = forwardingObjective.flag().toString(); | ||
58 | + if (!jsonFlag.equals(flag)) { | ||
59 | + description.appendText("flag was " + jsonFlag); | ||
60 | + return false; | ||
61 | + } | ||
62 | + | ||
63 | + return true; | ||
64 | + } | ||
65 | + | ||
66 | + @Override | ||
67 | + public void describeTo(Description description) { | ||
68 | + description.appendText(forwardingObjective.toString()); | ||
69 | + } | ||
70 | + | ||
71 | + /** | ||
72 | + * Factory to allocate a forwardingObjective matcher. | ||
73 | + * | ||
74 | + * @param forwardingObjective forwardingObjective object we are looking for | ||
75 | + * @return matcher | ||
76 | + */ | ||
77 | + public static ForwardingObjectiveJsonMatcher matchesForwardingObjective(ForwardingObjective forwardingObjective) { | ||
78 | + return new ForwardingObjectiveJsonMatcher(forwardingObjective); | ||
79 | + } | ||
80 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | +import org.junit.Before; | ||
21 | +import org.junit.Test; | ||
22 | +import org.onosproject.codec.JsonCodec; | ||
23 | +import org.onosproject.core.CoreService; | ||
24 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
25 | +import org.onosproject.net.flow.TrafficTreatment; | ||
26 | +import org.onosproject.net.flowobjective.DefaultNextObjective; | ||
27 | +import org.onosproject.net.flowobjective.NextObjective; | ||
28 | + | ||
29 | +import java.io.IOException; | ||
30 | +import java.io.InputStream; | ||
31 | + | ||
32 | +import static org.easymock.EasyMock.createMock; | ||
33 | +import static org.easymock.EasyMock.expect; | ||
34 | +import static org.easymock.EasyMock.replay; | ||
35 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
36 | +import static org.hamcrest.Matchers.is; | ||
37 | +import static org.hamcrest.Matchers.notNullValue; | ||
38 | +import static org.onosproject.codec.impl.NextObjectiveJsonMatcher.matchesNextObjective; | ||
39 | +import static org.onosproject.net.NetTestTools.APP_ID; | ||
40 | + | ||
41 | +/** | ||
42 | + * Unit tests for NextObjective Codec. | ||
43 | + */ | ||
44 | +public class NextObjectiveCodecTest { | ||
45 | + | ||
46 | + MockCodecContext context; | ||
47 | + JsonCodec<NextObjective> nextObjectiveCodec; | ||
48 | + final CoreService mockCoreService = createMock(CoreService.class); | ||
49 | + | ||
50 | + /** | ||
51 | + * Sets up for each test. | ||
52 | + * Creates a context and fetches the NextObjective codec. | ||
53 | + */ | ||
54 | + @Before | ||
55 | + public void setUp() { | ||
56 | + context = new MockCodecContext(); | ||
57 | + nextObjectiveCodec = context.codec(NextObjective.class); | ||
58 | + assertThat(nextObjectiveCodec, notNullValue()); | ||
59 | + | ||
60 | + expect(mockCoreService.registerApplication(NextObjectiveCodec.REST_APP_ID)) | ||
61 | + .andReturn(APP_ID).anyTimes(); | ||
62 | + replay(mockCoreService); | ||
63 | + context.registerService(CoreService.class, mockCoreService); | ||
64 | + } | ||
65 | + | ||
66 | + /** | ||
67 | + * Tests encoding of a NextObjective object. | ||
68 | + */ | ||
69 | + @Test | ||
70 | + public void testNextObjectiveEncode() { | ||
71 | + | ||
72 | + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); | ||
73 | + | ||
74 | + NextObjective nextObj = DefaultNextObjective.builder() | ||
75 | + .makePermanent() | ||
76 | + .withType(NextObjective.Type.HASHED) | ||
77 | + .fromApp(APP_ID) | ||
78 | + .withPriority(60) | ||
79 | + .withId(5) | ||
80 | + .addTreatment(treatment) | ||
81 | + .add(); | ||
82 | + | ||
83 | + ObjectNode nextObjJson = nextObjectiveCodec.encode(nextObj, context); | ||
84 | + assertThat(nextObjJson, matchesNextObjective(nextObj)); | ||
85 | + } | ||
86 | + | ||
87 | + /** | ||
88 | + * Test decoding of a NextObjective object. | ||
89 | + */ | ||
90 | + @Test | ||
91 | + public void testNextObjectiveDecode() throws IOException { | ||
92 | + NextObjective nextObjective = getNextObjective("NextObjective.json"); | ||
93 | + | ||
94 | + assertThat(nextObjective.type(), is(NextObjective.Type.FAILOVER)); | ||
95 | + assertThat(nextObjective.op(), is(NextObjective.Operation.ADD)); | ||
96 | + } | ||
97 | + | ||
98 | + /** | ||
99 | + * Reads in a nextObjective from the given resource and decodes it. | ||
100 | + * | ||
101 | + * @param resourceName resource to use to read the JSON for the rule | ||
102 | + * @return decoded nextObjective | ||
103 | + * @throws IOException if processing the resource fails | ||
104 | + */ | ||
105 | + private NextObjective getNextObjective(String resourceName) throws IOException { | ||
106 | + InputStream jsonStream = NextObjectiveCodecTest.class.getResourceAsStream(resourceName); | ||
107 | + JsonNode json = context.mapper().readTree(jsonStream); | ||
108 | + assertThat(json, notNullValue()); | ||
109 | + NextObjective nextObjective = nextObjectiveCodec.decode((ObjectNode) json, context); | ||
110 | + assertThat(nextObjective, notNullValue()); | ||
111 | + return nextObjective; | ||
112 | + } | ||
113 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import org.hamcrest.Description; | ||
20 | +import org.hamcrest.TypeSafeDiagnosingMatcher; | ||
21 | +import org.onosproject.net.flowobjective.NextObjective; | ||
22 | + | ||
23 | +/** | ||
24 | + * Hamcrest matcher for nextObjective. | ||
25 | + */ | ||
26 | +public final class NextObjectiveJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> { | ||
27 | + | ||
28 | + final NextObjective nextObjective; | ||
29 | + | ||
30 | + private NextObjectiveJsonMatcher(NextObjective nextObjective) { | ||
31 | + this.nextObjective = nextObjective; | ||
32 | + } | ||
33 | + | ||
34 | + @Override | ||
35 | + protected boolean matchesSafely(JsonNode jsonNextObj, Description description) { | ||
36 | + ObjectiveJsonMatcher.matchesObjective(nextObjective).matchesSafely(jsonNextObj); | ||
37 | + | ||
38 | + // check id | ||
39 | + int jsonId = jsonNextObj.get("id").asInt(); | ||
40 | + int id = nextObjective.id(); | ||
41 | + if (jsonId != id) { | ||
42 | + description.appendText("id was " + jsonId); | ||
43 | + return false; | ||
44 | + } | ||
45 | + | ||
46 | + // check type | ||
47 | + String jsonType = jsonNextObj.get("type").asText(); | ||
48 | + String type = nextObjective.type().toString(); | ||
49 | + if (!jsonType.equals(type)) { | ||
50 | + description.appendText("type was " + jsonType); | ||
51 | + return false; | ||
52 | + } | ||
53 | + | ||
54 | + // check size of treatment array | ||
55 | + JsonNode jsonTreatments = jsonNextObj.get("treatments"); | ||
56 | + if (jsonTreatments.size() != nextObjective.next().size()) { | ||
57 | + description.appendText("treatments size was " + jsonTreatments.size()); | ||
58 | + return false; | ||
59 | + } | ||
60 | + | ||
61 | + // TODO: need to check the content of treatment collection | ||
62 | + | ||
63 | + // TODO: need to check the content of selector instance | ||
64 | + | ||
65 | + return true; | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + public void describeTo(Description description) { | ||
70 | + description.appendText(nextObjective.toString()); | ||
71 | + } | ||
72 | + | ||
73 | + /** | ||
74 | + * Factory to allocate a nextObjective matcher. | ||
75 | + * | ||
76 | + * @param nextObjective nextObjective object we are looking for | ||
77 | + * @return matcher | ||
78 | + */ | ||
79 | + public static NextObjectiveJsonMatcher matchesNextObjective(NextObjective nextObjective) { | ||
80 | + return new NextObjectiveJsonMatcher(nextObjective); | ||
81 | + } | ||
82 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.codec.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import org.onosproject.net.flowobjective.Objective; | ||
20 | + | ||
21 | +/** | ||
22 | + * Hamcrest matcher for instructions. | ||
23 | + */ | ||
24 | +public final class ObjectiveJsonMatcher { | ||
25 | + | ||
26 | + final Objective objective; | ||
27 | + | ||
28 | + private ObjectiveJsonMatcher(Objective objective) { | ||
29 | + this.objective = objective; | ||
30 | + } | ||
31 | + | ||
32 | + protected boolean matchesSafely(JsonNode jsonObjective) { | ||
33 | + | ||
34 | + // check operation | ||
35 | + String jsonOp = jsonObjective.get("operation").asText(); | ||
36 | + String op = objective.op().toString(); | ||
37 | + if (!jsonOp.equals(op)) { | ||
38 | + return false; | ||
39 | + } | ||
40 | + | ||
41 | + // check permanent | ||
42 | + boolean jsonPermanent = jsonObjective.get("isPermanent").asBoolean(); | ||
43 | + boolean permanent = objective.permanent(); | ||
44 | + if (jsonPermanent != permanent) { | ||
45 | + return false; | ||
46 | + } | ||
47 | + | ||
48 | + // check priority | ||
49 | + int jsonPriority = jsonObjective.get("priority").asInt(); | ||
50 | + int priority = objective.priority(); | ||
51 | + if (jsonPriority != priority) { | ||
52 | + return false; | ||
53 | + } | ||
54 | + | ||
55 | + // check timeout | ||
56 | + int jsonTimeout = jsonObjective.get("timeout").asInt(); | ||
57 | + int timeout = objective.timeout(); | ||
58 | + if (jsonTimeout != timeout) { | ||
59 | + return false; | ||
60 | + } | ||
61 | + | ||
62 | + return true; | ||
63 | + } | ||
64 | + | ||
65 | + /** | ||
66 | + * Factory to allocate a ObjectiveJsonMatcher. | ||
67 | + * | ||
68 | + * @param objective objective object we are looking for | ||
69 | + * @return matcher | ||
70 | + */ | ||
71 | + public static ObjectiveJsonMatcher matchesObjective(Objective objective) { | ||
72 | + return new ObjectiveJsonMatcher(objective); | ||
73 | + } | ||
74 | +} |
1 | +{ | ||
2 | + "priority": 60, | ||
3 | + "isPermanent": "false", | ||
4 | + "timeout": 1, | ||
5 | + "type": "PERMIT", | ||
6 | + "operation": "ADD", | ||
7 | + "conditions": [ | ||
8 | + { | ||
9 | + "type": "IN_PORT", | ||
10 | + "port": 23 | ||
11 | + } | ||
12 | + ], | ||
13 | + "meta": { | ||
14 | + "instructions": [ | ||
15 | + { | ||
16 | + "type": "OUTPUT", | ||
17 | + "port": -3 | ||
18 | + }, | ||
19 | + { | ||
20 | + "type": "DROP" | ||
21 | + } | ||
22 | + ], | ||
23 | + "deferred": [] | ||
24 | + } | ||
25 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{ | ||
2 | + "priority": 60, | ||
3 | + "isPermanent": "false", | ||
4 | + "timeout": 1, | ||
5 | + "flag": "SPECIFIC", | ||
6 | + "operation": "ADD", | ||
7 | + "selector": { | ||
8 | + "criteria": [ | ||
9 | + { | ||
10 | + "type": "ETH_TYPE", | ||
11 | + "ethType": "0x806" | ||
12 | + } | ||
13 | + ] | ||
14 | + }, | ||
15 | + "treatment": | ||
16 | + { | ||
17 | + "instructions": | ||
18 | + [ | ||
19 | + {"type":"OUTPUT","port":-3}, | ||
20 | + {"type":"DROP"} | ||
21 | + ], | ||
22 | + "deferred":[] | ||
23 | + } | ||
24 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{ | ||
2 | + "id": 1, | ||
3 | + "type": "FAILOVER", | ||
4 | + "operation": "ADD", | ||
5 | + "treatments": [ | ||
6 | + { | ||
7 | + "instructions": [ | ||
8 | + { | ||
9 | + "type": "OUTPUT", | ||
10 | + "port": -3 | ||
11 | + }, | ||
12 | + { | ||
13 | + "type": "DROP" | ||
14 | + } | ||
15 | + ], | ||
16 | + "deferred": [] | ||
17 | + } | ||
18 | + ], | ||
19 | + "meta": { | ||
20 | + "criteria": [ | ||
21 | + { | ||
22 | + "type": "IN_PORT", | ||
23 | + "port": 23 | ||
24 | + } | ||
25 | + ] | ||
26 | + } | ||
27 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment