[
https://issues.apache.org/jira/browse/IGNITE-22355?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17850479#comment-17850479
]
Mikhail Efremov edited comment on IGNITE-22355 at 5/29/24 7:26 PM:
-------------------------------------------------------------------
Due to [https://github.com/mockito/mockito/issues/2142] static mocks aren't
accessible from a different threads. I tired to use static mock as a field:
{code:java}
private MockedStatic<AffinityUtils> affinityUtilsStaticMock;
@BeforeEach
void before() throws NodeStoppingException {
affinityUtilsStaticMock = mockStatic(AffinityUtils.class);
// ...
}
// ...
private TableViewInternal mockManagersAndCreateTableWithDelay(
String tableName,
CompletableFuture<TableManager> tblManagerFut,
@Nullable Phaser phaser
) throws Exception {
// ...
ArrayList<List<ClusterNode>> assignment = new ArrayList<>(PARTITIONS);
for (int part = 0; part < PARTITIONS; part++) {
assignment.add(new ArrayList<>(Collections.singleton(node)));
}
affinityUtilsStaticMock.when(() ->
AffinityUtils.calculateAssignments(any(), anyInt(),
anyInt())).thenReturn(assignment);
TableManager tableManager = createTableManager(tblManagerFut);
// ...
}
// ...
void after() throws Exception {
ComponentContext componentContext = new ComponentContext();
closeAll(
// ...
affinityUtilsStaticMock
);
}
{code}
But inside inside {{TableManager#getOrCreateAssignments}} it didn't works, the
place:
{code:java}
assignmentsFuture = distributionZoneManager.dataNodes(causalityToken,
catalogVersion, zoneDescriptor.id())
.thenApply(dataNodes -> AffinityUtils.calculateAssignments(
dataNodes,
zoneDescriptor.partitions(),
zoneDescriptor.replicas()
)//...
{code}
returns a list with size {{zoneDescriptor.partitions()}} of empty node set as
the ticket describes as problem. In debug we can check is the mocking still
works with:
{code:java}
Mockito.mockingDetails(AffinityUtils.class).isMock()
{code}
and it returns {{false}}. In oppisite, we can check that after {{.when}}
statement the same check returns {{true}}.
The temporal solution is to mock {{DistributionZoneManager#dataNodes}} with
non-empty set with {{node1}} inside. Then, non-mocked
{{AffinityUtils#calculateAssignments}} returns a list with size
{{zoneDescriptor.partitions()}} (in the case partitions equals 32) of non-empty
node set with {{node1} inside as desired.
The test class demands rewriting, the related ticket must be created.
was (Author: JIRAUSER303791):
Due to [https://github.com/mockito/mockito/issues/2142] static mocks aren't
accessible from a different threads. I tired to use static mock as a field:
{code:java}
private MockedStatic<AffinityUtils> affinityUtilsStaticMock;
@BeforeEach
void before() throws NodeStoppingException {
affinityUtilsStaticMock = mockStatic(AffinityUtils.class);
// ...
}
// ...
private TableViewInternal mockManagersAndCreateTableWithDelay(
String tableName,
CompletableFuture<TableManager> tblManagerFut,
@Nullable Phaser phaser
) throws Exception {
// ...
ArrayList<List<ClusterNode>> assignment = new ArrayList<>(PARTITIONS);
for (int part = 0; part < PARTITIONS; part++) {
assignment.add(new ArrayList<>(Collections.singleton(node)));
}
affinityUtilsStaticMock.when(() ->
AffinityUtils.calculateAssignments(any(), anyInt(),
anyInt())).thenReturn(assignment);
TableManager tableManager = createTableManager(tblManagerFut);
// ...
}
// ...
void after() throws Exception {
ComponentContext componentContext = new ComponentContext();
closeAll(
// ...
affinityUtilsStaticMock
);
}
{code}
But inside inside {{TableManager#getOrCreateAssignments}} it didn't works, the
place:
{code:java}
assignmentsFuture = distributionZoneManager.dataNodes(causalityToken,
catalogVersion, zoneDescriptor.id())
.thenApply(dataNodes -> AffinityUtils.calculateAssignments(
dataNodes,
zoneDescriptor.partitions(),
zoneDescriptor.replicas()
)//...
{code}
returns a list with size {{zoneDescriptor.partitions()}} of empty node set as
the ticket describes as problem. In debug we can check is the mocking still
works with:
{code:java}
Mockito.mockingDetails(AffinityUtils.class).isMock()
{code}
and it returns {{false}}. In oppisite, we can check that after {{.when}}
statement the same check returns {{true}}.
The temporal solution is to mock {{DistributionZoneManager#dataNodes}} with
non-empty set with {{node1}} inside. Then, non-mocked
{{AffinityUtils#calculateAssignments}} returns a list with size
{{zoneDescriptor.partitions()}} (in the case partitions equals 32) of non-empty
node set with {{node1} inside as desired.
The test class demands rewriting, the related ticket must be created.
> TableManagerTest's static mocks from #mockManagersAndCreateTableWithDelay
> don't work properly
> ---------------------------------------------------------------------------------------------
>
> Key: IGNITE-22355
> URL: https://issues.apache.org/jira/browse/IGNITE-22355
> Project: Ignite
> Issue Type: Bug
> Reporter: Mikhail Efremov
> Assignee: Mikhail Efremov
> Priority: Major
> Labels: ignite-3
>
> *Description*
> In tests table creation method there is code like below:
>
> {code:java}
> try (MockedStatic<AffinityUtils> affinityServiceMock =
> mockStatic(AffinityUtils.class)) {
> ArrayList<List<ClusterNode>> assignment = new ArrayList<>(PARTITIONS);
> for (int part = 0; part < PARTITIONS; part++) {
> assignment.add(new ArrayList<>(Collections.singleton(node)));
> }
> affinityServiceMock.when(() -> AffinityUtils.calculateAssignments(any(),
> anyInt(), anyInt()))
> .thenReturn(assignment);
> }{code}
> As the result {{AffinityUtils#calculateAssignments}} calls outside of
> try-with-resources returns List of empty sets, but desired behavior is list
> of sets with the given {{{}node{}}}.
> *Definition of done*
> {{AffinityUtils#calculateAssignments}} call inside
> {{TableManager#getOrCreateAssignments}} must returns list of non-empty sets
> with single node.
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)