summaryrefslogtreecommitdiffstats
path: root/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor')
-rw-r--r--lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/LocatorDumpExecutorTest.java105
-rw-r--r--lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/LocatorSetsDumpExecutorTest.java95
-rw-r--r--lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/MapResolversDumpExecutorTest.java76
-rw-r--r--lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/MappingsDumpExecutorTest.java121
-rw-r--r--lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/VniTableDumpExecutorTest.java76
5 files changed, 473 insertions, 0 deletions
diff --git a/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/LocatorDumpExecutorTest.java b/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/LocatorDumpExecutorTest.java
new file mode 100644
index 000000000..efa655bf1
--- /dev/null
+++ b/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/LocatorDumpExecutorTest.java
@@ -0,0 +1,105 @@
+package io.fd.honeycomb.lisp.translate.read.dump.executor;
+
+
+import static io.fd.honeycomb.lisp.translate.read.dump.executor.params.LocatorDumpParams.LocatorDumpParamsBuilder;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.collect.ImmutableList;
+import io.fd.honeycomb.lisp.translate.read.dump.executor.params.LocatorDumpParams;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.DumpExecutionFailedException;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.i.DumpCallFailedException;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.i.DumpTimeoutException;
+import io.fd.honeycomb.vpp.test.read.JvppDumpExecutorTest;
+import java.util.concurrent.TimeoutException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mockito;
+import org.openvpp.jvpp.core.dto.LispLocatorDetails;
+import org.openvpp.jvpp.core.dto.LispLocatorDetailsReplyDump;
+import org.openvpp.jvpp.core.dto.LispLocatorDump;
+
+
+public class LocatorDumpExecutorTest extends JvppDumpExecutorTest<LocatorDumpExecutor> {
+
+ @Captor
+ private ArgumentCaptor<LispLocatorDump> requestCaptor;
+
+ private LispLocatorDetailsReplyDump validDump;
+
+ @Before
+ public void init() {
+ validDump = new LispLocatorDetailsReplyDump();
+ LispLocatorDetails detail = new LispLocatorDetails();
+
+ detail.swIfIndex = 1;
+ detail.priority = 2;
+ detail.local = 1;
+ detail.weight = 3;
+ detail.isIpv6 = 0;
+ detail.context = 8;
+ detail.ipAddress = new byte[]{-64, -88, 4, 2};
+
+ validDump.lispLocatorDetails = ImmutableList.of(detail);
+ }
+
+ @Test
+ public void testExecuteDumpTimeout() throws Exception {
+ doThrowTimeoutExceptionWhen().lispLocatorDump(Mockito.any());
+ try {
+ getExecutor().executeDump(new LocatorDumpParamsBuilder().build());
+ } catch (Exception e) {
+ assertTrue(e instanceof DumpTimeoutException);
+ assertTrue(e.getCause() instanceof TimeoutException);
+ return;
+ }
+ fail("Test should have thrown exception");
+ }
+
+ @Test(expected = DumpCallFailedException.class)
+ public void testExecuteDumpHalted() throws DumpExecutionFailedException {
+ doThrowFailExceptionWhen().lispLocatorDump(Mockito.any());
+ getExecutor().executeDump(new LocatorDumpParamsBuilder().build());
+ }
+
+ @Test
+ public void testExecuteDump() throws DumpExecutionFailedException {
+ doReturnResponseWhen(validDump).lispLocatorDump(Mockito.any());
+
+ final LocatorDumpParams params = new LocatorDumpParamsBuilder().setLocatorSetIndex(5).build();
+
+ final LispLocatorDetailsReplyDump reply = getExecutor().executeDump(params);
+ verify(api, times(1)).lispLocatorDump(requestCaptor.capture());
+
+ final LispLocatorDump request = requestCaptor.getValue();
+
+ //check passed params
+ assertNotNull(request);
+ assertEquals(5, request.lsIndex);
+
+ //check result
+ assertNotNull(reply);
+ assertEquals(1, reply.lispLocatorDetails.size());
+
+ final LispLocatorDetails details = reply.lispLocatorDetails.get(0);
+ assertEquals(1, details.swIfIndex);
+ assertEquals(2, details.priority);
+ assertEquals(1, details.local);
+ assertEquals(3, details.weight);
+ assertEquals(0, details.isIpv6);
+ assertEquals(8, details.context);
+ assertArrayEquals(new byte[]{-64, -88, 4, 2}, details.ipAddress);
+ }
+
+ @Override
+ protected LocatorDumpExecutor initExecutor() {
+ return new LocatorDumpExecutor(api);
+ }
+} \ No newline at end of file
diff --git a/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/LocatorSetsDumpExecutorTest.java b/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/LocatorSetsDumpExecutorTest.java
new file mode 100644
index 000000000..5daf77a3d
--- /dev/null
+++ b/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/LocatorSetsDumpExecutorTest.java
@@ -0,0 +1,95 @@
+package io.fd.honeycomb.lisp.translate.read.dump.executor;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.collect.ImmutableList;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.DumpExecutionFailedException;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.i.DumpCallFailedException;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.i.DumpTimeoutException;
+import io.fd.honeycomb.vpp.test.read.JvppDumpExecutorTest;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeoutException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.openvpp.jvpp.core.dto.LispLocatorSetDetails;
+import org.openvpp.jvpp.core.dto.LispLocatorSetDetailsReplyDump;
+import org.openvpp.jvpp.core.dto.LispLocatorSetDump;
+
+
+public class LocatorSetsDumpExecutorTest extends JvppDumpExecutorTest<LocatorSetsDumpExecutor> {
+
+ public static final byte[] LOCATOR_SET_NAME_BYTES = "loc-set".getBytes(StandardCharsets.UTF_8);
+
+ private LispLocatorSetDetailsReplyDump validDump;
+
+ @Captor
+ private ArgumentCaptor<LispLocatorSetDump> requestCaptor;
+
+ @Before
+ public void init() {
+ validDump = new LispLocatorSetDetailsReplyDump();
+ LispLocatorSetDetails detail = new LispLocatorSetDetails();
+ detail.lsIndex = 2;
+ detail.lsName = LOCATOR_SET_NAME_BYTES;
+ detail.context = 4;
+
+ validDump.lispLocatorSetDetails = ImmutableList.of(detail);
+ }
+
+ @Test
+ public void testExecuteDumpTimeout() throws Exception {
+ doThrowTimeoutExceptionWhen().lispLocatorSetDump(any());
+ try {
+ getExecutor().executeDump(EntityDumpExecutor.NO_PARAMS);
+ } catch (Exception e) {
+ assertTrue(e instanceof DumpTimeoutException);
+ assertTrue(e.getCause() instanceof TimeoutException);
+ return;
+ }
+ fail("Test should have thrown exception");
+ }
+
+ @Test(expected = DumpCallFailedException.class)
+ public void testExecuteDumpHalted() throws DumpExecutionFailedException {
+ doThrowFailExceptionWhen().lispLocatorSetDump(any());
+ getExecutor().executeDump(EntityDumpExecutor.NO_PARAMS);
+ }
+
+ @Test
+ public void testExecuteDump() throws DumpExecutionFailedException {
+ doReturnResponseWhen(validDump).lispLocatorSetDump(any());
+
+ final LispLocatorSetDetailsReplyDump replyDump = getExecutor().executeDump(EntityDumpExecutor.NO_PARAMS);
+ verify(api, times(1)).lispLocatorSetDump(requestCaptor.capture());
+
+ final LispLocatorSetDump request = requestCaptor.getValue();
+
+ assertNotNull(request);
+ assertEquals(1, request.filter);
+
+ assertNotNull(replyDump);
+ assertNotNull(replyDump.lispLocatorSetDetails);
+ assertEquals(1, replyDump.lispLocatorSetDetails.size());
+ final LispLocatorSetDetails detail = replyDump.lispLocatorSetDetails.get(0);
+
+ assertNotNull(detail);
+ assertEquals(4, detail.context);
+ assertEquals(2, detail.lsIndex);
+ assertEquals(LOCATOR_SET_NAME_BYTES, detail.lsName);
+ }
+
+ @Override
+ protected LocatorSetsDumpExecutor initExecutor() {
+ return new LocatorSetsDumpExecutor(api);
+ }
+} \ No newline at end of file
diff --git a/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/MapResolversDumpExecutorTest.java b/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/MapResolversDumpExecutorTest.java
new file mode 100644
index 000000000..446300365
--- /dev/null
+++ b/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/MapResolversDumpExecutorTest.java
@@ -0,0 +1,76 @@
+package io.fd.honeycomb.lisp.translate.read.dump.executor;
+
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableList;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.DumpExecutionFailedException;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.i.DumpCallFailedException;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.i.DumpTimeoutException;
+import io.fd.honeycomb.vpp.test.read.JvppDumpExecutorTest;
+import java.util.concurrent.TimeoutException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.openvpp.jvpp.core.dto.LispMapResolverDetails;
+import org.openvpp.jvpp.core.dto.LispMapResolverDetailsReplyDump;
+
+
+public class MapResolversDumpExecutorTest extends JvppDumpExecutorTest<MapResolversDumpExecutor> {
+
+ private LispMapResolverDetailsReplyDump validDump;
+
+ @Before
+ public void init() {
+ validDump = new LispMapResolverDetailsReplyDump();
+ final LispMapResolverDetails details = new LispMapResolverDetails();
+ details.isIpv6 = 0;
+ details.ipAddress = new byte[]{-64, -88, 5, 4};
+ details.context = 7;
+
+ validDump.lispMapResolverDetails = ImmutableList.of(details);
+ }
+
+ @Test
+ public void testExecuteDumpTimeout() throws Exception {
+ doThrowTimeoutExceptionWhen().lispMapResolverDump(Mockito.any());
+ try {
+ getExecutor().executeDump(EntityDumpExecutor.NO_PARAMS);
+ } catch (Exception e) {
+ assertTrue(e instanceof DumpTimeoutException);
+ assertTrue(e.getCause() instanceof TimeoutException);
+ return;
+ }
+ fail("Test should have thrown exception");
+ }
+
+ @Test(expected = DumpCallFailedException.class)
+ public void testExecuteDumpHalted() throws DumpExecutionFailedException {
+ doThrowFailExceptionWhen().lispMapResolverDump(Mockito.any());
+ getExecutor().executeDump(EntityDumpExecutor.NO_PARAMS);
+ }
+
+ @Test
+ public void testExecuteDump() throws DumpExecutionFailedException {
+ doReturnResponseWhen(validDump).lispMapResolverDump(Mockito.any());
+ final LispMapResolverDetailsReplyDump reply = getExecutor().executeDump(EntityDumpExecutor.NO_PARAMS);
+
+ assertNotNull(reply);
+ assertEquals(1, reply.lispMapResolverDetails.size());
+
+ final LispMapResolverDetails detail = reply.lispMapResolverDetails.get(0);
+ assertEquals(7, detail.context);
+ assertEquals(0, detail.isIpv6);
+ assertArrayEquals(new byte[]{-64, -88, 5, 4}, detail.ipAddress);
+ }
+
+ @Override
+ protected MapResolversDumpExecutor initExecutor() {
+ return new MapResolversDumpExecutor(api);
+ }
+} \ No newline at end of file
diff --git a/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/MappingsDumpExecutorTest.java b/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/MappingsDumpExecutorTest.java
new file mode 100644
index 000000000..85b22fa7e
--- /dev/null
+++ b/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/MappingsDumpExecutorTest.java
@@ -0,0 +1,121 @@
+package io.fd.honeycomb.lisp.translate.read.dump.executor;
+
+import static io.fd.honeycomb.lisp.translate.read.dump.executor.params.MappingsDumpParams.EidType;
+import static io.fd.honeycomb.lisp.translate.read.dump.executor.params.MappingsDumpParams.FilterType;
+import static io.fd.honeycomb.lisp.translate.read.dump.executor.params.MappingsDumpParams.MappingsDumpParamsBuilder;
+import static io.fd.honeycomb.lisp.translate.read.dump.executor.params.MappingsDumpParams.QuantityType;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.collect.ImmutableList;
+import io.fd.honeycomb.lisp.translate.read.dump.executor.params.MappingsDumpParams;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.DumpExecutionFailedException;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.i.DumpCallFailedException;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.i.DumpTimeoutException;
+import io.fd.honeycomb.vpp.test.read.JvppDumpExecutorTest;
+import java.util.concurrent.TimeoutException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.openvpp.jvpp.core.dto.LispEidTableDetails;
+import org.openvpp.jvpp.core.dto.LispEidTableDetailsReplyDump;
+import org.openvpp.jvpp.core.dto.LispEidTableDump;
+
+public class MappingsDumpExecutorTest extends JvppDumpExecutorTest<MappingsDumpExecutor> {
+
+ private static final byte[] EID = {-64, -88, 2, 1};
+
+ @Captor
+ private ArgumentCaptor<LispEidTableDump> requestCaptor;
+
+ private LispEidTableDetailsReplyDump validDump;
+ private MappingsDumpParams emptyParams;
+ private MappingsDumpParams validParams;
+
+ @Before
+ public void init() {
+ validDump = new LispEidTableDetailsReplyDump();
+
+ LispEidTableDetails detail = new LispEidTableDetails();
+ detail.action = 0;
+ detail.authoritative = 1;
+ detail.context = 4;
+ detail.eid = new byte[]{-64, -88, 2, 1};
+ detail.eidPrefixLen = 32;
+ detail.isLocal = 1;
+ detail.locatorSetIndex = 2;
+ detail.ttl = 7;
+ detail.vni = 2;
+
+ validDump.lispEidTableDetails = ImmutableList.of(detail);
+
+ emptyParams = MappingsDumpParamsBuilder.newInstance().build();
+ validParams =
+ MappingsDumpParamsBuilder.newInstance().setVni(2).setPrefixLength((byte) 32).setEidSet(QuantityType.ALL)
+ .setEid(EID)
+ .setEidType(EidType.IPV4).setFilter(FilterType.LOCAL).build();
+ }
+
+ @Test
+ public void testExecuteDumpTimeout() throws Exception {
+ doThrowTimeoutExceptionWhen().lispEidTableDump(any());
+ try {
+ getExecutor().executeDump(emptyParams);
+ } catch (Exception e) {
+ assertTrue(e instanceof DumpTimeoutException);
+ assertTrue(e.getCause() instanceof TimeoutException);
+ return;
+ }
+ fail("Test should have thrown exception");
+ }
+
+ @Test(expected = DumpCallFailedException.class)
+ public void testExecuteDumpHalted() throws DumpExecutionFailedException {
+ doThrowFailExceptionWhen().lispEidTableDump(any());
+ getExecutor().executeDump(emptyParams);
+ }
+
+ @Test
+ public void testExecuteDump() throws DumpExecutionFailedException {
+ doReturnResponseWhen(validDump).lispEidTableDump(any());
+ final LispEidTableDetailsReplyDump reply = getExecutor().executeDump(validParams);
+ verify(api, times(1)).lispEidTableDump(requestCaptor.capture());
+
+ final LispEidTableDump request = requestCaptor.getValue();
+ assertNotNull(request);
+ assertEquals(2, request.vni);
+ assertEquals(QuantityType.ALL.getValue(), request.eidSet);
+ assertArrayEquals(EID, request.eid);
+ assertEquals(EidType.IPV4.getValue(), request.eidType);
+ assertEquals(FilterType.LOCAL.getValue(), request.filter);
+ assertEquals(32, request.prefixLength);
+
+ assertNotNull(reply);
+ assertEquals(1, reply.lispEidTableDetails.size());
+
+ final LispEidTableDetails detail = reply.lispEidTableDetails.get(0);
+
+ assertNotNull(detail);
+ assertEquals(0, detail.action);
+ assertEquals(1, detail.authoritative);
+ assertEquals(4, detail.context);
+ assertArrayEquals(EID, detail.eid);
+ assertEquals(32, detail.eidPrefixLen);
+ assertEquals(1, detail.isLocal);
+ assertEquals(2, detail.locatorSetIndex);
+ assertEquals(7, detail.ttl);
+ assertEquals(2, detail.vni);
+ }
+
+ @Override
+ protected MappingsDumpExecutor initExecutor() {
+ return new MappingsDumpExecutor(api);
+ }
+} \ No newline at end of file
diff --git a/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/VniTableDumpExecutorTest.java b/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/VniTableDumpExecutorTest.java
new file mode 100644
index 000000000..13033bf65
--- /dev/null
+++ b/lisp/lisp2vpp/src/test/java/io/fd/honeycomb/lisp/translate/read/dump/executor/VniTableDumpExecutorTest.java
@@ -0,0 +1,76 @@
+package io.fd.honeycomb.lisp.translate.read.dump.executor;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableList;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.DumpExecutionFailedException;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.i.DumpCallFailedException;
+import io.fd.honeycomb.translate.util.read.cache.exceptions.execution.i.DumpTimeoutException;
+import io.fd.honeycomb.vpp.test.read.JvppDumpExecutorTest;
+import java.util.concurrent.TimeoutException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.openvpp.jvpp.core.dto.LispEidTableMapDetails;
+import org.openvpp.jvpp.core.dto.LispEidTableMapDetailsReplyDump;
+
+
+public class VniTableDumpExecutorTest extends JvppDumpExecutorTest<VniTableDumpExecutor> {
+
+ private LispEidTableMapDetailsReplyDump validDump;
+
+ @Before
+ public void init() {
+ validDump = new LispEidTableMapDetailsReplyDump();
+ LispEidTableMapDetails detail = new LispEidTableMapDetails();
+ detail.dpTable = 1;
+ detail.vni = 2;
+ detail.context = 4;
+ validDump.lispEidTableMapDetails = ImmutableList.of(detail);
+ }
+
+ @Test(expected = DumpCallFailedException.class)
+ public void testExecuteDumpFail() throws DumpExecutionFailedException {
+ doThrowFailExceptionWhen().lispEidTableMapDump(Mockito.any());
+ getExecutor().executeDump(EntityDumpExecutor.NO_PARAMS);
+ }
+
+
+ @Test
+ public void testExecuteDumpTimeout() throws Exception {
+ doThrowTimeoutExceptionWhen().lispEidTableMapDump(Mockito.any());
+ try {
+ getExecutor().executeDump(EntityDumpExecutor.NO_PARAMS);
+ } catch (Exception e) {
+ assertTrue(e instanceof DumpTimeoutException);
+ assertTrue(e.getCause() instanceof TimeoutException);
+ return;
+ }
+ fail("Test should have thrown exception");
+ }
+
+ @Test
+ public void testExecuteDump() throws DumpExecutionFailedException {
+
+ doReturnResponseWhen(validDump).lispEidTableMapDump(Mockito.any());
+ final LispEidTableMapDetailsReplyDump reply = getExecutor().executeDump(EntityDumpExecutor.NO_PARAMS);
+
+ assertNotNull(reply);
+ assertEquals(1, reply.lispEidTableMapDetails.size());
+ final LispEidTableMapDetails detail = reply.lispEidTableMapDetails.get(0);
+
+ assertEquals(4, detail.context);
+ assertEquals(1, detail.dpTable);
+ assertEquals(2, detail.vni);
+ }
+
+ @Override
+ protected VniTableDumpExecutor initExecutor() {
+ return new VniTableDumpExecutor(api);
+ }
+} \ No newline at end of file