Bump upstreams for Silicon
[openflowplugin.git] / openflowplugin / src / test / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / flow / FlowConvertorTest.java
1 /*
2  * Copyright (c) 2014 Pantheon Technologies s.r.o. 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
9 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow;
10
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.Optional;
15 import org.junit.Assert;
16 import org.junit.Before;
17 import org.junit.Test;
18 import org.opendaylight.openflowplugin.api.OFConstants;
19 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
20 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.clear.actions._case.ClearActionsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.MeterBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActionsBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCase;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.MeterCase;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCase;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
70 import org.opendaylight.yangtools.yang.binding.AbstractAugmentable;
71 import org.opendaylight.yangtools.yang.common.Uint16;
72 import org.opendaylight.yangtools.yang.common.Uint32;
73 import org.opendaylight.yangtools.yang.common.Uint64;
74 import org.opendaylight.yangtools.yang.common.Uint8;
75
76 /**
77  * Unit tests for flow conversion.
78  *
79  * @author michal.polkorab
80  */
81 public class FlowConvertorTest {
82     private ConvertorManager convertorManager;
83
84     @Before
85     public void setUp() {
86         convertorManager = ConvertorManagerFactory.createDefaultManager();
87     }
88
89     /**
90      * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
91      */
92     @Test
93     public void test() {
94         RemoveFlowInputBuilder flowBuilder = new RemoveFlowInputBuilder();
95         flowBuilder.setBarrier(false);
96         flowBuilder.setCookie(new FlowCookie(Uint64.valueOf(4)));
97         flowBuilder.setCookieMask(new FlowCookie(Uint64.valueOf(5)));
98         flowBuilder.setTableId(Uint8.valueOf(6));
99         flowBuilder.setStrict(true);
100         flowBuilder.setIdleTimeout(Uint16.valueOf(50));
101         flowBuilder.setHardTimeout(Uint16.valueOf(500));
102         flowBuilder.setPriority(Uint16.valueOf(40));
103         flowBuilder.setBufferId(Uint32.valueOf(18));
104         flowBuilder.setOutPort(Uint64.valueOf(65535));
105         flowBuilder.setOutGroup(Uint32.valueOf(5000));
106         flowBuilder.setFlags(null);
107         flowBuilder.setMatch(null);
108         RemoveFlowInput flow = flowBuilder.build();
109
110         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
111         data.setDatapathId(Uint64.valueOf(42));
112
113         List<FlowModInputBuilder> flowMod = convert(flow, data);
114
115         Assert.assertEquals("Wrong version", 4, flowMod.get(0).getVersion().intValue());
116         Assert.assertEquals("Wrong cookie", 4, flowMod.get(0).getCookie().intValue());
117         Assert.assertEquals("Wrong cookie mask", 5, flowMod.get(0).getCookieMask().intValue());
118         Assert.assertEquals("Wrong table id", 6, flowMod.get(0).getTableId().getValue().intValue());
119         Assert.assertEquals("Wrong command", FlowModCommand.OFPFCDELETESTRICT, flowMod.get(0).getCommand());
120         Assert.assertEquals("Wrong idle timeout", 50, flowMod.get(0).getIdleTimeout().intValue());
121         Assert.assertEquals("Wrong hard timeout", 500, flowMod.get(0).getHardTimeout().intValue());
122         Assert.assertEquals("Wrong priority", 40, flowMod.get(0).getPriority().intValue());
123         Assert.assertEquals("Wrong buffer id", 18, flowMod.get(0).getBufferId().intValue());
124         Assert.assertEquals("Wrong out port", 65535, flowMod.get(0).getOutPort().getValue().intValue());
125         Assert.assertEquals("Wrong out group", 5000, flowMod.get(0).getOutGroup().intValue());
126         Assert.assertEquals("Wrong flags", new FlowModFlags(false, false, false, false, false),
127                 flowMod.get(0).getFlags());
128         Assert.assertEquals("Wrong match",
129                 "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType",
130                 flowMod.get(0).getMatch().getType().getName());
131         Assert.assertEquals("Wrong match entries size", 0, flowMod.get(0).getMatch().nonnullMatchEntry().size());
132     }
133
134     /**
135      * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
136      */
137     @Test
138     public void testOnlyModifyStrictCommand() {
139         UpdatedFlowBuilder flowBuilder = new UpdatedFlowBuilder();
140         flowBuilder.setStrict(true);
141         UpdatedFlow flow = flowBuilder.build();
142
143         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
144         data.setDatapathId(Uint64.valueOf(42));
145
146         List<FlowModInputBuilder> flowMod = convert(flow, data);
147
148         Assert.assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
149         Assert.assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
150     }
151
152     /**
153      * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
154      */
155     @Test
156     public void testInstructionsTranslation() {
157         InstructionBuilder instructionBuilder = new InstructionBuilder();
158         GoToTableCaseBuilder goToCaseBuilder = new GoToTableCaseBuilder();
159         GoToTableBuilder goToBuilder = new GoToTableBuilder();
160         goToBuilder.setTableId(Uint8.ONE);
161         goToCaseBuilder.setGoToTable(goToBuilder.build());
162         instructionBuilder.setInstruction(goToCaseBuilder.build());
163         instructionBuilder.setOrder(0);
164
165         List<Instruction> instructions = new ArrayList<>();
166         instructions.add(instructionBuilder.build());
167         instructionBuilder = new InstructionBuilder();
168         WriteMetadataCaseBuilder metaCaseBuilder = new WriteMetadataCaseBuilder();
169         WriteMetadataBuilder metaBuilder = new WriteMetadataBuilder();
170         metaBuilder.setMetadata(Uint64.valueOf(2));
171         metaBuilder.setMetadataMask(Uint64.valueOf(3));
172         metaCaseBuilder.setWriteMetadata(metaBuilder.build());
173         instructionBuilder.setInstruction(metaCaseBuilder.build());
174         instructionBuilder.setOrder(1);
175         instructions.add(instructionBuilder.build());
176         instructionBuilder = new InstructionBuilder();
177         WriteActionsCaseBuilder writeCaseBuilder = new WriteActionsCaseBuilder();
178         WriteActionsBuilder writeBuilder = new WriteActionsBuilder();
179         List<Action> actions = new ArrayList<>();
180         writeBuilder.setAction(actions);
181         writeCaseBuilder.setWriteActions(writeBuilder.build());
182         instructionBuilder.setInstruction(writeCaseBuilder.build());
183         instructionBuilder.setOrder(2);
184         instructions.add(instructionBuilder.build());
185         instructionBuilder = new InstructionBuilder();
186         ApplyActionsCaseBuilder applyCaseBuilder = new ApplyActionsCaseBuilder();
187         ApplyActionsBuilder applyBuilder = new ApplyActionsBuilder();
188         actions = new ArrayList<>();
189         applyBuilder.setAction(actions);
190         applyCaseBuilder.setApplyActions(applyBuilder.build());
191         instructionBuilder.setInstruction(applyCaseBuilder.build());
192         instructionBuilder.setOrder(3);
193         instructions.add(instructionBuilder.build());
194         instructionBuilder = new InstructionBuilder();
195         ClearActionsCaseBuilder clearCaseBuilder = new ClearActionsCaseBuilder();
196         ClearActionsBuilder clearBuilder = new ClearActionsBuilder();
197         actions = new ArrayList<>();
198         clearBuilder.setAction(actions);
199         clearCaseBuilder.setClearActions(clearBuilder.build());
200         instructionBuilder.setInstruction(clearCaseBuilder.build());
201         instructionBuilder.setOrder(4);
202         instructions.add(instructionBuilder.build());
203         instructionBuilder = new InstructionBuilder();
204         MeterCaseBuilder meterCaseBuilder = new MeterCaseBuilder();
205         MeterBuilder meterBuilder = new MeterBuilder();
206         meterBuilder.setMeterId(new MeterId(Uint32.valueOf(5)));
207         meterCaseBuilder.setMeter(meterBuilder.build());
208         instructionBuilder.setInstruction(meterCaseBuilder.build());
209         instructionBuilder.setOrder(5);
210         instructions.add(instructionBuilder.build());
211
212         InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
213         instructionsBuilder.setInstruction(instructions);
214
215         AddFlowInputBuilder flowBuilder = new AddFlowInputBuilder();
216         flowBuilder.setInstructions(instructionsBuilder.build());
217         AddFlowInput flow = flowBuilder.build();
218
219         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
220         data.setDatapathId(Uint64.valueOf(42));
221         List<FlowModInputBuilder> flowMod = convert(flow, data);
222
223         Assert.assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
224         Assert.assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
225         Assert.assertEquals("Wrong instructions size", 6, flowMod.get(0).getInstruction().size());
226         org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions
227             .grouping.Instruction instruction = flowMod.get(0).getInstruction().get(0);
228         Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
229                 + ".instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCase",
230                 instruction.getInstructionChoice().implementedInterface().getName());
231         GotoTableCase gotoTableCase = (GotoTableCase) instruction.getInstructionChoice();
232         Assert.assertEquals("Wrong table id", 1, gotoTableCase.getGotoTable().getTableId().intValue());
233         instruction = flowMod.get(0).getInstruction().get(1);
234         Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
235                 + ".instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCase",
236                 instruction.getInstructionChoice().implementedInterface().getName());
237         WriteMetadataCase writeMetadataCase = (WriteMetadataCase) instruction.getInstructionChoice();
238         Assert.assertArrayEquals("Wrong metadata", new byte[]{0, 0, 0, 0, 0, 0, 0, 2},
239                 writeMetadataCase.getWriteMetadata().getMetadata());
240         Assert.assertArrayEquals("Wrong metadata mask", new byte[]{0, 0, 0, 0, 0, 0, 0, 3},
241                 writeMetadataCase.getWriteMetadata().getMetadataMask());
242
243         instruction = flowMod.get(0).getInstruction().get(2);
244         Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
245                 + ".instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCase",
246                 instruction.getInstructionChoice().implementedInterface().getName());
247         WriteActionsCase writeActionsCase = (WriteActionsCase) instruction.getInstructionChoice();
248         Assert.assertEquals("Wrong actions size", 0, writeActionsCase.getWriteActions().nonnullAction().size());
249         instruction = flowMod.get(0).getInstruction().get(3);
250         Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
251                 + ".instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCase",
252                 instruction.getInstructionChoice().implementedInterface().getName());
253         ApplyActionsCase applyActionsCase =  (ApplyActionsCase) instruction.getInstructionChoice();
254         Assert.assertEquals("Wrong actions size", 0, applyActionsCase.getApplyActions().nonnullAction().size());
255         instruction = flowMod.get(0).getInstruction().get(4);
256         Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
257                 + ".instruction.rev130731.instruction.grouping.instruction.choice.ClearActionsCase",
258                 instruction.getInstructionChoice().implementedInterface().getName());
259         instruction = flowMod.get(0).getInstruction().get(5);
260         Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
261                 + ".instruction.rev130731.instruction.grouping.instruction.choice.MeterCase",
262                 instruction.getInstructionChoice().implementedInterface().getName());
263         MeterCase meterCase = (MeterCase) instruction.getInstructionChoice();
264         Assert.assertEquals("Wrong meter id", 5, meterCase.getMeter().getMeterId().intValue());
265     }
266
267     @Test
268     public void testCloneAndAugmentFlowWithSetVlanId() {
269         MockFlow mockFlow = new MockFlow();
270         Action action1 = createAction(
271                 new SetVlanIdActionCaseBuilder().setSetVlanIdAction(
272                         new SetVlanIdActionBuilder().setVlanId(new VlanId(Uint16.TEN)).build())
273                         .build(),
274                 0);
275
276         mockFlow.setMatch(new MatchBuilder().setEthernetMatch(createEthernetMatch()).build());
277         mockFlow.setInstructions(toApplyInstruction(Collections.singletonList(action1)));
278
279         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
280         data.setDatapathId(Uint64.ONE);
281
282         List<FlowModInputBuilder> flowModInputBuilders = convert(mockFlow, data);
283
284         Assert.assertEquals(2, flowModInputBuilders.size());
285
286     }
287
288     private List<FlowModInputBuilder> convert(final Flow flow, final VersionDatapathIdConvertorData data) {
289         Optional<List<FlowModInputBuilder>> flowModOptional = convertorManager.convert(flow, data);
290         Assert.assertTrue("Flow convertor not found", flowModOptional.isPresent());
291         return flowModOptional.get();
292     }
293
294     private static Action createAction(
295             final org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionCase,
296             final int order) {
297         Action action = new ActionBuilder().setOrder(order).setAction(actionCase).build();
298         return action;
299     }
300
301     private static EthernetMatch createEthernetMatch() {
302         return new EthernetMatchBuilder()
303                 .setEthernetType(new EthernetTypeBuilder().setType(new EtherType(Uint32.valueOf(33024))).build())
304                 .build();
305     }
306
307     private static Instructions toApplyInstruction(
308             final List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list
309                 .Action> actions) {
310         return new InstructionsBuilder().setInstruction(Collections.singletonList(new InstructionBuilder().setOrder(0)
311                 .setInstruction(new ApplyActionsCaseBuilder()
312                         .setApplyActions(new ApplyActionsBuilder().setAction(actions).build()).build())
313                 .build())).build();
314     }
315
316     private static class MockFlow extends AbstractAugmentable<AddFlowInput> implements AddFlowInput {
317         private Instructions instructions;
318         private Match match;
319
320         public void setInstructions(final Instructions instructions) {
321             this.instructions = instructions;
322         }
323
324         public void setMatch(final Match match) {
325             this.match = match;
326         }
327
328         @Override
329         public FlowRef getFlowRef() {
330             return null;
331         }
332
333         @Override
334         public FlowTableRef getFlowTable() {
335             return null;
336         }
337
338         @Override
339         public Match getMatch() {
340             return match;
341         }
342
343         @Override
344         public Instructions getInstructions() {
345             return instructions;
346         }
347
348         @Override
349         public String getContainerName() {
350             return null;
351         }
352
353         @Override
354         public FlowCookie getCookieMask() {
355             return null;
356         }
357
358         @Override
359         public Uint32 getBufferId() {
360             return null;
361         }
362
363         @Override
364         public Uint64 getOutPort() {
365             return null;
366         }
367
368         @Override
369         public Uint32 getOutGroup() {
370             return null;
371         }
372
373         @Override
374         public org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags getFlags() {
375             return null;
376         }
377
378         @Override
379         public String getFlowName() {
380             return null;
381         }
382
383         @Override
384         public Boolean isInstallHw() {
385             return null;
386         }
387
388         @Override
389         public Boolean isBarrier() {
390             return null;
391         }
392
393         @Override
394         public Boolean isStrict() {
395             return null;
396         }
397
398         @Override
399         public Uint16 getPriority() {
400             return null;
401         }
402
403         @Override
404         public Uint16 getIdleTimeout() {
405             return null;
406         }
407
408         @Override
409         public Uint16 getHardTimeout() {
410             return null;
411         }
412
413         @Override
414         public FlowCookie getCookie() {
415             return null;
416         }
417
418         @Override
419         public Uint8 getTableId() {
420             return null;
421         }
422
423         @Override
424         public NodeRef getNode() {
425             return null;
426         }
427
428         @Override
429         public Uri getTransactionUri() {
430             return null;
431         }
432     }
433 }