--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+import java.util.BitSet;
+import java.util.Map;
+
+/**
+ * A class capable of representing available frequency slots as a bit map may implement
+ * this interface.
+ *
+ * <p>
+ * Available frequency ranges are represented by a (signed) byte array.
+ * The size of the byte array multiplied by byte size is equal to the
+ * total number of frequency "slots".
+ * e.g. 96 bytes = 768 bits = 768 frequency slots.
+ *
+ * <p>
+ * Each frequency range is assumed to be 1 signed byte, i.e. 8 bits where
+ * each bit represents a frequency range with a width of e.g. 6.25 GHz.
+ *
+ * <p>
+ * Examples:
+ * byte[] frequencies = {0} => {0b00000000} (no frequency slots available)
+ * byte[] frequencies = {1} => {0b00000001}
+ * byte[] frequencies = {56} => {0b00111000}
+ * byte[] frequencies = {127} => {0b01111111}
+ * byte[] frequencies = {-128} => {0b10000000}
+ * byte[] frequencies = {-1} => {0b11111111} (all frequency slots available)
+ * byte[] frequencies = {-58} => {0b11000110}
+ * byte[] frequencies = {-58, -1} => {0b11000110, 0b11111111}
+ *
+ * <p>
+ * The available frequency slots...
+ * byte[] frequencies = {-58, -1} => {0b11000110, 0b11111111}
+ * ...can be reversed using the method assignedFrequencies():
+ * availableFrequencies() => {0b00111001, 0b00000000}
+ */
+public interface Available {
+
+ /**
+ * Available frequency ranges.
+ *
+ * <p>
+ * This method returns a byte array representing available frequency ranges.
+ *
+ * @return A byte array representing available frequency ranges.
+ */
+ byte[] availableFrequencyRanges();
+
+ /**
+ * Assigned frequencies.
+ *
+ * <p>
+ * This method returns a BitSet representing used frequencies.
+ *
+ * <p>
+ * Each bit in the set represents a frequency range.
+ * - 1 (true) indicates that the frequency range is assigned (used).
+ * - 0 (false) indicates that the frequency range is available.
+ *
+ * @return A BitSet representing used frequency ranges.
+ */
+ BitSet assignedFrequencies();
+
+ /**
+ * Available frequencies.
+ *
+ * <p>
+ * This method returns a BitSet representing available frequencies.
+ * This is the equivalent of inverting a bitset of used frequencies,
+ * i.e. inverting the result of the method assignedFrequencies().
+ *
+ * <p>
+ * Each bit in the set represents a frequency.
+ * - 1 (true) indicates that the frequency range is available.
+ * - 0 (false) indicates that the frequency range is unavailable (used).
+ *
+ * @return A BitSet representing available frequency ranges.
+ */
+ BitSet availableFrequencies();
+
+ /**
+ * Return a map of ASSIGNED (i.e. used) frequency ranges.
+ *
+ * <p>
+ * The key is the lower frequency bound and the value is the upper frequency bound.
+ */
+ Map<Double, Double> assignedFrequency(Numeric numeric);
+
+ /**
+ * Return a map of AVAILABLE frequency ranges.
+ *
+ * <p>
+ * The key is the lower frequency bound and the value is the upper frequency bound.
+ */
+ Map<Double, Double> availableFrequency(Numeric numeric);
+
+}
--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+import java.util.BitSet;
+import java.util.Map;
+
+public class AvailableGrid implements Available {
+
+ private final byte[] availableFrequencyGrid;
+
+ /**
+ * The available frequency slots are represented by a (signed) byte array.
+ *
+ * <p>
+ * The size of the byte array multiplied by byte size is equal to the
+ * total number of frequency slots.
+ * e.g. 96 bytes = 768 bits = 768 frequency slots.
+ *
+ * <p>
+ * The available frequency slots...
+ * byte[] frequencies = {-58, -1} => {0b11000110, 0b11111111}
+ * ...can be reversed using the method assignedFrequencies():
+ * availableFrequencies() => {0b00111001, 0b00000000}
+ */
+ public AvailableGrid(byte[] availableFrequencyGrid) {
+ this.availableFrequencyGrid = new byte[availableFrequencyGrid.length];
+ System.arraycopy(availableFrequencyGrid, 0, this.availableFrequencyGrid, 0, availableFrequencyGrid.length);
+ }
+
+ @Override
+ public byte[] availableFrequencyRanges() {
+
+ byte[] freqBitSetCopy = new byte[availableFrequencyGrid.length];
+
+ System.arraycopy(availableFrequencyGrid, 0, freqBitSetCopy, 0, availableFrequencyGrid.length);
+
+ return freqBitSetCopy;
+ }
+
+ @Override
+ public BitSet assignedFrequencies() {
+
+ BitSet bitSet = new BitSet(availableFrequencyGrid.length * Byte.SIZE);
+
+ bitSet.or(BitSet.valueOf(availableFrequencyGrid));
+
+ bitSet.flip(0, availableFrequencyGrid.length * Byte.SIZE);
+
+ return bitSet;
+ }
+
+ @Override
+ public BitSet availableFrequencies() {
+
+ BitSet bitSet = new BitSet(availableFrequencyGrid.length * Byte.SIZE);
+
+ bitSet.or(BitSet.valueOf(availableFrequencyGrid));
+
+ return bitSet;
+
+ }
+
+ @Override
+ public Map<Double, Double> assignedFrequency(Numeric numeric) {
+ return numeric.assignedFrequency(this);
+ }
+
+ @Override
+ public Map<Double, Double> availableFrequency(Numeric numeric) {
+ return numeric.availableFrequency(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+
+public class AvailableGridFactory implements Factory {
+
+ @Override
+ public Available fromAvailable(byte[] frequencyRange) {
+ return new AvailableGrid(frequencyRange);
+ }
+
+ @Override
+ public Available fromAssigned(byte[] frequencyRange) {
+ byte[] frequencyRangeCopy = new byte[frequencyRange.length];
+
+ for (int i = 0; i < frequencyRange.length; i++) {
+ frequencyRangeCopy[i] = (byte) ~frequencyRange[i];
+ }
+
+ return new AvailableGrid(frequencyRangeCopy);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+
+public interface Factory {
+
+ /**
+ * Creates an instance of Available, treating
+ * the byte array as an available frequency range.
+ */
+ Available fromAvailable(byte[] frequencyRange);
+
+ /**
+ * Creates an instance of Available, treating
+ * the byte array as an assigned (used) frequency range.
+ */
+ Available fromAssigned(byte[] frequencyRange);
+
+}
--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+import org.opendaylight.transportpce.common.fixedflex.GridUtils;
+
+public class FrequencyMath implements Math {
+ @Override
+ public Double getStartFrequencyFromIndex(int index) {
+ return GridUtils.getStartFrequencyFromIndex(index).doubleValue();
+ }
+
+ @Override
+ public Double getStopFrequencyFromIndex(int index) {
+ return GridUtils.getStopFrequencyFromIndex(index).doubleValue();
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+public interface Math {
+
+ /**
+ * Compute the start frequency in THz for the given index.
+ *
+ * @param index int
+ * @return the start frequency in THz for the provided index.
+ */
+ Double getStartFrequencyFromIndex(int index);
+
+ /**
+ * Compute the stop frequency in THz for the given index.
+ *
+ * @param index int
+ * @return the stop frequency in THz for the provided index.
+ */
+ Double getStopFrequencyFromIndex(int index);
+
+}
--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+import java.util.Map;
+
+public interface Numeric {
+
+ /**
+ * Return a map of ASSIGNED (i.e. used) frequency ranges.
+ *
+ * <p>
+ * The key is the lower frequency bound and the value is the upper frequency bound.
+ */
+ Map<Double, Double> assignedFrequency(Available frequency);
+
+ /**
+ * Return a map of AVAILABLE frequency ranges.
+ *
+ * <p>
+ * The key is the lower frequency bound and the value is the upper frequency bound.
+ */
+ Map<Double, Double> availableFrequency(Available frequency);
+
+}
--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics, Orange and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+import java.util.BitSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class NumericFrequency implements Numeric {
+
+ private final Double startFrequency;
+
+ private final int nrOfBits;
+
+ private final Math math;
+
+ public NumericFrequency(Double startFrequency, int nrOfBits) {
+ this(startFrequency, nrOfBits, new FrequencyMath());
+ }
+
+ public NumericFrequency(Double startFrequency, int nrOfBits, Math math) {
+ this.startFrequency = startFrequency;
+ this.nrOfBits = nrOfBits;
+ this.math = math;
+ }
+
+ @Override
+ public Map<Double, Double> assignedFrequency(Available frequency) {
+ return this.range(frequency.assignedFrequencies());
+ }
+
+ @Override
+ public Map<Double, Double> availableFrequency(Available frequency) {
+ return this.range(frequency.availableFrequencies());
+ }
+
+ /**
+ * Note: This code is mostly copied as is from the original
+ * class ConvertORToTapiTopology.java as part of refactoring.
+ */
+ private Map<Double, Double> range(BitSet bitSet) {
+
+ Map<Double,Double> freqMap = new LinkedHashMap<>();
+
+ Double startFreq = startFrequency;
+ Double stopFreq = 0.0;
+ boolean occupied = !bitSet.get(0);
+
+ for (int index = 0 ; index < nrOfBits ; index++) {
+ if (occupied) {
+ if (bitSet.get(index)) {
+ startFreq = math.getStartFrequencyFromIndex(index);
+ stopFreq = math.getStartFrequencyFromIndex(index);
+ occupied = false;
+ }
+ } else {
+ if (!bitSet.get(index)) {
+ stopFreq = math.getStartFrequencyFromIndex(index);
+ occupied = true;
+ }
+ }
+ if (occupied) {
+ if (stopFreq > startFreq) {
+ freqMap.put(startFreq, stopFreq);
+ startFreq = stopFreq;
+ }
+ } else {
+ if (index == nrOfBits - 1
+ && Double.compare(startFreq, stopFreq) == 0) {
+ stopFreq = math.getStopFrequencyFromIndex(index);
+ freqMap.put(startFreq, stopFreq);
+ }
+ }
+ }
+ return freqMap;
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+
+import java.util.BitSet;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+class AvailableGridFactoryTest {
+
+ @Test
+ void assignedFrequency() {
+ AvailableGridFactory availableGridFactory = new AvailableGridFactory();
+ byte[] frequency = {0, -1, -1, -1, -1, -1, -1, -1};
+ byte[] expected = {0, -1, -1, -1, -1, -1, -1, -1};
+
+ Assert.assertArrayEquals(
+ expected,
+ availableGridFactory.fromAvailable(frequency).availableFrequencyRanges()
+ );
+ }
+
+ @Test
+ void availableFrequency() {
+ AvailableGridFactory availableGridFactory = new AvailableGridFactory();
+
+ byte[] assignedFrequencies = {-1, 0, 0, 0, 0, 0, 0, 0};
+ byte[] expectedAvailableFrequencies = { 0, -1, -1, -1, -1, -1, -1, -1};
+
+ Available bitMap = availableGridFactory.fromAssigned(assignedFrequencies);
+
+ byte[] availableFrequencies = bitMap.availableFrequencyRanges();
+
+ Assert.assertArrayEquals(
+ expectedAvailableFrequencies,
+ availableFrequencies
+ );
+
+ Assert.assertArrayEquals(
+ availableFrequencies,
+ bitMap.availableFrequencyRanges()
+ );
+
+ Assert.assertEquals(
+ BitSet.valueOf(assignedFrequencies),
+ bitMap.assignedFrequencies()
+ );
+
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+import java.util.Arrays;
+import java.util.BitSet;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+class AvailableGridTest {
+
+ @Test
+ void testSize() {
+ byte[] frequencies = {0, -1, -1, 0, 0, 0, 0, -1};
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ Assert.assertEquals(64, availableGrid.assignedFrequencies().size());
+ Assert.assertEquals(64, availableGrid.availableFrequencies().size());
+ }
+
+ @Test
+ void availableFrequencyRanges() {
+ byte[] frequencies = {0, -1, -1, 0, 0, 0, 0, -1};
+ byte[] expected = {0, -1, -1, 0, 0, 0, 0, -1};
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ Assert.assertArrayEquals(expected, availableGrid.availableFrequencyRanges());
+ }
+
+ @Test
+ void availableFrequencyRangesAreInMutable() {
+ byte[] frequencies = {0, -1, -1, 0, 0, 0, 0, -1};
+ byte[] expected = {0, -1, -1, 0, 0, 0, 0, -1};
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ //This change shouldn't affect the contents of the assignedFrequencies object
+ frequencies[0] = -1;
+
+ //The arrays are different
+ Assert.assertFalse(Arrays.equals(expected, frequencies));
+
+ //The contents of the assignedFrequencies object are still the same
+ Assert.assertArrayEquals(expected, availableGrid.availableFrequencyRanges());
+ }
+
+
+ @Test
+ void assignedFrequenciesStart() {
+ byte[] frequencies = {-1, 0, 0, 0, 0, 0, 0, 0};
+ BitSet expected = new BitSet();
+ expected.set(0, 8);
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ Assert.assertEquals(expected, availableGrid.availableFrequencies());
+ }
+
+ @Test
+ void assignedFrequenciesMiddle() {
+ byte[] frequencies = {0, -1, 0, 0, 0, 0, 0, 0};
+ BitSet expected = new BitSet();
+ expected.set(8, 16);
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ Assert.assertEquals(expected, availableGrid.availableFrequencies());
+ }
+
+ @Test
+ void assignedFrequenciesConsecutive() {
+ byte[] frequencies = {0, -1, -1, 0, 0, 0, 0, 0};
+ BitSet expected = new BitSet();
+ expected.set(8, 24);
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ Assert.assertEquals(expected, availableGrid.availableFrequencies());
+ }
+
+ @Test
+ void assignedFrequenciesEnd() {
+ byte[] frequencies = {0, 0, 0, 0, 0, 0, 0, -1};
+ BitSet expected = new BitSet();
+ expected.set(56, 64);
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ Assert.assertEquals(expected, availableGrid.availableFrequencies());
+ }
+
+ @Test
+ void assignedFrequenciesPartial() {
+ byte[] frequencies = {0, 0, 0, 0, 0, 0, 0, 56};
+ BitSet expected = new BitSet();
+ expected.set(59, 62);
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ Assert.assertEquals(expected, availableGrid.availableFrequencies());
+ }
+
+ @Test
+ void assignedFrequenciesJoined() {
+ byte[] frequencies = {0, -128, 7, 0, 0, 0, 0, 0};
+ BitSet expected = new BitSet();
+ expected.set(15, 19);
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ Assert.assertEquals(expected, availableGrid.availableFrequencies());
+ }
+
+ @Test
+ void assignedFrequenciesAll() {
+ byte[] frequencies = {-1, -1, -1, -1, -1, -1, -1, -1};
+ BitSet expected = new BitSet();
+ expected.set(0, 64);
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ Assert.assertEquals(expected, availableGrid.availableFrequencies());
+ }
+
+ @Test
+ void assignedFrequenciesNone() {
+ byte[] frequencies = {0, 0, 0, 0, 0, 0, 0, 0};
+ BitSet expected = new BitSet();
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ Assert.assertEquals(expected, availableGrid.availableFrequencies());
+ }
+
+ @Test
+ void availableFrequencies() {
+ byte[] frequencies = {0, -1, 0, 0, 0, 0, 0, 0};
+
+ BitSet expected = new BitSet();
+ expected.set(0, 8);
+ expected.set(16, 64);
+
+ AvailableGrid availableGrid = new AvailableGrid(frequencies);
+
+ BitSet assigned = availableGrid.assignedFrequencies();
+ Assert.assertEquals(expected, assigned);
+
+ BitSet available = availableGrid.availableFrequencies();
+ Assert.assertEquals(BitSet.valueOf(frequencies), available);
+
+ Assert.assertNotEquals(available, assigned);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright © 2024 Smartoptics and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.tapi.frequency;
+
+import java.util.BitSet;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+class NumericFrequencyTest {
+
+ @Test
+ void assignedFrequency() {
+ BitSet assigned = new BitSet(768);
+ assigned.set(760, 768);
+
+ Available used = Mockito.mock(Available.class);
+ Mockito.when(used.assignedFrequencies()).thenReturn(assigned);
+
+ Math math = Mockito.mock(Math.class);
+ Mockito.when(math.getStartFrequencyFromIndex(760)).thenReturn(196.075);
+ Mockito.when(math.getStopFrequencyFromIndex(767)).thenReturn(196.125);
+
+ Map<Double, Double> expected = Map.of(196.075, 196.125);
+
+ Numeric frequencyService = new NumericFrequency(191.325, 768, math);
+ Assert.assertEquals(expected, frequencyService.assignedFrequency(used));
+
+ }
+
+ @Test
+ void assignedStartAndEndFrequencyRanges() {
+ Math math = Mockito.mock(Math.class);
+ Mockito.when(math.getStartFrequencyFromIndex(8)).thenReturn(191.375);
+ Mockito.when(math.getStartFrequencyFromIndex(760)).thenReturn(196.075);
+ Mockito.when(math.getStopFrequencyFromIndex(767)).thenReturn(196.125);
+
+ BitSet assigned = new BitSet(768);
+ assigned.set(0, 8);
+ assigned.set(760, 768);
+
+ Available used = Mockito.mock(Available.class);
+ Mockito.when(used.assignedFrequencies()).thenReturn(assigned);
+
+ Map<Double, Double> expected = Map.of(191.325, 191.375, 196.075, 196.125);
+
+ Numeric frequencyService = new NumericFrequency(191.325, 768, math);
+ Assert.assertEquals(expected, frequencyService.assignedFrequency(used));
+
+ }
+
+ @Test
+ void assignedMiddleFrequencyRanges() {
+ Math math = Mockito.mock(Math.class);
+ Mockito.when(math.getStartFrequencyFromIndex(32)).thenReturn(191.525);
+ Mockito.when(math.getStartFrequencyFromIndex(40)).thenReturn(191.575);
+
+ BitSet assigned = new BitSet(768);
+ assigned.set(32, 40);
+
+ Available used = Mockito.mock(Available.class);
+ Mockito.when(used.assignedFrequencies()).thenReturn(assigned);
+
+ Map<Double, Double> expected = Map.of(191.525, 191.575);
+
+ Numeric frequencyService = new NumericFrequency(191.325, 768, math);
+ Assert.assertEquals(expected, frequencyService.assignedFrequency(used));
+
+ }
+
+ @Test
+ void assignedStartMiddleAndEndFrequencyRanges() {
+ Math math = Mockito.mock(Math.class);
+ Mockito.when(math.getStartFrequencyFromIndex(8)).thenReturn(191.375);
+ Mockito.when(math.getStartFrequencyFromIndex(32)).thenReturn(191.525);
+ Mockito.when(math.getStartFrequencyFromIndex(40)).thenReturn(191.575);
+ Mockito.when(math.getStartFrequencyFromIndex(760)).thenReturn(196.075);
+ Mockito.when(math.getStopFrequencyFromIndex(767)).thenReturn(196.125);
+
+ BitSet assigned = new BitSet(768);
+ assigned.set(0, 8);
+ assigned.set(32, 40);
+ assigned.set(760, 768);
+
+ Available used = Mockito.mock(Available.class);
+ Mockito.when(used.assignedFrequencies()).thenReturn(assigned);
+
+ Map<Double, Double> expected = Map.of(191.325, 191.375, 191.525, 191.575, 196.075, 196.125);
+
+ Numeric frequencyService = new NumericFrequency(191.325, 768, math);
+ Assert.assertEquals(expected, frequencyService.assignedFrequency(used));
+
+ }
+
+ @Test
+ void availableFrequency() {
+ Math math = Mockito.mock(Math.class);
+ Mockito.when(math.getStartFrequencyFromIndex(760)).thenReturn(196.075);
+
+ Numeric frequencyService = new NumericFrequency(191.325, 768, math);
+
+ BitSet available = new BitSet(768);
+ available.set(0, 760);
+
+ Available bitMap = Mockito.mock(Available.class);
+ Mockito.when(bitMap.availableFrequencies()).thenReturn(available);
+
+ Map<Double, Double> expected = Map.of(191.325, 196.075);
+ Assert.assertEquals(expected, frequencyService.availableFrequency(bitMap));
+ }
+
+ @Test
+ void availableSplitByAssignedMiddleFrequencyRanges() {
+ Math math = Mockito.mock(Math.class);
+ Mockito.when(math.getStartFrequencyFromIndex(32)).thenReturn(191.525);
+ Mockito.when(math.getStartFrequencyFromIndex(40)).thenReturn(191.575);
+ Mockito.when(math.getStopFrequencyFromIndex(767)).thenReturn(196.125);
+
+ BitSet available = new BitSet(768);
+ available.set(0, 32);
+ available.set(40, 768);
+
+ Available used = Mockito.mock(Available.class);
+ Mockito.when(used.availableFrequencies()).thenReturn(available);
+
+ Map<Double, Double> expected = Map.of(191.325, 191.525, 191.575, 196.125);
+
+ Numeric frequencyService = new NumericFrequency(191.325, 768, math);
+ Assert.assertEquals(expected, frequencyService.availableFrequency(used));
+
+ }
+
+ @Test
+ void flexGrid() {
+ Math math = Mockito.mock(Math.class);
+ Mockito.when(math.getStartFrequencyFromIndex(5)).thenReturn(191.35625);
+ Mockito.when(math.getStartFrequencyFromIndex(11)).thenReturn(191.39374999999998);
+ Mockito.when(math.getStartFrequencyFromIndex(19)).thenReturn(191.44375);
+ Mockito.when(math.getStopFrequencyFromIndex(767)).thenReturn(196.125);
+
+ BitSet available = new BitSet(768);
+ available.set(5, 11);
+ available.set(19, 768);
+
+ Available used = Mockito.mock(Available.class);
+ Mockito.when(used.availableFrequencies()).thenReturn(available);
+
+ Map<Double, Double> expected = Map.of(191.35625, 191.39374999999998, 191.44375, 196.125);
+
+ Numeric frequencyService = new NumericFrequency(191.325, 768, math);
+ Assert.assertEquals(expected, frequencyService.availableFrequency(used));
+
+ }
+
+}
\ No newline at end of file