Unexpected error when unit testing nested JNA Structure objectsIterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loopHow to unit test abstract classes: extend with stubs?“cannot find symbol method drawImage(java.awt.image.BufferedImage,<nulltype>,int,int)”linux to windows C++ byte arrayJUnit test of the same objectWhy this class should implement java.io.Serializable when I using hibernate?Type mismatch in key from map: expected .. Text, received … LongWritablewhy spill failure happens for Custom Data Type in HadoopFatal error with JNA structureWhen I run The Junit Test Case in Eclispe I am getting The errr

Term used to describe a person who predicts future outcomes

Unlock your Lock

What stops you from using fixed income in developing countries?

Why does Windows store Wi-Fi passwords in a reversible format?

What is the meaning of “these lederhosen are riding up my Bundesliga”?

Is a memoized pure function itself considered pure?

Did anybody find out it was Anakin who blew up the command center?

What is this fighter jet at Weymouth NAS?

According to UK government, Parliament cannot stop a no-deal Brexit: Could this also be used to push through the agreement agreed by Theresa May?

How can I download a file from a host I can only SSH to through another host?

Is this password scheme legit?

Multiple delayed triggers from Massacre Girl interaction

If I said I had $100 when asked, but I actually had $200, would I be lying by omission?

Defending Castle from Zombies

What's the point of fighting monsters in Zelda BoTW?

What is the 3D printer filament (or pellet) most resistant to bending at high heats?

Count the number of shortest paths to n

74S vs 74LS ICs

The term Feed-forward and its meaning?

Why can't UK MPs vote for the Withdrawal Agreement, then renege on the backstop if it comes to that?

Why does matter stay collapsed in the core, following a supernova explosion?

Why is getting a PhD considered "financially irresponsible" by some people?

Why does this London Underground poster from 1924 have a Star of David atop a Christmas tree?

Is there a word or phrase that means "use other people's wifi or Internet service without consent"?



Unexpected error when unit testing nested JNA Structure objects


Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loopHow to unit test abstract classes: extend with stubs?“cannot find symbol method drawImage(java.awt.image.BufferedImage,<nulltype>,int,int)”linux to windows C++ byte arrayJUnit test of the same objectWhy this class should implement java.io.Serializable when I using hibernate?Type mismatch in key from map: expected .. Text, received … LongWritablewhy spill failure happens for Custom Data Type in HadoopFatal error with JNA structureWhen I run The Junit Test Case in Eclispe I am getting The errr






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








1















The following unit test is intended to verify that a nested JNA data structure is properly parsed based on the data that gets passed into the constructor. The unit test properly checks when JNA initializes the 'parent' structure. However, the test fails when testing member variables of a nested structure. I suspect the problem to be that the unit test sets a pointer to a memory location that contains the data for the nested structure. Perhaps the Java Pointer isn't translating one-to-one to how C does it.



I tried placing the WlanBssEntry at the start of WlanBssEntry[] but that didn't provide any different results than how it is currently implemented. When I tried placing it contiguously, I did not call pointerToMem.setPointer(8, ...)



This is the unit test:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sevensignal.EyeQAgent.Models.Platform;
import com.sevensignal.EyeQAgent.Util.Utils;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeThat;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Utils.class)
public class WlanBssListTest

Pointer pWlanBssList;

private final static long OFFSET_TO_FIRST_WLAN_BSS_ENTRY = 1024;

@Before
public void setUp()
assumeThat(Utils.getPlatform(), equalTo(Platform.WINDOWS));
pWlanBssList = allocateMemory(65536);
initWlanBssEntryMemory(pWlanBssList, OFFSET_TO_FIRST_WLAN_BSS_ENTRY, 50);
initWlanBssListMemory(pWlanBssList, 12, 1, OFFSET_TO_FIRST_WLAN_BSS_ENTRY);


@Test
public void shouldSetTotalSize()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should set total size", new WinDef.DWORD(12), subject.dwTotalSize);


@Test
public void shouldSetNumberOfItems()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should set number of items", new WinDef.DWORD(1), subject.dwNumberOfItems);


@Test
public void shouldInitWlanBssEntries()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should init WLAN BSS Entries", 1, subject.wlanBssEntries.length);
assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(50), subject.wlanBssEntries[0].uPhyId);


@Test
public void shouldInitWlanBssEntriesWhenNoEntriesExist()
pWlanBssList.setInt(4, 0);
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should init WLAN BSS Entries when no entries exist", 0, subject.wlanBssEntries.length);


private Pointer allocateMemory(long size)
return new Memory(size).share(0);


private void initWlanBssListMemory(Pointer pointerToMem, int dwTotalSize, int dwNumberOfItems, long offsetToWlanBssEntry)
pointerToMem.setInt(0, dwTotalSize);
pointerToMem.setInt(4, dwNumberOfItems);
pointerToMem.setPointer(8, pointerToMem.share(offsetToWlanBssEntry));


private void initWlanBssEntryMemory(Pointer pointerToMem, long offsetToWlanBssEntry, long uPhyId)
final int PHY_ID_OFFSET = 40;
pointerToMem.setLong(offsetToWlanBssEntry + 0, 3);
pointerToMem.setByte(offsetToWlanBssEntry + 8, (byte)'T');
pointerToMem.setByte(offsetToWlanBssEntry + 9, (byte)'S');
pointerToMem.setByte(offsetToWlanBssEntry + 10, (byte)'T');
pointerToMem.setLong(offsetToWlanBssEntry + PHY_ID_OFFSET, uPhyId);




This is the WlanBssList class which is the highest level structure:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.DWORD;

import java.util.Arrays;
import java.util.List;

public class WlanBssList extends Structure

public DWORD dwTotalSize;
public DWORD dwNumberOfItems;
public WlanBssEntry[] wlanBssEntries;

public static class ByReference extends WlanBssList implements Structure.ByReference

public ByReference()




public ByReference(Pointer p)

super(p);



public WlanBssList()
wlanBssEntries = new WlanBssEntry[1];


public WlanBssList(Pointer p)
super(p);
dwTotalSize = new DWORD(p.getInt(0));
dwNumberOfItems = new DWORD(p.getInt(4));
if(dwNumberOfItems.intValue() > 0)
wlanBssEntries = new WlanBssEntry[dwNumberOfItems.intValue()];
readField("wlanBssEntries");
else
wlanBssEntries = new WlanBssEntry[0];



@Override
protected List<String> getFieldOrder()
return Arrays.asList("dwTotalSize", "dwNumberOfItems", "wlanBssEntries");




And these are the nested structures:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sevensignal.EyeQAgent.Models.InformationElementGetter;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.LONG;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinDef.ULONGLONG;
import com.sun.jna.platform.win32.WinDef.USHORT;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.List;

@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WlanBssEntry extends Structure implements InformationElementGetter

public DOT11_SSID dot11Ssid;
public ULONG uPhyId;
public DOT11_MAC_ADDRESS dot11Bssid;
public int dot11BssType;
public int dot11BssPhyType;
public LONG lRssi;
public ULONG uLinkQuality;
public boolean bInRegDomain;
public USHORT usBeaconPeriod;
public ULONGLONG ullTimestamp;
public ULONGLONG ullHostTimestamp;
public USHORT usCapabilityInformation;
public ULONG ulChCenterFrequency;
public WlanRateSet wlanRateSet;
public ULONG ulIeOffset;
public ULONG ulIeSize;

@Override
protected List<String> getFieldOrder()

return Arrays.asList("dot11Ssid",
"uPhyId",
"dot11Bssid",
"dot11BssType",
"dot11BssPhyType",
"lRssi",
"uLinkQuality",
"bInRegDomain",
"usBeaconPeriod",
"ullTimestamp",
"ullHostTimestamp",
"usCapabilityInformation",
"ulChCenterFrequency",
"wlanRateSet",
"ulIeOffset",
"ulIeSize");


public byte[] getInformationElement()
return this.getPointer()
.getByteArray(this.ulIeOffset.intValue(), this.ulIeSize.intValue());




package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.*;

import java.util.Arrays;
import java.util.List;

public class DOT11_SSID extends Structure

public static class ByReference extends DOT11_SSID implements Structure.ByReference




public static int DOT11_SSID_MAX_LENGTH = 32;

/**
* The length, in bytes, of the ucSSID array.
*/
public ULONG uSSIDLength;

/**
* The SSID. DOT11_SSID_MAX_LENGTH is set to 32.
*/
public byte[] ucSSID;

public DOT11_SSID()

ucSSID = new byte[DOT11_SSID_MAX_LENGTH];


@Override
protected List<String> getFieldOrder()

return Arrays.asList("uSSIDLength", "ucSSID");


@Override
public String toString()
if(uSSIDLength != null)
int ssidArrayLength = uSSIDLength.intValue();
if (ssidArrayLength > DOT11_SSID_MAX_LENGTH)
ssidArrayLength = DOT11_SSID_MAX_LENGTH;


return new String(Arrays.copyOfRange(ucSSID, 0, ssidArrayLength));
else
return "";





The results of the unit test are:



java.lang.AssertionError: should init WLAN BSS Entry data struct 
Expected :50
Actual :0


The assertion that fails is:



assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(50), subject.wlanBssEntries[0].uPhyId);










share|improve this question



















  • 1





    Welcome to Stack Overflow! I'm not sure but think your array initialization wlanBssEntries = new WlanBssEntry[dwNumberOfItems.intValue()]; won't work. You should do wlanBssEntries = (new WlanBssEntry()).toArray(dwNumberOfItems.intValue());. (Also JNA doesn't support 0 length arrays so the second part of your conditional is impossible: always initialize with at least 1 element.)

    – Daniel Widdis
    Mar 27 at 21:06






  • 1





    to be more clear, the new foo[] structure array only works on the Java side and does not initialize the structure object. You would have to initialize every individual foo in the array (non-contiguous native memory which wouldn't work well as an array parameter) or use toArray() to initialize the structures with contiguous native memory.

    – Daniel Widdis
    Mar 27 at 21:14






  • 1





    JNA iterates over the fields in your FieldOrder list, using reflection to get the mapped class so it knows their native size so it knows the offset. Are you sure your calculated offsets are correct?

    – Daniel Widdis
    Mar 28 at 15:39






  • 1





    I figured it out. I'll post my answer later but wanted to let you know so you don't spend your valuable time. In short, my problem was two fold. First, I did have an offset problem in the data that I was initializing. Second, I didn't place the data I was initializing at the "end" of the WlanBssList (starting at offset 8). Thank you for your help. Your mention of toArray helped and having another sounding board was all it took.

    – Aaron Bauman
    Mar 28 at 18:15






  • 1





    Glad you fixed it and that I could help!

    – Daniel Widdis
    Mar 28 at 18:33

















1















The following unit test is intended to verify that a nested JNA data structure is properly parsed based on the data that gets passed into the constructor. The unit test properly checks when JNA initializes the 'parent' structure. However, the test fails when testing member variables of a nested structure. I suspect the problem to be that the unit test sets a pointer to a memory location that contains the data for the nested structure. Perhaps the Java Pointer isn't translating one-to-one to how C does it.



I tried placing the WlanBssEntry at the start of WlanBssEntry[] but that didn't provide any different results than how it is currently implemented. When I tried placing it contiguously, I did not call pointerToMem.setPointer(8, ...)



This is the unit test:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sevensignal.EyeQAgent.Models.Platform;
import com.sevensignal.EyeQAgent.Util.Utils;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeThat;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Utils.class)
public class WlanBssListTest

Pointer pWlanBssList;

private final static long OFFSET_TO_FIRST_WLAN_BSS_ENTRY = 1024;

@Before
public void setUp()
assumeThat(Utils.getPlatform(), equalTo(Platform.WINDOWS));
pWlanBssList = allocateMemory(65536);
initWlanBssEntryMemory(pWlanBssList, OFFSET_TO_FIRST_WLAN_BSS_ENTRY, 50);
initWlanBssListMemory(pWlanBssList, 12, 1, OFFSET_TO_FIRST_WLAN_BSS_ENTRY);


@Test
public void shouldSetTotalSize()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should set total size", new WinDef.DWORD(12), subject.dwTotalSize);


@Test
public void shouldSetNumberOfItems()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should set number of items", new WinDef.DWORD(1), subject.dwNumberOfItems);


@Test
public void shouldInitWlanBssEntries()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should init WLAN BSS Entries", 1, subject.wlanBssEntries.length);
assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(50), subject.wlanBssEntries[0].uPhyId);


@Test
public void shouldInitWlanBssEntriesWhenNoEntriesExist()
pWlanBssList.setInt(4, 0);
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should init WLAN BSS Entries when no entries exist", 0, subject.wlanBssEntries.length);


private Pointer allocateMemory(long size)
return new Memory(size).share(0);


private void initWlanBssListMemory(Pointer pointerToMem, int dwTotalSize, int dwNumberOfItems, long offsetToWlanBssEntry)
pointerToMem.setInt(0, dwTotalSize);
pointerToMem.setInt(4, dwNumberOfItems);
pointerToMem.setPointer(8, pointerToMem.share(offsetToWlanBssEntry));


private void initWlanBssEntryMemory(Pointer pointerToMem, long offsetToWlanBssEntry, long uPhyId)
final int PHY_ID_OFFSET = 40;
pointerToMem.setLong(offsetToWlanBssEntry + 0, 3);
pointerToMem.setByte(offsetToWlanBssEntry + 8, (byte)'T');
pointerToMem.setByte(offsetToWlanBssEntry + 9, (byte)'S');
pointerToMem.setByte(offsetToWlanBssEntry + 10, (byte)'T');
pointerToMem.setLong(offsetToWlanBssEntry + PHY_ID_OFFSET, uPhyId);




This is the WlanBssList class which is the highest level structure:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.DWORD;

import java.util.Arrays;
import java.util.List;

public class WlanBssList extends Structure

public DWORD dwTotalSize;
public DWORD dwNumberOfItems;
public WlanBssEntry[] wlanBssEntries;

public static class ByReference extends WlanBssList implements Structure.ByReference

public ByReference()




public ByReference(Pointer p)

super(p);



public WlanBssList()
wlanBssEntries = new WlanBssEntry[1];


public WlanBssList(Pointer p)
super(p);
dwTotalSize = new DWORD(p.getInt(0));
dwNumberOfItems = new DWORD(p.getInt(4));
if(dwNumberOfItems.intValue() > 0)
wlanBssEntries = new WlanBssEntry[dwNumberOfItems.intValue()];
readField("wlanBssEntries");
else
wlanBssEntries = new WlanBssEntry[0];



@Override
protected List<String> getFieldOrder()
return Arrays.asList("dwTotalSize", "dwNumberOfItems", "wlanBssEntries");




And these are the nested structures:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sevensignal.EyeQAgent.Models.InformationElementGetter;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.LONG;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinDef.ULONGLONG;
import com.sun.jna.platform.win32.WinDef.USHORT;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.List;

@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WlanBssEntry extends Structure implements InformationElementGetter

public DOT11_SSID dot11Ssid;
public ULONG uPhyId;
public DOT11_MAC_ADDRESS dot11Bssid;
public int dot11BssType;
public int dot11BssPhyType;
public LONG lRssi;
public ULONG uLinkQuality;
public boolean bInRegDomain;
public USHORT usBeaconPeriod;
public ULONGLONG ullTimestamp;
public ULONGLONG ullHostTimestamp;
public USHORT usCapabilityInformation;
public ULONG ulChCenterFrequency;
public WlanRateSet wlanRateSet;
public ULONG ulIeOffset;
public ULONG ulIeSize;

@Override
protected List<String> getFieldOrder()

return Arrays.asList("dot11Ssid",
"uPhyId",
"dot11Bssid",
"dot11BssType",
"dot11BssPhyType",
"lRssi",
"uLinkQuality",
"bInRegDomain",
"usBeaconPeriod",
"ullTimestamp",
"ullHostTimestamp",
"usCapabilityInformation",
"ulChCenterFrequency",
"wlanRateSet",
"ulIeOffset",
"ulIeSize");


public byte[] getInformationElement()
return this.getPointer()
.getByteArray(this.ulIeOffset.intValue(), this.ulIeSize.intValue());




package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.*;

import java.util.Arrays;
import java.util.List;

public class DOT11_SSID extends Structure

public static class ByReference extends DOT11_SSID implements Structure.ByReference




public static int DOT11_SSID_MAX_LENGTH = 32;

/**
* The length, in bytes, of the ucSSID array.
*/
public ULONG uSSIDLength;

/**
* The SSID. DOT11_SSID_MAX_LENGTH is set to 32.
*/
public byte[] ucSSID;

public DOT11_SSID()

ucSSID = new byte[DOT11_SSID_MAX_LENGTH];


@Override
protected List<String> getFieldOrder()

return Arrays.asList("uSSIDLength", "ucSSID");


@Override
public String toString()
if(uSSIDLength != null)
int ssidArrayLength = uSSIDLength.intValue();
if (ssidArrayLength > DOT11_SSID_MAX_LENGTH)
ssidArrayLength = DOT11_SSID_MAX_LENGTH;


return new String(Arrays.copyOfRange(ucSSID, 0, ssidArrayLength));
else
return "";





The results of the unit test are:



java.lang.AssertionError: should init WLAN BSS Entry data struct 
Expected :50
Actual :0


The assertion that fails is:



assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(50), subject.wlanBssEntries[0].uPhyId);










share|improve this question



















  • 1





    Welcome to Stack Overflow! I'm not sure but think your array initialization wlanBssEntries = new WlanBssEntry[dwNumberOfItems.intValue()]; won't work. You should do wlanBssEntries = (new WlanBssEntry()).toArray(dwNumberOfItems.intValue());. (Also JNA doesn't support 0 length arrays so the second part of your conditional is impossible: always initialize with at least 1 element.)

    – Daniel Widdis
    Mar 27 at 21:06






  • 1





    to be more clear, the new foo[] structure array only works on the Java side and does not initialize the structure object. You would have to initialize every individual foo in the array (non-contiguous native memory which wouldn't work well as an array parameter) or use toArray() to initialize the structures with contiguous native memory.

    – Daniel Widdis
    Mar 27 at 21:14






  • 1





    JNA iterates over the fields in your FieldOrder list, using reflection to get the mapped class so it knows their native size so it knows the offset. Are you sure your calculated offsets are correct?

    – Daniel Widdis
    Mar 28 at 15:39






  • 1





    I figured it out. I'll post my answer later but wanted to let you know so you don't spend your valuable time. In short, my problem was two fold. First, I did have an offset problem in the data that I was initializing. Second, I didn't place the data I was initializing at the "end" of the WlanBssList (starting at offset 8). Thank you for your help. Your mention of toArray helped and having another sounding board was all it took.

    – Aaron Bauman
    Mar 28 at 18:15






  • 1





    Glad you fixed it and that I could help!

    – Daniel Widdis
    Mar 28 at 18:33













1












1








1








The following unit test is intended to verify that a nested JNA data structure is properly parsed based on the data that gets passed into the constructor. The unit test properly checks when JNA initializes the 'parent' structure. However, the test fails when testing member variables of a nested structure. I suspect the problem to be that the unit test sets a pointer to a memory location that contains the data for the nested structure. Perhaps the Java Pointer isn't translating one-to-one to how C does it.



I tried placing the WlanBssEntry at the start of WlanBssEntry[] but that didn't provide any different results than how it is currently implemented. When I tried placing it contiguously, I did not call pointerToMem.setPointer(8, ...)



This is the unit test:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sevensignal.EyeQAgent.Models.Platform;
import com.sevensignal.EyeQAgent.Util.Utils;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeThat;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Utils.class)
public class WlanBssListTest

Pointer pWlanBssList;

private final static long OFFSET_TO_FIRST_WLAN_BSS_ENTRY = 1024;

@Before
public void setUp()
assumeThat(Utils.getPlatform(), equalTo(Platform.WINDOWS));
pWlanBssList = allocateMemory(65536);
initWlanBssEntryMemory(pWlanBssList, OFFSET_TO_FIRST_WLAN_BSS_ENTRY, 50);
initWlanBssListMemory(pWlanBssList, 12, 1, OFFSET_TO_FIRST_WLAN_BSS_ENTRY);


@Test
public void shouldSetTotalSize()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should set total size", new WinDef.DWORD(12), subject.dwTotalSize);


@Test
public void shouldSetNumberOfItems()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should set number of items", new WinDef.DWORD(1), subject.dwNumberOfItems);


@Test
public void shouldInitWlanBssEntries()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should init WLAN BSS Entries", 1, subject.wlanBssEntries.length);
assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(50), subject.wlanBssEntries[0].uPhyId);


@Test
public void shouldInitWlanBssEntriesWhenNoEntriesExist()
pWlanBssList.setInt(4, 0);
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should init WLAN BSS Entries when no entries exist", 0, subject.wlanBssEntries.length);


private Pointer allocateMemory(long size)
return new Memory(size).share(0);


private void initWlanBssListMemory(Pointer pointerToMem, int dwTotalSize, int dwNumberOfItems, long offsetToWlanBssEntry)
pointerToMem.setInt(0, dwTotalSize);
pointerToMem.setInt(4, dwNumberOfItems);
pointerToMem.setPointer(8, pointerToMem.share(offsetToWlanBssEntry));


private void initWlanBssEntryMemory(Pointer pointerToMem, long offsetToWlanBssEntry, long uPhyId)
final int PHY_ID_OFFSET = 40;
pointerToMem.setLong(offsetToWlanBssEntry + 0, 3);
pointerToMem.setByte(offsetToWlanBssEntry + 8, (byte)'T');
pointerToMem.setByte(offsetToWlanBssEntry + 9, (byte)'S');
pointerToMem.setByte(offsetToWlanBssEntry + 10, (byte)'T');
pointerToMem.setLong(offsetToWlanBssEntry + PHY_ID_OFFSET, uPhyId);




This is the WlanBssList class which is the highest level structure:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.DWORD;

import java.util.Arrays;
import java.util.List;

public class WlanBssList extends Structure

public DWORD dwTotalSize;
public DWORD dwNumberOfItems;
public WlanBssEntry[] wlanBssEntries;

public static class ByReference extends WlanBssList implements Structure.ByReference

public ByReference()




public ByReference(Pointer p)

super(p);



public WlanBssList()
wlanBssEntries = new WlanBssEntry[1];


public WlanBssList(Pointer p)
super(p);
dwTotalSize = new DWORD(p.getInt(0));
dwNumberOfItems = new DWORD(p.getInt(4));
if(dwNumberOfItems.intValue() > 0)
wlanBssEntries = new WlanBssEntry[dwNumberOfItems.intValue()];
readField("wlanBssEntries");
else
wlanBssEntries = new WlanBssEntry[0];



@Override
protected List<String> getFieldOrder()
return Arrays.asList("dwTotalSize", "dwNumberOfItems", "wlanBssEntries");




And these are the nested structures:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sevensignal.EyeQAgent.Models.InformationElementGetter;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.LONG;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinDef.ULONGLONG;
import com.sun.jna.platform.win32.WinDef.USHORT;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.List;

@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WlanBssEntry extends Structure implements InformationElementGetter

public DOT11_SSID dot11Ssid;
public ULONG uPhyId;
public DOT11_MAC_ADDRESS dot11Bssid;
public int dot11BssType;
public int dot11BssPhyType;
public LONG lRssi;
public ULONG uLinkQuality;
public boolean bInRegDomain;
public USHORT usBeaconPeriod;
public ULONGLONG ullTimestamp;
public ULONGLONG ullHostTimestamp;
public USHORT usCapabilityInformation;
public ULONG ulChCenterFrequency;
public WlanRateSet wlanRateSet;
public ULONG ulIeOffset;
public ULONG ulIeSize;

@Override
protected List<String> getFieldOrder()

return Arrays.asList("dot11Ssid",
"uPhyId",
"dot11Bssid",
"dot11BssType",
"dot11BssPhyType",
"lRssi",
"uLinkQuality",
"bInRegDomain",
"usBeaconPeriod",
"ullTimestamp",
"ullHostTimestamp",
"usCapabilityInformation",
"ulChCenterFrequency",
"wlanRateSet",
"ulIeOffset",
"ulIeSize");


public byte[] getInformationElement()
return this.getPointer()
.getByteArray(this.ulIeOffset.intValue(), this.ulIeSize.intValue());




package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.*;

import java.util.Arrays;
import java.util.List;

public class DOT11_SSID extends Structure

public static class ByReference extends DOT11_SSID implements Structure.ByReference




public static int DOT11_SSID_MAX_LENGTH = 32;

/**
* The length, in bytes, of the ucSSID array.
*/
public ULONG uSSIDLength;

/**
* The SSID. DOT11_SSID_MAX_LENGTH is set to 32.
*/
public byte[] ucSSID;

public DOT11_SSID()

ucSSID = new byte[DOT11_SSID_MAX_LENGTH];


@Override
protected List<String> getFieldOrder()

return Arrays.asList("uSSIDLength", "ucSSID");


@Override
public String toString()
if(uSSIDLength != null)
int ssidArrayLength = uSSIDLength.intValue();
if (ssidArrayLength > DOT11_SSID_MAX_LENGTH)
ssidArrayLength = DOT11_SSID_MAX_LENGTH;


return new String(Arrays.copyOfRange(ucSSID, 0, ssidArrayLength));
else
return "";





The results of the unit test are:



java.lang.AssertionError: should init WLAN BSS Entry data struct 
Expected :50
Actual :0


The assertion that fails is:



assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(50), subject.wlanBssEntries[0].uPhyId);










share|improve this question














The following unit test is intended to verify that a nested JNA data structure is properly parsed based on the data that gets passed into the constructor. The unit test properly checks when JNA initializes the 'parent' structure. However, the test fails when testing member variables of a nested structure. I suspect the problem to be that the unit test sets a pointer to a memory location that contains the data for the nested structure. Perhaps the Java Pointer isn't translating one-to-one to how C does it.



I tried placing the WlanBssEntry at the start of WlanBssEntry[] but that didn't provide any different results than how it is currently implemented. When I tried placing it contiguously, I did not call pointerToMem.setPointer(8, ...)



This is the unit test:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sevensignal.EyeQAgent.Models.Platform;
import com.sevensignal.EyeQAgent.Util.Utils;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeThat;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Utils.class)
public class WlanBssListTest

Pointer pWlanBssList;

private final static long OFFSET_TO_FIRST_WLAN_BSS_ENTRY = 1024;

@Before
public void setUp()
assumeThat(Utils.getPlatform(), equalTo(Platform.WINDOWS));
pWlanBssList = allocateMemory(65536);
initWlanBssEntryMemory(pWlanBssList, OFFSET_TO_FIRST_WLAN_BSS_ENTRY, 50);
initWlanBssListMemory(pWlanBssList, 12, 1, OFFSET_TO_FIRST_WLAN_BSS_ENTRY);


@Test
public void shouldSetTotalSize()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should set total size", new WinDef.DWORD(12), subject.dwTotalSize);


@Test
public void shouldSetNumberOfItems()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should set number of items", new WinDef.DWORD(1), subject.dwNumberOfItems);


@Test
public void shouldInitWlanBssEntries()
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should init WLAN BSS Entries", 1, subject.wlanBssEntries.length);
assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(50), subject.wlanBssEntries[0].uPhyId);


@Test
public void shouldInitWlanBssEntriesWhenNoEntriesExist()
pWlanBssList.setInt(4, 0);
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should init WLAN BSS Entries when no entries exist", 0, subject.wlanBssEntries.length);


private Pointer allocateMemory(long size)
return new Memory(size).share(0);


private void initWlanBssListMemory(Pointer pointerToMem, int dwTotalSize, int dwNumberOfItems, long offsetToWlanBssEntry)
pointerToMem.setInt(0, dwTotalSize);
pointerToMem.setInt(4, dwNumberOfItems);
pointerToMem.setPointer(8, pointerToMem.share(offsetToWlanBssEntry));


private void initWlanBssEntryMemory(Pointer pointerToMem, long offsetToWlanBssEntry, long uPhyId)
final int PHY_ID_OFFSET = 40;
pointerToMem.setLong(offsetToWlanBssEntry + 0, 3);
pointerToMem.setByte(offsetToWlanBssEntry + 8, (byte)'T');
pointerToMem.setByte(offsetToWlanBssEntry + 9, (byte)'S');
pointerToMem.setByte(offsetToWlanBssEntry + 10, (byte)'T');
pointerToMem.setLong(offsetToWlanBssEntry + PHY_ID_OFFSET, uPhyId);




This is the WlanBssList class which is the highest level structure:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.DWORD;

import java.util.Arrays;
import java.util.List;

public class WlanBssList extends Structure

public DWORD dwTotalSize;
public DWORD dwNumberOfItems;
public WlanBssEntry[] wlanBssEntries;

public static class ByReference extends WlanBssList implements Structure.ByReference

public ByReference()




public ByReference(Pointer p)

super(p);



public WlanBssList()
wlanBssEntries = new WlanBssEntry[1];


public WlanBssList(Pointer p)
super(p);
dwTotalSize = new DWORD(p.getInt(0));
dwNumberOfItems = new DWORD(p.getInt(4));
if(dwNumberOfItems.intValue() > 0)
wlanBssEntries = new WlanBssEntry[dwNumberOfItems.intValue()];
readField("wlanBssEntries");
else
wlanBssEntries = new WlanBssEntry[0];



@Override
protected List<String> getFieldOrder()
return Arrays.asList("dwTotalSize", "dwNumberOfItems", "wlanBssEntries");




And these are the nested structures:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sevensignal.EyeQAgent.Models.InformationElementGetter;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.LONG;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinDef.ULONGLONG;
import com.sun.jna.platform.win32.WinDef.USHORT;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.List;

@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WlanBssEntry extends Structure implements InformationElementGetter

public DOT11_SSID dot11Ssid;
public ULONG uPhyId;
public DOT11_MAC_ADDRESS dot11Bssid;
public int dot11BssType;
public int dot11BssPhyType;
public LONG lRssi;
public ULONG uLinkQuality;
public boolean bInRegDomain;
public USHORT usBeaconPeriod;
public ULONGLONG ullTimestamp;
public ULONGLONG ullHostTimestamp;
public USHORT usCapabilityInformation;
public ULONG ulChCenterFrequency;
public WlanRateSet wlanRateSet;
public ULONG ulIeOffset;
public ULONG ulIeSize;

@Override
protected List<String> getFieldOrder()

return Arrays.asList("dot11Ssid",
"uPhyId",
"dot11Bssid",
"dot11BssType",
"dot11BssPhyType",
"lRssi",
"uLinkQuality",
"bInRegDomain",
"usBeaconPeriod",
"ullTimestamp",
"ullHostTimestamp",
"usCapabilityInformation",
"ulChCenterFrequency",
"wlanRateSet",
"ulIeOffset",
"ulIeSize");


public byte[] getInformationElement()
return this.getPointer()
.getByteArray(this.ulIeOffset.intValue(), this.ulIeSize.intValue());




package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.*;

import java.util.Arrays;
import java.util.List;

public class DOT11_SSID extends Structure

public static class ByReference extends DOT11_SSID implements Structure.ByReference




public static int DOT11_SSID_MAX_LENGTH = 32;

/**
* The length, in bytes, of the ucSSID array.
*/
public ULONG uSSIDLength;

/**
* The SSID. DOT11_SSID_MAX_LENGTH is set to 32.
*/
public byte[] ucSSID;

public DOT11_SSID()

ucSSID = new byte[DOT11_SSID_MAX_LENGTH];


@Override
protected List<String> getFieldOrder()

return Arrays.asList("uSSIDLength", "ucSSID");


@Override
public String toString()
if(uSSIDLength != null)
int ssidArrayLength = uSSIDLength.intValue();
if (ssidArrayLength > DOT11_SSID_MAX_LENGTH)
ssidArrayLength = DOT11_SSID_MAX_LENGTH;


return new String(Arrays.copyOfRange(ucSSID, 0, ssidArrayLength));
else
return "";





The results of the unit test are:



java.lang.AssertionError: should init WLAN BSS Entry data struct 
Expected :50
Actual :0


The assertion that fails is:



assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(50), subject.wlanBssEntries[0].uPhyId);







java windows junit jna






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 27 at 20:27









Aaron BaumanAaron Bauman

163 bronze badges




163 bronze badges










  • 1





    Welcome to Stack Overflow! I'm not sure but think your array initialization wlanBssEntries = new WlanBssEntry[dwNumberOfItems.intValue()]; won't work. You should do wlanBssEntries = (new WlanBssEntry()).toArray(dwNumberOfItems.intValue());. (Also JNA doesn't support 0 length arrays so the second part of your conditional is impossible: always initialize with at least 1 element.)

    – Daniel Widdis
    Mar 27 at 21:06






  • 1





    to be more clear, the new foo[] structure array only works on the Java side and does not initialize the structure object. You would have to initialize every individual foo in the array (non-contiguous native memory which wouldn't work well as an array parameter) or use toArray() to initialize the structures with contiguous native memory.

    – Daniel Widdis
    Mar 27 at 21:14






  • 1





    JNA iterates over the fields in your FieldOrder list, using reflection to get the mapped class so it knows their native size so it knows the offset. Are you sure your calculated offsets are correct?

    – Daniel Widdis
    Mar 28 at 15:39






  • 1





    I figured it out. I'll post my answer later but wanted to let you know so you don't spend your valuable time. In short, my problem was two fold. First, I did have an offset problem in the data that I was initializing. Second, I didn't place the data I was initializing at the "end" of the WlanBssList (starting at offset 8). Thank you for your help. Your mention of toArray helped and having another sounding board was all it took.

    – Aaron Bauman
    Mar 28 at 18:15






  • 1





    Glad you fixed it and that I could help!

    – Daniel Widdis
    Mar 28 at 18:33












  • 1





    Welcome to Stack Overflow! I'm not sure but think your array initialization wlanBssEntries = new WlanBssEntry[dwNumberOfItems.intValue()]; won't work. You should do wlanBssEntries = (new WlanBssEntry()).toArray(dwNumberOfItems.intValue());. (Also JNA doesn't support 0 length arrays so the second part of your conditional is impossible: always initialize with at least 1 element.)

    – Daniel Widdis
    Mar 27 at 21:06






  • 1





    to be more clear, the new foo[] structure array only works on the Java side and does not initialize the structure object. You would have to initialize every individual foo in the array (non-contiguous native memory which wouldn't work well as an array parameter) or use toArray() to initialize the structures with contiguous native memory.

    – Daniel Widdis
    Mar 27 at 21:14






  • 1





    JNA iterates over the fields in your FieldOrder list, using reflection to get the mapped class so it knows their native size so it knows the offset. Are you sure your calculated offsets are correct?

    – Daniel Widdis
    Mar 28 at 15:39






  • 1





    I figured it out. I'll post my answer later but wanted to let you know so you don't spend your valuable time. In short, my problem was two fold. First, I did have an offset problem in the data that I was initializing. Second, I didn't place the data I was initializing at the "end" of the WlanBssList (starting at offset 8). Thank you for your help. Your mention of toArray helped and having another sounding board was all it took.

    – Aaron Bauman
    Mar 28 at 18:15






  • 1





    Glad you fixed it and that I could help!

    – Daniel Widdis
    Mar 28 at 18:33







1




1





Welcome to Stack Overflow! I'm not sure but think your array initialization wlanBssEntries = new WlanBssEntry[dwNumberOfItems.intValue()]; won't work. You should do wlanBssEntries = (new WlanBssEntry()).toArray(dwNumberOfItems.intValue());. (Also JNA doesn't support 0 length arrays so the second part of your conditional is impossible: always initialize with at least 1 element.)

– Daniel Widdis
Mar 27 at 21:06





Welcome to Stack Overflow! I'm not sure but think your array initialization wlanBssEntries = new WlanBssEntry[dwNumberOfItems.intValue()]; won't work. You should do wlanBssEntries = (new WlanBssEntry()).toArray(dwNumberOfItems.intValue());. (Also JNA doesn't support 0 length arrays so the second part of your conditional is impossible: always initialize with at least 1 element.)

– Daniel Widdis
Mar 27 at 21:06




1




1





to be more clear, the new foo[] structure array only works on the Java side and does not initialize the structure object. You would have to initialize every individual foo in the array (non-contiguous native memory which wouldn't work well as an array parameter) or use toArray() to initialize the structures with contiguous native memory.

– Daniel Widdis
Mar 27 at 21:14





to be more clear, the new foo[] structure array only works on the Java side and does not initialize the structure object. You would have to initialize every individual foo in the array (non-contiguous native memory which wouldn't work well as an array parameter) or use toArray() to initialize the structures with contiguous native memory.

– Daniel Widdis
Mar 27 at 21:14




1




1





JNA iterates over the fields in your FieldOrder list, using reflection to get the mapped class so it knows their native size so it knows the offset. Are you sure your calculated offsets are correct?

– Daniel Widdis
Mar 28 at 15:39





JNA iterates over the fields in your FieldOrder list, using reflection to get the mapped class so it knows their native size so it knows the offset. Are you sure your calculated offsets are correct?

– Daniel Widdis
Mar 28 at 15:39




1




1





I figured it out. I'll post my answer later but wanted to let you know so you don't spend your valuable time. In short, my problem was two fold. First, I did have an offset problem in the data that I was initializing. Second, I didn't place the data I was initializing at the "end" of the WlanBssList (starting at offset 8). Thank you for your help. Your mention of toArray helped and having another sounding board was all it took.

– Aaron Bauman
Mar 28 at 18:15





I figured it out. I'll post my answer later but wanted to let you know so you don't spend your valuable time. In short, my problem was two fold. First, I did have an offset problem in the data that I was initializing. Second, I didn't place the data I was initializing at the "end" of the WlanBssList (starting at offset 8). Thank you for your help. Your mention of toArray helped and having another sounding board was all it took.

– Aaron Bauman
Mar 28 at 18:15




1




1





Glad you fixed it and that I could help!

– Daniel Widdis
Mar 28 at 18:33





Glad you fixed it and that I could help!

– Daniel Widdis
Mar 28 at 18:33












1 Answer
1






active

oldest

votes


















1















I fixed the failing unit test. There were 2 problems when the data was initialized in the allocated memory.



First of all, the offset into the uPhyId was off by 4 because I thought the length field of the dot11Ssid was 8 rather than 4.



Secondly, the memory for the first WlanBssEntry is located at an offset of 8 into the WlanBssList structure.



Lastly, I changed how wlanBssEntries gets initialized to guarantee that the array of WlanBssEntry instances appear contiguously in memory. My unit tests passed even without this change. But per @Daniel Widdis recommendations plus some online documentation I figured it's best to follow recommended procedures. It gets initialized as follows:



wlanBssEntries = (WlanBssEntry[])(new WlanBssEntry()).toArray(dwNumberOfItems.intValue());



Here is the code for the passing unit test:



package com.sevensignal.EyeQAgent.Util.win32.struct;

import com.sevensignal.EyeQAgent.Models.Platform;
import com.sevensignal.EyeQAgent.Util.Utils;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeThat;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Utils.class)
public class WlanBssListTest

Pointer pWlanBssList;

private final static long OFFSET_TO_FIRST_WLAN_BSS_ENTRY = 8;
private final static int PHY_ID_OFFSET = 36;
private final static int WLAN_BSS_ENTRY_LENGTH = 360;

@Before
public void setUp()
assumeThat(Utils.getPlatform(), equalTo(Platform.WINDOWS));
pWlanBssList = allocateMemory(65536);


@Test
public void shouldSetTotalSize()
initWlanBssListMemory(pWlanBssList, 12, 1);
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should set total size", new WinDef.DWORD(12), subject.dwTotalSize);


@Test
public void shouldSetNumberOfItems()
initWlanBssListMemory(pWlanBssList, 12, 1);
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should set number of items", new WinDef.DWORD(1), subject.dwNumberOfItems);


@Test
public void shouldInitWlanBssEntries()
initWlanBssListMemory(pWlanBssList, 12, 1);
WlanBssList subject = new WlanBssList(pWlanBssList);
assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
new byte[]
(byte)'I', (byte)'D', (byte)'1', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
,
subject.wlanBssEntries[0].dot11Ssid.ucSSID);
assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(51), subject.wlanBssEntries[0].uPhyId);


@Test
public void shouldInitTwoWlanBssEntries()
initWlanBssListMemory(pWlanBssList, 12, 2);
WlanBssList subject = new WlanBssList(pWlanBssList);
assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
new byte[]
(byte)'I', (byte)'D', (byte)'1', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
,
subject.wlanBssEntries[0].dot11Ssid.ucSSID);
assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(51), subject.wlanBssEntries[0].uPhyId);

assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
new byte[]
(byte)'I', (byte)'D', (byte)'2', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
,
subject.wlanBssEntries[1].dot11Ssid.ucSSID);
assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(0xC2), subject.wlanBssEntries[1].uPhyId);


@Test
public void shouldInitWlanBssEntriesWhenNoEntriesExist()
initWlanBssListMemory(pWlanBssList, 12, 0);
WlanBssList subject = new WlanBssList(pWlanBssList);
assertEquals("should init WLAN BSS Entries when no entries exist", 0, subject.wlanBssEntries.length);


private Pointer allocateMemory(long size)
return new Memory(size).share(0);


private void initWlanBssListMemory(Pointer pointerToMem, int dwTotalSize, int dwNumberOfItems)
pointerToMem.setInt(0, dwTotalSize);
pointerToMem.setInt(4, dwNumberOfItems);
initWlanBssEntryMemory(pointerToMem);


private void initWlanBssEntryMemory(Pointer pointerToWlanBssEntryMem)
pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 0, 3);
pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 4, (byte)'I');
pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 5, (byte)'D');
pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 6, (byte)'1');
pointerToWlanBssEntryMem.setMemory(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 7, 29, (byte)0);
pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + PHY_ID_OFFSET, 51);

pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 0, 3);
pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 4, (byte)'I');
pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 5, (byte)'D');
pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 6, (byte)'2');
pointerToWlanBssEntryMem.setMemory(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 7, 29, (byte)0);
pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + PHY_ID_OFFSET, 0xC2);







share|improve this answer
























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55385907%2funexpected-error-when-unit-testing-nested-jna-structure-objects%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1















    I fixed the failing unit test. There were 2 problems when the data was initialized in the allocated memory.



    First of all, the offset into the uPhyId was off by 4 because I thought the length field of the dot11Ssid was 8 rather than 4.



    Secondly, the memory for the first WlanBssEntry is located at an offset of 8 into the WlanBssList structure.



    Lastly, I changed how wlanBssEntries gets initialized to guarantee that the array of WlanBssEntry instances appear contiguously in memory. My unit tests passed even without this change. But per @Daniel Widdis recommendations plus some online documentation I figured it's best to follow recommended procedures. It gets initialized as follows:



    wlanBssEntries = (WlanBssEntry[])(new WlanBssEntry()).toArray(dwNumberOfItems.intValue());



    Here is the code for the passing unit test:



    package com.sevensignal.EyeQAgent.Util.win32.struct;

    import com.sevensignal.EyeQAgent.Models.Platform;
    import com.sevensignal.EyeQAgent.Util.Utils;
    import com.sun.jna.Memory;
    import com.sun.jna.Pointer;
    import com.sun.jna.platform.win32.WinDef;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.PowerMockRunner;

    import static org.hamcrest.CoreMatchers.equalTo;
    import static org.junit.Assert.*;
    import static org.junit.Assume.assumeThat;

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(Utils.class)
    public class WlanBssListTest

    Pointer pWlanBssList;

    private final static long OFFSET_TO_FIRST_WLAN_BSS_ENTRY = 8;
    private final static int PHY_ID_OFFSET = 36;
    private final static int WLAN_BSS_ENTRY_LENGTH = 360;

    @Before
    public void setUp()
    assumeThat(Utils.getPlatform(), equalTo(Platform.WINDOWS));
    pWlanBssList = allocateMemory(65536);


    @Test
    public void shouldSetTotalSize()
    initWlanBssListMemory(pWlanBssList, 12, 1);
    WlanBssList subject = new WlanBssList(pWlanBssList);
    assertEquals("should set total size", new WinDef.DWORD(12), subject.dwTotalSize);


    @Test
    public void shouldSetNumberOfItems()
    initWlanBssListMemory(pWlanBssList, 12, 1);
    WlanBssList subject = new WlanBssList(pWlanBssList);
    assertEquals("should set number of items", new WinDef.DWORD(1), subject.dwNumberOfItems);


    @Test
    public void shouldInitWlanBssEntries()
    initWlanBssListMemory(pWlanBssList, 12, 1);
    WlanBssList subject = new WlanBssList(pWlanBssList);
    assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
    new byte[]
    (byte)'I', (byte)'D', (byte)'1', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
    ,
    subject.wlanBssEntries[0].dot11Ssid.ucSSID);
    assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(51), subject.wlanBssEntries[0].uPhyId);


    @Test
    public void shouldInitTwoWlanBssEntries()
    initWlanBssListMemory(pWlanBssList, 12, 2);
    WlanBssList subject = new WlanBssList(pWlanBssList);
    assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
    new byte[]
    (byte)'I', (byte)'D', (byte)'1', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
    ,
    subject.wlanBssEntries[0].dot11Ssid.ucSSID);
    assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(51), subject.wlanBssEntries[0].uPhyId);

    assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
    new byte[]
    (byte)'I', (byte)'D', (byte)'2', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
    ,
    subject.wlanBssEntries[1].dot11Ssid.ucSSID);
    assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(0xC2), subject.wlanBssEntries[1].uPhyId);


    @Test
    public void shouldInitWlanBssEntriesWhenNoEntriesExist()
    initWlanBssListMemory(pWlanBssList, 12, 0);
    WlanBssList subject = new WlanBssList(pWlanBssList);
    assertEquals("should init WLAN BSS Entries when no entries exist", 0, subject.wlanBssEntries.length);


    private Pointer allocateMemory(long size)
    return new Memory(size).share(0);


    private void initWlanBssListMemory(Pointer pointerToMem, int dwTotalSize, int dwNumberOfItems)
    pointerToMem.setInt(0, dwTotalSize);
    pointerToMem.setInt(4, dwNumberOfItems);
    initWlanBssEntryMemory(pointerToMem);


    private void initWlanBssEntryMemory(Pointer pointerToWlanBssEntryMem)
    pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 0, 3);
    pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 4, (byte)'I');
    pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 5, (byte)'D');
    pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 6, (byte)'1');
    pointerToWlanBssEntryMem.setMemory(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 7, 29, (byte)0);
    pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + PHY_ID_OFFSET, 51);

    pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 0, 3);
    pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 4, (byte)'I');
    pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 5, (byte)'D');
    pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 6, (byte)'2');
    pointerToWlanBssEntryMem.setMemory(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 7, 29, (byte)0);
    pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + PHY_ID_OFFSET, 0xC2);







    share|improve this answer





























      1















      I fixed the failing unit test. There were 2 problems when the data was initialized in the allocated memory.



      First of all, the offset into the uPhyId was off by 4 because I thought the length field of the dot11Ssid was 8 rather than 4.



      Secondly, the memory for the first WlanBssEntry is located at an offset of 8 into the WlanBssList structure.



      Lastly, I changed how wlanBssEntries gets initialized to guarantee that the array of WlanBssEntry instances appear contiguously in memory. My unit tests passed even without this change. But per @Daniel Widdis recommendations plus some online documentation I figured it's best to follow recommended procedures. It gets initialized as follows:



      wlanBssEntries = (WlanBssEntry[])(new WlanBssEntry()).toArray(dwNumberOfItems.intValue());



      Here is the code for the passing unit test:



      package com.sevensignal.EyeQAgent.Util.win32.struct;

      import com.sevensignal.EyeQAgent.Models.Platform;
      import com.sevensignal.EyeQAgent.Util.Utils;
      import com.sun.jna.Memory;
      import com.sun.jna.Pointer;
      import com.sun.jna.platform.win32.WinDef;
      import org.junit.Before;
      import org.junit.Test;
      import org.junit.runner.RunWith;
      import org.powermock.core.classloader.annotations.PrepareForTest;
      import org.powermock.modules.junit4.PowerMockRunner;

      import static org.hamcrest.CoreMatchers.equalTo;
      import static org.junit.Assert.*;
      import static org.junit.Assume.assumeThat;

      @RunWith(PowerMockRunner.class)
      @PrepareForTest(Utils.class)
      public class WlanBssListTest

      Pointer pWlanBssList;

      private final static long OFFSET_TO_FIRST_WLAN_BSS_ENTRY = 8;
      private final static int PHY_ID_OFFSET = 36;
      private final static int WLAN_BSS_ENTRY_LENGTH = 360;

      @Before
      public void setUp()
      assumeThat(Utils.getPlatform(), equalTo(Platform.WINDOWS));
      pWlanBssList = allocateMemory(65536);


      @Test
      public void shouldSetTotalSize()
      initWlanBssListMemory(pWlanBssList, 12, 1);
      WlanBssList subject = new WlanBssList(pWlanBssList);
      assertEquals("should set total size", new WinDef.DWORD(12), subject.dwTotalSize);


      @Test
      public void shouldSetNumberOfItems()
      initWlanBssListMemory(pWlanBssList, 12, 1);
      WlanBssList subject = new WlanBssList(pWlanBssList);
      assertEquals("should set number of items", new WinDef.DWORD(1), subject.dwNumberOfItems);


      @Test
      public void shouldInitWlanBssEntries()
      initWlanBssListMemory(pWlanBssList, 12, 1);
      WlanBssList subject = new WlanBssList(pWlanBssList);
      assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
      new byte[]
      (byte)'I', (byte)'D', (byte)'1', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
      (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
      (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
      (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
      ,
      subject.wlanBssEntries[0].dot11Ssid.ucSSID);
      assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(51), subject.wlanBssEntries[0].uPhyId);


      @Test
      public void shouldInitTwoWlanBssEntries()
      initWlanBssListMemory(pWlanBssList, 12, 2);
      WlanBssList subject = new WlanBssList(pWlanBssList);
      assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
      new byte[]
      (byte)'I', (byte)'D', (byte)'1', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
      (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
      (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
      (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
      ,
      subject.wlanBssEntries[0].dot11Ssid.ucSSID);
      assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(51), subject.wlanBssEntries[0].uPhyId);

      assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
      new byte[]
      (byte)'I', (byte)'D', (byte)'2', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
      (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
      (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
      (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
      ,
      subject.wlanBssEntries[1].dot11Ssid.ucSSID);
      assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(0xC2), subject.wlanBssEntries[1].uPhyId);


      @Test
      public void shouldInitWlanBssEntriesWhenNoEntriesExist()
      initWlanBssListMemory(pWlanBssList, 12, 0);
      WlanBssList subject = new WlanBssList(pWlanBssList);
      assertEquals("should init WLAN BSS Entries when no entries exist", 0, subject.wlanBssEntries.length);


      private Pointer allocateMemory(long size)
      return new Memory(size).share(0);


      private void initWlanBssListMemory(Pointer pointerToMem, int dwTotalSize, int dwNumberOfItems)
      pointerToMem.setInt(0, dwTotalSize);
      pointerToMem.setInt(4, dwNumberOfItems);
      initWlanBssEntryMemory(pointerToMem);


      private void initWlanBssEntryMemory(Pointer pointerToWlanBssEntryMem)
      pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 0, 3);
      pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 4, (byte)'I');
      pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 5, (byte)'D');
      pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 6, (byte)'1');
      pointerToWlanBssEntryMem.setMemory(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 7, 29, (byte)0);
      pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + PHY_ID_OFFSET, 51);

      pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 0, 3);
      pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 4, (byte)'I');
      pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 5, (byte)'D');
      pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 6, (byte)'2');
      pointerToWlanBssEntryMem.setMemory(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 7, 29, (byte)0);
      pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + PHY_ID_OFFSET, 0xC2);







      share|improve this answer



























        1














        1










        1









        I fixed the failing unit test. There were 2 problems when the data was initialized in the allocated memory.



        First of all, the offset into the uPhyId was off by 4 because I thought the length field of the dot11Ssid was 8 rather than 4.



        Secondly, the memory for the first WlanBssEntry is located at an offset of 8 into the WlanBssList structure.



        Lastly, I changed how wlanBssEntries gets initialized to guarantee that the array of WlanBssEntry instances appear contiguously in memory. My unit tests passed even without this change. But per @Daniel Widdis recommendations plus some online documentation I figured it's best to follow recommended procedures. It gets initialized as follows:



        wlanBssEntries = (WlanBssEntry[])(new WlanBssEntry()).toArray(dwNumberOfItems.intValue());



        Here is the code for the passing unit test:



        package com.sevensignal.EyeQAgent.Util.win32.struct;

        import com.sevensignal.EyeQAgent.Models.Platform;
        import com.sevensignal.EyeQAgent.Util.Utils;
        import com.sun.jna.Memory;
        import com.sun.jna.Pointer;
        import com.sun.jna.platform.win32.WinDef;
        import org.junit.Before;
        import org.junit.Test;
        import org.junit.runner.RunWith;
        import org.powermock.core.classloader.annotations.PrepareForTest;
        import org.powermock.modules.junit4.PowerMockRunner;

        import static org.hamcrest.CoreMatchers.equalTo;
        import static org.junit.Assert.*;
        import static org.junit.Assume.assumeThat;

        @RunWith(PowerMockRunner.class)
        @PrepareForTest(Utils.class)
        public class WlanBssListTest

        Pointer pWlanBssList;

        private final static long OFFSET_TO_FIRST_WLAN_BSS_ENTRY = 8;
        private final static int PHY_ID_OFFSET = 36;
        private final static int WLAN_BSS_ENTRY_LENGTH = 360;

        @Before
        public void setUp()
        assumeThat(Utils.getPlatform(), equalTo(Platform.WINDOWS));
        pWlanBssList = allocateMemory(65536);


        @Test
        public void shouldSetTotalSize()
        initWlanBssListMemory(pWlanBssList, 12, 1);
        WlanBssList subject = new WlanBssList(pWlanBssList);
        assertEquals("should set total size", new WinDef.DWORD(12), subject.dwTotalSize);


        @Test
        public void shouldSetNumberOfItems()
        initWlanBssListMemory(pWlanBssList, 12, 1);
        WlanBssList subject = new WlanBssList(pWlanBssList);
        assertEquals("should set number of items", new WinDef.DWORD(1), subject.dwNumberOfItems);


        @Test
        public void shouldInitWlanBssEntries()
        initWlanBssListMemory(pWlanBssList, 12, 1);
        WlanBssList subject = new WlanBssList(pWlanBssList);
        assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
        new byte[]
        (byte)'I', (byte)'D', (byte)'1', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
        ,
        subject.wlanBssEntries[0].dot11Ssid.ucSSID);
        assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(51), subject.wlanBssEntries[0].uPhyId);


        @Test
        public void shouldInitTwoWlanBssEntries()
        initWlanBssListMemory(pWlanBssList, 12, 2);
        WlanBssList subject = new WlanBssList(pWlanBssList);
        assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
        new byte[]
        (byte)'I', (byte)'D', (byte)'1', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
        ,
        subject.wlanBssEntries[0].dot11Ssid.ucSSID);
        assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(51), subject.wlanBssEntries[0].uPhyId);

        assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
        new byte[]
        (byte)'I', (byte)'D', (byte)'2', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
        ,
        subject.wlanBssEntries[1].dot11Ssid.ucSSID);
        assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(0xC2), subject.wlanBssEntries[1].uPhyId);


        @Test
        public void shouldInitWlanBssEntriesWhenNoEntriesExist()
        initWlanBssListMemory(pWlanBssList, 12, 0);
        WlanBssList subject = new WlanBssList(pWlanBssList);
        assertEquals("should init WLAN BSS Entries when no entries exist", 0, subject.wlanBssEntries.length);


        private Pointer allocateMemory(long size)
        return new Memory(size).share(0);


        private void initWlanBssListMemory(Pointer pointerToMem, int dwTotalSize, int dwNumberOfItems)
        pointerToMem.setInt(0, dwTotalSize);
        pointerToMem.setInt(4, dwNumberOfItems);
        initWlanBssEntryMemory(pointerToMem);


        private void initWlanBssEntryMemory(Pointer pointerToWlanBssEntryMem)
        pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 0, 3);
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 4, (byte)'I');
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 5, (byte)'D');
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 6, (byte)'1');
        pointerToWlanBssEntryMem.setMemory(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 7, 29, (byte)0);
        pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + PHY_ID_OFFSET, 51);

        pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 0, 3);
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 4, (byte)'I');
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 5, (byte)'D');
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 6, (byte)'2');
        pointerToWlanBssEntryMem.setMemory(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 7, 29, (byte)0);
        pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + PHY_ID_OFFSET, 0xC2);







        share|improve this answer













        I fixed the failing unit test. There were 2 problems when the data was initialized in the allocated memory.



        First of all, the offset into the uPhyId was off by 4 because I thought the length field of the dot11Ssid was 8 rather than 4.



        Secondly, the memory for the first WlanBssEntry is located at an offset of 8 into the WlanBssList structure.



        Lastly, I changed how wlanBssEntries gets initialized to guarantee that the array of WlanBssEntry instances appear contiguously in memory. My unit tests passed even without this change. But per @Daniel Widdis recommendations plus some online documentation I figured it's best to follow recommended procedures. It gets initialized as follows:



        wlanBssEntries = (WlanBssEntry[])(new WlanBssEntry()).toArray(dwNumberOfItems.intValue());



        Here is the code for the passing unit test:



        package com.sevensignal.EyeQAgent.Util.win32.struct;

        import com.sevensignal.EyeQAgent.Models.Platform;
        import com.sevensignal.EyeQAgent.Util.Utils;
        import com.sun.jna.Memory;
        import com.sun.jna.Pointer;
        import com.sun.jna.platform.win32.WinDef;
        import org.junit.Before;
        import org.junit.Test;
        import org.junit.runner.RunWith;
        import org.powermock.core.classloader.annotations.PrepareForTest;
        import org.powermock.modules.junit4.PowerMockRunner;

        import static org.hamcrest.CoreMatchers.equalTo;
        import static org.junit.Assert.*;
        import static org.junit.Assume.assumeThat;

        @RunWith(PowerMockRunner.class)
        @PrepareForTest(Utils.class)
        public class WlanBssListTest

        Pointer pWlanBssList;

        private final static long OFFSET_TO_FIRST_WLAN_BSS_ENTRY = 8;
        private final static int PHY_ID_OFFSET = 36;
        private final static int WLAN_BSS_ENTRY_LENGTH = 360;

        @Before
        public void setUp()
        assumeThat(Utils.getPlatform(), equalTo(Platform.WINDOWS));
        pWlanBssList = allocateMemory(65536);


        @Test
        public void shouldSetTotalSize()
        initWlanBssListMemory(pWlanBssList, 12, 1);
        WlanBssList subject = new WlanBssList(pWlanBssList);
        assertEquals("should set total size", new WinDef.DWORD(12), subject.dwTotalSize);


        @Test
        public void shouldSetNumberOfItems()
        initWlanBssListMemory(pWlanBssList, 12, 1);
        WlanBssList subject = new WlanBssList(pWlanBssList);
        assertEquals("should set number of items", new WinDef.DWORD(1), subject.dwNumberOfItems);


        @Test
        public void shouldInitWlanBssEntries()
        initWlanBssListMemory(pWlanBssList, 12, 1);
        WlanBssList subject = new WlanBssList(pWlanBssList);
        assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
        new byte[]
        (byte)'I', (byte)'D', (byte)'1', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
        ,
        subject.wlanBssEntries[0].dot11Ssid.ucSSID);
        assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(51), subject.wlanBssEntries[0].uPhyId);


        @Test
        public void shouldInitTwoWlanBssEntries()
        initWlanBssListMemory(pWlanBssList, 12, 2);
        WlanBssList subject = new WlanBssList(pWlanBssList);
        assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
        new byte[]
        (byte)'I', (byte)'D', (byte)'1', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
        ,
        subject.wlanBssEntries[0].dot11Ssid.ucSSID);
        assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(51), subject.wlanBssEntries[0].uPhyId);

        assertArrayEquals("should init SSID entry in WLAN BSS Entry data struct",
        new byte[]
        (byte)'I', (byte)'D', (byte)'2', (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
        ,
        subject.wlanBssEntries[1].dot11Ssid.ucSSID);
        assertEquals("should init WLAN BSS Entry data struct", new WinDef.LONG(0xC2), subject.wlanBssEntries[1].uPhyId);


        @Test
        public void shouldInitWlanBssEntriesWhenNoEntriesExist()
        initWlanBssListMemory(pWlanBssList, 12, 0);
        WlanBssList subject = new WlanBssList(pWlanBssList);
        assertEquals("should init WLAN BSS Entries when no entries exist", 0, subject.wlanBssEntries.length);


        private Pointer allocateMemory(long size)
        return new Memory(size).share(0);


        private void initWlanBssListMemory(Pointer pointerToMem, int dwTotalSize, int dwNumberOfItems)
        pointerToMem.setInt(0, dwTotalSize);
        pointerToMem.setInt(4, dwNumberOfItems);
        initWlanBssEntryMemory(pointerToMem);


        private void initWlanBssEntryMemory(Pointer pointerToWlanBssEntryMem)
        pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 0, 3);
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 4, (byte)'I');
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 5, (byte)'D');
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 6, (byte)'1');
        pointerToWlanBssEntryMem.setMemory(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + 7, 29, (byte)0);
        pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + PHY_ID_OFFSET, 51);

        pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 0, 3);
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 4, (byte)'I');
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 5, (byte)'D');
        pointerToWlanBssEntryMem.setByte(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 6, (byte)'2');
        pointerToWlanBssEntryMem.setMemory(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + 7, 29, (byte)0);
        pointerToWlanBssEntryMem.setLong(OFFSET_TO_FIRST_WLAN_BSS_ENTRY + WLAN_BSS_ENTRY_LENGTH + PHY_ID_OFFSET, 0xC2);








        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 28 at 20:48









        Aaron BaumanAaron Bauman

        163 bronze badges




        163 bronze badges





















            Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.







            Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.



















            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55385907%2funexpected-error-when-unit-testing-nested-jna-structure-objects%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

            용인 삼성생명 블루밍스 목차 통계 역대 감독 선수단 응원단 경기장 같이 보기 외부 링크 둘러보기 메뉴samsungblueminx.comeh선수 명단용인 삼성생명 블루밍스용인 삼성생명 블루밍스ehsamsungblueminx.comeheheheh

            155 수학 과학 기타 둘러보기 메뉴eh추가해eh문서를 완성해