1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; 4 import static android.os.Build.VERSION_CODES.M; 5 import static android.os.Build.VERSION_CODES.R; 6 7 import android.net.Network; 8 import java.io.FileDescriptor; 9 import java.net.DatagramSocket; 10 import java.net.Socket; 11 import java.util.HashSet; 12 import java.util.Set; 13 import org.robolectric.annotation.Implementation; 14 import org.robolectric.annotation.Implements; 15 import org.robolectric.annotation.RealObject; 16 import org.robolectric.shadow.api.Shadow; 17 import org.robolectric.util.ReflectionHelpers; 18 19 @Implements(value = Network.class) 20 public class ShadowNetwork { 21 22 @RealObject private Network realObject; 23 24 private final Set<Socket> boundSockets = new HashSet<>(); 25 private final Set<DatagramSocket> boundDatagramSockets = new HashSet<>(); 26 private final Set<FileDescriptor> boundFileDescriptors = new HashSet<>(); 27 28 /** 29 * Creates new instance of {@link Network}, because its constructor is hidden. 30 * 31 * @param netId The netId. 32 * @return The Network instance. 33 */ newInstance(int netId)34 public static Network newInstance(int netId) { 35 return Shadow.newInstance(Network.class, new Class[] {int.class}, new Object[] {netId}); 36 } 37 38 /** Checks if the {@code socket} was previously bound to this network. */ isSocketBound(Socket socket)39 public boolean isSocketBound(Socket socket) { 40 return boundSockets.contains(socket); 41 } 42 43 /** Checks if the {@code datagramSocket} was previously bound to this network. */ isSocketBound(DatagramSocket socket)44 public boolean isSocketBound(DatagramSocket socket) { 45 return boundDatagramSockets.contains(socket); 46 } 47 48 /** Checks if the {@code fileDescriptor} was previously bound to this network. */ isSocketBound(FileDescriptor fd)49 public boolean isSocketBound(FileDescriptor fd) { 50 return boundFileDescriptors.contains(fd); 51 } 52 53 /** Returns the total number of sockets bound to this network interface. */ boundSocketCount()54 public int boundSocketCount() { 55 return boundSockets.size() + boundDatagramSockets.size() + boundFileDescriptors.size(); 56 } 57 58 /** 59 * Simulates a socket bind. isSocketBound can be called to verify that the socket was bound to 60 * this network interface, and boundSocketCount() will increment for any unique socket. 61 */ 62 @Implementation(minSdk = LOLLIPOP_MR1) bindSocket(DatagramSocket socket)63 protected void bindSocket(DatagramSocket socket) { 64 boundDatagramSockets.add(socket); 65 } 66 67 /** 68 * Simulates a socket bind. isSocketBound can be called to verify that the socket was bound to 69 * this network interface, and boundSocketCount() will increment for any unique socket. 70 */ 71 @Implementation bindSocket(Socket socket)72 protected void bindSocket(Socket socket) { 73 boundSockets.add(socket); 74 } 75 76 /** 77 * Simulates a socket bind. isSocketBound can be called to verify that the fd was bound to this 78 * network interface, and boundSocketCount() will increment for any unique socket. 79 */ 80 @Implementation(minSdk = M) bindSocket(FileDescriptor fd)81 protected void bindSocket(FileDescriptor fd) { 82 boundFileDescriptors.add(fd); 83 } 84 85 /** 86 * Allows to get the stored netId. 87 * 88 * @return The netId. 89 */ 90 @Implementation(minSdk = R) getNetId()91 public int getNetId() { 92 return ReflectionHelpers.getField(realObject, "netId"); 93 } 94 } 95