Skip to content

Commit

Permalink
NPE fix (#254)
Browse files Browse the repository at this point in the history
  • Loading branch information
lumber1000 authored Mar 5, 2024
1 parent 74d139f commit e6e84ec
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 70 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,10 @@ A test event can have a reference to its parent, thus forming a hierarchical str

Events in a batch can have a reference only to the parent of the batch or other test events from the same batch. Events outside the batch should not reference events within the batch.

Test events have mandatory parameters that are verified when storing an event. These are: id, name (for non-batch events), start timestamp.
Test events have mandatory parameters that are verified when storing an event. These are: id, name (for non-batch events), start timestamp.

## Changes

### 5.1.5

* fixed: NullPointerException on AbstractMessageIteratorProvider creation for book with no pages in it.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id "io.github.gradle-nexus.publish-plugin" version "1.0.0"
id "org.owasp.dependencycheck" version "8.2.1"
id "io.github.gradle-nexus.publish-plugin" version "1.3.0"
id "org.owasp.dependencycheck" version "9.0.9"
id 'signing'
}

Expand Down
24 changes: 10 additions & 14 deletions cradle-cassandra/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
ext {
driver_version = '4.15.0'
}

configurations.configureEach {
exclude group: 'com.esri.geometry'
exclude group: 'org.apache.tinkerpop'
Expand All @@ -13,24 +9,24 @@ dependencies {
implementation "org.apache.commons:commons-lang3"
implementation 'com.exactpro.th2:task-utils:0.1.2'

implementation "com.datastax.oss:java-driver-core:${driver_version}"
implementation "com.datastax.oss:java-driver-query-builder:${driver_version}"
implementation "com.datastax.oss:java-driver-mapper-processor:${driver_version}"
implementation "com.datastax.oss:java-driver-mapper-runtime:${driver_version}"
implementation "com.datastax.oss:java-driver-core"
implementation "com.datastax.oss:java-driver-query-builder"
implementation "com.datastax.oss:java-driver-mapper-processor"
implementation "com.datastax.oss:java-driver-mapper-runtime"
implementation 'io.prometheus:simpleclient_dropwizard:0.16.0'
implementation 'com.google.guava:guava'

// this section is required to bypass failing vulnerability check caused by cassandra driver's transitive dependencies
annotationProcessor platform('com.exactpro.th2:bom:4.4.0')
annotationProcessor "com.datastax.oss:java-driver-mapper-processor:${driver_version}"
annotationProcessor platform('com.exactpro.th2:bom:4.5.0')
annotationProcessor "com.datastax.oss:java-driver-mapper-processor"
// ---

testImplementation 'org.testng:testng:7.7.0'
testImplementation 'org.assertj:assertj-core:3.12.2'
testImplementation 'org.testng:testng:7.9.0'
testImplementation 'org.assertj:assertj-core:3.25.3'
testImplementation "org.apache.logging.log4j:log4j-slf4j2-impl"
testImplementation 'org.apache.logging.log4j:log4j-core'
testImplementation 'org.mockito:mockito-core:5.2.0'
testImplementation 'org.testcontainers:cassandra:1.17.5'
testImplementation 'org.mockito:mockito-core:5.10.0'
testImplementation 'org.testcontainers:cassandra:1.19.6'
}

def gen_dir = 'build/generated/sources/annotationProcessor/main'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2023 Exactpro (Exactpro Systems Limited)
* Copyright 2021-2024 Exactpro (Exactpro Systems Limited)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -117,11 +117,14 @@ public AbstractMessageIteratorProvider(String requestInfo, MessageFilter filter,
}

//TODO refactor this method to assigns firstPage outside the method
protected FilterForGreater<Instant> createLeftBoundFilter(MessageFilter filter) throws CradleStorageException
{
protected FilterForGreater<Instant> createLeftBoundFilter(MessageFilter filter) throws CradleStorageException {
FilterForGreater<Instant> result = filter.getTimestampFrom();
firstPage = FilterUtils.findFirstPage(filter.getPageId(), result, book);
Instant leftBoundFromPage = firstPage.getStarted();

if (result == null && firstPage == null)
return null;

Instant leftBoundFromPage = firstPage == null ? Instant.MIN : firstPage.getStarted();
if (result == null || (filter.getPageId() != null && leftBoundFromPage.isAfter(result.getValue())))
return FilterForGreater.forGreaterOrEquals(leftBoundFromPage);

Expand All @@ -132,8 +135,7 @@ protected FilterForGreater<Instant> createLeftBoundFilter(MessageFilter filter)
filter.getDirection().getLabel(), leftBoundLocalDate.toLocalDate(),
leftBoundLocalDate.toLocalTime());

if (nearestBatchTime != null)
{
if (nearestBatchTime != null) {
Instant nearestBatchInstant = TimeUtils.toInstant(leftBoundLocalDate.toLocalDate(), nearestBatchTime);
if (nearestBatchInstant.isBefore(result.getValue()))
result = FilterForGreater.forGreaterOrEquals(nearestBatchInstant);
Expand Down Expand Up @@ -175,21 +177,19 @@ private LocalTime getNearestBatchTime(PageInfo page, String sessionAlias, String
}

//TODO refactor this method to assign last page outside of this method.
protected FilterForLess<Instant> createRightBoundFilter(MessageFilter filter)
{
protected FilterForLess<Instant> createRightBoundFilter(MessageFilter filter) {
FilterForLess<Instant> result = filter.getTimestampTo();
lastPage = FilterUtils.findLastPage(filter.getPageId(), result, book);
Instant endOfPage = lastPage.getEnded() == null ? Instant.now() : lastPage.getEnded();
Instant endOfPage = lastPage == null || lastPage.getEnded() == null ? Instant.now() : lastPage.getEnded();

return FilterForLess.forLessOrEquals(result == null || endOfPage.isBefore(result.getValue()) ? endOfPage : result.getValue());
}

protected CassandraStoredMessageFilter createInitialFilter(MessageFilter filter)
{
protected CassandraStoredMessageFilter createInitialFilter(MessageFilter filter) {
if (filter.getOrder() == Order.DIRECT) {
return new CassandraStoredMessageFilter(
firstPage.getId().getBookId().getName(),
firstPage.getId().getName(),
book.getId().getName(),
firstPage != null ? firstPage.getId().getName() : null,
filter.getSessionAlias(),
filter.getDirection().getLabel(),
leftBoundFilter,
Expand All @@ -198,17 +198,15 @@ protected CassandraStoredMessageFilter createInitialFilter(MessageFilter filter)
filter.getOrder());
} else {
return new CassandraStoredMessageFilter(
lastPage.getId().getBookId().getName(),
lastPage.getId().getName(),
book.getId().getName(),
lastPage != null ? lastPage.getId().getName() : null,
filter.getSessionAlias(),
filter.getDirection().getLabel(),
leftBoundFilter,
rightBoundFilter,
filter.getLimit(),
filter.getOrder());
}


}

protected CassandraStoredMessageFilter createNextFilter(CassandraStoredMessageFilter prevFilter, int updatedLimit)
Expand Down Expand Up @@ -240,22 +238,22 @@ protected CassandraStoredMessageFilter createNextFilter(CassandraStoredMessageFi
filter.getOrder());
}

protected boolean performNextIteratorChecks () {
protected boolean interruptIteratorChecks () {
if (cassandraFilter == null) {
return false;
return true;
}

if (takeWhileIterator != null && takeWhileIterator.isHalted()) {
logger.debug("Iterator was interrupted because iterator condition was not met");
return false;
return true;
}

if (limit > 0 && returned.get() >= limit) {
logger.debug("Filtering interrupted because limit for records to return ({}) is reached ({})", limit, returned);
return false;
return true;
}

return true;
return false;
}

protected Iterator<StoredMessageBatch> getBatchedIterator (MappedAsyncPagingIterable<MessageBatchEntity> resultSet) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2023 Exactpro (Exactpro Systems Limited)
* Copyright 2021-2024 Exactpro (Exactpro Systems Limited)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,7 +20,6 @@
import com.datastax.oss.driver.api.core.metadata.schema.ClusteringOrder;
import com.datastax.oss.driver.api.querybuilder.relation.MultiColumnRelationBuilder;
import com.datastax.oss.driver.api.querybuilder.select.Select;
import com.datastax.oss.driver.shaded.guava.common.base.Preconditions;
import com.exactpro.cradle.Order;
import com.exactpro.cradle.cassandra.dao.CassandraFilter;
import com.exactpro.cradle.cassandra.utils.FilterUtils;
Expand Down Expand Up @@ -84,14 +83,16 @@ public CassandraStoredMessageFilter(String book, String page, String sessionAlia
}

@Override
public Select addConditions(Select select)
{
public Select addConditions(Select select) {
select = select
.whereColumn(FIELD_BOOK).isEqualTo(bindMarker())
.whereColumn(FIELD_PAGE).isEqualTo(bindMarker())
.whereColumn(FIELD_SESSION_ALIAS).isEqualTo(bindMarker())
.whereColumn(FIELD_DIRECTION).isEqualTo(bindMarker());


if (page != null) {
select = select.whereColumn(FIELD_PAGE).isEqualTo(bindMarker());
}

if (sequence != null)
select = addMessageIdConditions(select);
else
Expand All @@ -115,14 +116,16 @@ public Select addConditions(Select select)
}

@Override
public BoundStatementBuilder bindParameters(BoundStatementBuilder builder)
{
public BoundStatementBuilder bindParameters(BoundStatementBuilder builder) {
builder = builder
.setString(FIELD_BOOK, book)
.setString(FIELD_PAGE, page)
.setString(FIELD_SESSION_ALIAS, sessionAlias)
.setString(FIELD_DIRECTION, direction);


if (page != null) {
builder = builder.setString(FIELD_PAGE, page);
}

if (sequence != null)
builder = bindMessageIdParameters(builder);
else
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2023 Exactpro (Exactpro Systems Limited)
* Copyright 2021-2024 Exactpro (Exactpro Systems Limited)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -38,15 +38,14 @@ public class MessageBatchesIteratorProvider extends AbstractMessageIteratorProvi

public MessageBatchesIteratorProvider(String requestInfo, MessageFilter filter, CassandraOperators operators, BookInfo book,
ExecutorService composingService, SelectQueryExecutor selectQueryExecutor,
Function<BoundStatementBuilder, BoundStatementBuilder> readAttrs) throws CradleStorageException
{
Function<BoundStatementBuilder, BoundStatementBuilder> readAttrs) throws CradleStorageException {
super(requestInfo, filter, operators, book, composingService, selectQueryExecutor, readAttrs);
}


@Override
public CompletableFuture<Iterator<StoredMessageBatch>> nextIterator() {
if (!performNextIteratorChecks()) {
if (interruptIteratorChecks()) {
return CompletableFuture.completedFuture(null);
}

Expand All @@ -55,4 +54,4 @@ public CompletableFuture<Iterator<StoredMessageBatch>> nextIterator() {
.thenApplyAsync(this::getBatchedIterator, composingService)
.thenApply(it -> limit > 0 ? new LimitedIterator<>(it, limit) : it);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2023 Exactpro (Exactpro Systems Limited)
* Copyright 2021-2024 Exactpro (Exactpro Systems Limited)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -36,15 +36,13 @@ public class MessagesIteratorProvider extends AbstractMessageIteratorProvider<St

public MessagesIteratorProvider(String requestInfo, MessageFilter filter, CassandraOperators operators, BookInfo book,
ExecutorService composingService, SelectQueryExecutor selectQueryExecutor,
Function<BoundStatementBuilder, BoundStatementBuilder> readAttrs) throws CradleStorageException
{
Function<BoundStatementBuilder, BoundStatementBuilder> readAttrs) throws CradleStorageException {
super(requestInfo, filter, operators, book, composingService, selectQueryExecutor, readAttrs);
}

@Override
public CompletableFuture<Iterator<StoredMessage>> nextIterator()
{
if (!performNextIteratorChecks()) {
public CompletableFuture<Iterator<StoredMessage>> nextIterator() {
if (interruptIteratorChecks()) {
return CompletableFuture.completedFuture(null);
}

Expand All @@ -53,4 +51,4 @@ public CompletableFuture<Iterator<StoredMessage>> nextIterator()
.thenApplyAsync(this::getBatchedIterator, composingService)
.thenApplyAsync(it -> new FilteredMessageIterator(it, filter, limit, returned), composingService);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2024 Exactpro (Exactpro Systems Limited)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.exactpro.cradle.cassandra.dao.messages;

import com.exactpro.cradle.BookId;
import com.exactpro.cradle.BookInfo;
import com.exactpro.cradle.Direction;
import com.exactpro.cradle.cassandra.dao.CassandraOperators;
import com.exactpro.cradle.messages.MessageFilter;
import com.exactpro.cradle.utils.CradleStorageException;
import org.mockito.Mockito;
import org.testng.annotations.Test;

import java.time.Instant;
import java.util.Collections;

public class MessagesIteratorProviderTest {
protected static final BookId DEFAULT_BOOK_ID = new BookId("test_book");
private static final String FIRST_SESSION_ALIAS = "test_session_alias";

@Test(description = "Create iterator provider with empty book")
public void createIteratorProviderWithEmptyBook() throws CradleStorageException {
CassandraOperators operators = Mockito.mock(CassandraOperators.class);
MessageFilter messageFilter = new MessageFilter(DEFAULT_BOOK_ID, FIRST_SESSION_ALIAS, Direction.FIRST, null);
new MessagesIteratorProvider(
"",
messageFilter,
operators,
new BookInfo(DEFAULT_BOOK_ID, "book_name", "", Instant.now(), Collections.emptyList()),
null,
null,
null
);
}
}
6 changes: 3 additions & 3 deletions cradle-core/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
dependencies {
api platform('com.exactpro.th2:bom:4.4.0')
api platform('com.exactpro.th2:bom:4.5.0')

implementation "com.fasterxml.jackson.core:jackson-databind"
implementation "org.apache.commons:commons-lang3"
Expand All @@ -10,8 +10,8 @@ dependencies {

testImplementation 'org.apache.logging.log4j:log4j-slf4j2-impl'
testImplementation 'org.apache.logging.log4j:log4j-core'
testImplementation 'org.testng:testng:7.7.0'
testImplementation 'org.assertj:assertj-core:3.12.2'
testImplementation 'org.testng:testng:7.9.0'
testImplementation 'org.assertj:assertj-core:3.25.3'
}

test {
Expand Down
Loading

0 comments on commit e6e84ec

Please sign in to comment.