[ 
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:25 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)

Reply via email to