@Test public void shouldMarshalValue() throws IOException { // Given: final StringValue val = StringValue.newBuilder().setValue("test").build(); // When: final byte[] buf; try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) { provider.writeTo(val, val.getClass(), null, EMPTY_ANNOTATIONS, MediaType.APPLICATION_JSON_TYPE, null, os); buf = os.toByteArray(); } // Then: assertTrue(provider.isReadable(StringValue.class, null, EMPTY_ANNOTATIONS, MediaType.APPLICATION_JSON_TYPE)); assertTrue(provider.isWriteable(StringValue.class, null, EMPTY_ANNOTATIONS, MediaType.APPLICATION_JSON_TYPE)); try (final ByteArrayInputStream is = new ByteArrayInputStream(buf)) { @SuppressWarnings("unchecked") final Class<Object> clazz = (Class) val.getClass(); final Object actual = provider.readFrom(clazz, null, EMPTY_ANNOTATIONS, MediaType.APPLICATION_JSON_TYPE, null, is); assertEquals(val, actual); } }
@Test public void shouldDeserializeUtf16Message() throws IOException { // Given: final String json = "{\"value\": \"Test\"}"; final Charset charset = Charset.forName("UTF-16"); final byte[] jsonBytes = json.getBytes(charset); final MediaType mediaType = new MediaType("application", "json", charset.name()); // When: final Object actual; try (final ByteArrayInputStream is = new ByteArrayInputStream(jsonBytes)) { @SuppressWarnings("unchecked") final Class<Object> clazz = (Class) StringValue.class; actual = provider.readFrom(clazz, null, EMPTY_ANNOTATIONS, mediaType, null, is); } // Then: final StringValue val = (StringValue) actual; assertEquals("Test", val.getValue()); }
@Test public void shouldParseCompatibleTypes() throws IOException { // Given: final StringValue val = StringValue.newBuilder().setValue("test").build(); // When: final byte[] buf; try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) { provider.writeTo(val, val.getClass(), null, EMPTY_ANNOTATIONS, ProtobufMediaType.MEDIA_TYPE, null, os); buf = os.toByteArray(); } // Then: assertTrue(provider.isReadable(BytesValue.class, null, EMPTY_ANNOTATIONS, ProtobufMediaType.MEDIA_TYPE)); assertTrue(provider.isWriteable(BytesValue.class, null, EMPTY_ANNOTATIONS, ProtobufMediaType.MEDIA_TYPE)); try (final ByteArrayInputStream is = new ByteArrayInputStream(buf)) { @SuppressWarnings("unchecked") final Class<Object> clazz = (Class) val.getClass(); final Object actual = provider.readFrom(clazz, null, EMPTY_ANNOTATIONS, ProtobufMediaType.MEDIA_TYPE, null, is); assertEquals(val, actual); } }
@Test public void sort_commands_by_timestamp() { final Command cmd1 = requestFactory.createCommand(StringValue.getDefaultInstance(), minutesAgo(1)); final Command cmd2 = requestFactory.createCommand(Int64Value.getDefaultInstance(), secondsAgo(30)); final Command cmd3 = requestFactory.createCommand(BoolValue.getDefaultInstance(), secondsAgo(5)); final List<Command> sortedCommands = newArrayList(cmd1, cmd2, cmd3); final List<Command> commandsToSort = newArrayList(cmd3, cmd1, cmd2); assertFalse(sortedCommands.equals(commandsToSort)); Commands.sort(commandsToSort); assertEquals(sortedCommands, commandsToSort); }
@Test public void create_wereBetween_predicate() { final Command command1 = requestFactory.createCommand(StringValue.getDefaultInstance(), minutesAgo(5)); final Command command2 = requestFactory.createCommand(Int64Value.getDefaultInstance(), minutesAgo(2)); final Command command3 = requestFactory.createCommand(BoolValue.getDefaultInstance(), secondsAgo(30)); final Command command4 = requestFactory.createCommand(BoolValue.getDefaultInstance(), secondsAgo(20)); final Command command5 = requestFactory.createCommand(BoolValue.getDefaultInstance(), secondsAgo(5)); final ImmutableList<Command> commands = ImmutableList.of(command1, command2, command3, command4, command5); final Iterable<Command> filter = Iterables.filter( commands, Commands.wereWithinPeriod(minutesAgo(3), secondsAgo(10)) ); assertEquals(3, FluentIterable.from(filter) .size()); }
@Test public void create_entity() { final long id = 1024L; final int version = 100500; final StringValue state = toMessage(getClass().getName()); final Timestamp timestamp = Time.getCurrentTime(); final VersionableEntity entity = givenEntity() .withId(id) .withVersion(version) .withState(state) .modifiedOn(timestamp) .build(); assertEquals(TestEntity.class, entity.getClass()); assertEquals(id, entity.getId()); assertEquals(state, entity.getState()); assertEquals(version, entity.getVersion().getNumber()); assertEquals(timestamp, entity.getVersion().getTimestamp()); }
@Test public void expose_playing_events_to_the_package() { final TestEventFactory eventFactory = TestEventFactory.newInstance(getClass()); final StringValue strValue = StringValue.newBuilder() .setValue("eins zwei drei") .build(); final Int32Value intValue = Int32Value.newBuilder().setValue(123).build(); final Version nextVersion = Versions.increment(projection.getVersion()); final Event e1 = eventFactory.createEvent(strValue, nextVersion); final Event e2 = eventFactory.createEvent(intValue, Versions.increment(nextVersion)); final boolean projectionChanged = Projection.play(projection, ImmutableList.of(e1, e2)); final String projectionState = projection.getState() .getValue(); assertTrue(projectionChanged); assertTrue(projectionState.contains(strValue.getValue())); assertTrue(projectionState.contains(String.valueOf(intValue.getValue()))); }
@Test public void log_error_if_dispatch_unknown_event() { final StringValue unknownEventMessage = StringValue.getDefaultInstance(); final Event event = GivenEvent.withMessage(unknownEventMessage); repository().dispatch(EventEnvelope.of(event)); TestProjectionRepository testRepo = (TestProjectionRepository)repository(); assertTrue(testRepo.getLastErrorEnvelope() instanceof EventEnvelope); assertEquals(Events.getMessage(event), testRepo.getLastErrorEnvelope() .getMessage()); assertEquals(event, testRepo.getLastErrorEnvelope().getOuterObject()); // It must be "illegal argument type" since projections of this repository // do not handle such events. assertTrue(testRepo.getLastException() instanceof IllegalArgumentException); }
@Test public void create_and_initialize_entity_instance() { final Long id = 100L; final Timestamp before = TimeTests.Past.secondsAgo(1); // Create and init the entity. final EntityClass<NanoEntity> entityClass = new EntityClass<>(NanoEntity.class); final AbstractVersionableEntity<Long, StringValue> entity = entityClass.createEntity(id); final Timestamp after = Time.getCurrentTime(); // The interval with a much earlier start to allow non-zero interval on faster computers. final Interval whileWeCreate = Intervals.between(before, after); assertEquals(id, entity.getId()); assertEquals(0, entity.getVersion() .getNumber()); assertTrue(Intervals.contains(whileWeCreate, entity.whenModified())); assertEquals(StringValue.getDefaultInstance(), entity.getState()); assertFalse(entity.isArchived()); assertFalse(entity.isDeleted()); }
@Test public void expose_external_dispatcher_that_delegates_onError() { final ExternalMessageDispatcher<String> extMessageDispatcher = delegatingDispatcher.getExternalDispatcher(); final TestEventFactory factory = TestEventFactory.newInstance(getClass()); final StringValue eventMsg = newUuidValue(); final Event event = factory.createEvent(eventMsg); final ExternalMessage externalMessage = ExternalMessages.of(event, BoundedContext.newName(getClass().getName())); final ExternalMessageEnvelope externalMessageEnvelope = ExternalMessageEnvelope.of(externalMessage, eventMsg); final RuntimeException exception = new RuntimeException("test external dispatcher delegating onError"); extMessageDispatcher.onError(externalMessageEnvelope,exception); assertTrue(delegate.onErrorCalled()); }
@Test public void create_iterating_router() { final StringValue commandMessage = toMessage("create_iterating_router"); final CommandContext commandContext = requestFactory.createCommandContext(); processManager.injectCommandBus(mock(CommandBus.class)); final IteratingCommandRouter router = processManager.newIteratingRouterFor(commandMessage, commandContext); assertNotNull(router); assertEquals(commandMessage, getMessage(router.getSource())); assertEquals(commandContext, router.getSource() .getContext()); }
@Test public void return_CommandRouted_from_routeFirst() throws Exception { final CommandRouted commandRouted = router().routeFirst(); assertSource(commandRouted); // Test that only only one command was produced by `routeFirst()`. assertEquals(1, commandRouted.getProducedCount()); // Test that there's only one produced command and it has correct message. final Command produced = commandRouted.getProduced(0); final StringValue commandMessage = Commands.getMessage(produced); assertEquals(messages().get(0), commandMessage); assertActorAndTenant(produced); // Test that the event contains messages to follow. assertEquals(messages().size() - 1, commandRouted.getMessageToFollowCount()); final List<Any> messageToFollow = commandRouted.getMessageToFollowList(); assertArrayEquals(messages().subList(1, messages().size()).toArray(), unpackAll(messageToFollow).toArray()); }
static Event validEvent() { final Command cmd = validCommand(); final PrjProjectCreated eventMessage = PrjProjectCreated.newBuilder() .setProjectId(ProjectId.newBuilder() .setId("12345AD0")) .build(); final StringValue producerId = toMessage(Given.class.getSimpleName()); final EventFactory eventFactory = EventFactory.on(CommandEnvelope.of(cmd), Identifier.pack(producerId)); final Event event = eventFactory.createEvent(eventMessage, Tests.<Version>nullRef()); final Event result = event.toBuilder() .setContext(event.getContext() .toBuilder() .setEnrichment(Enrichment.newBuilder() .setDoNotEnrich(true)) .build()) .build(); return result; }
@Test public void apply_default_route() { final TestActorRequestFactory factory = TestActorRequestFactory.newInstance(getClass()); // Replace the default route since we have custom command message. commandRouting.replaceDefault(customDefault) // Have custom route too. .route(StringValue.class, customRoute); final CommandEnvelope command = CommandEnvelope.of(factory.createCommand(Time.getCurrentTime())); final long id = commandRouting.apply(command.getMessage(), command.getCommandContext()); assertEquals(DEFAULT_ANSWER, id); }
@Test public void dispatch_event() { final TestEventFactory factory = TestEventFactory.newInstance(getClass()); final float messageValue = 2017.0729f; final FloatValue message = FloatValue.newBuilder() .setValue(messageValue) .build(); final EventEnvelope eventEnvelope = EventEnvelope.of(factory.createEvent(message)); final List<? extends Message> eventMessages = dispatchEvent(aggregate, eventEnvelope); assertTrue(aggregate.getState() .getValue() .contains(String.valueOf(messageValue))); assertEquals(1, eventMessages.size()); assertTrue(eventMessages.get(0) instanceof StringValue); }
@Override public Mono<UserProto> getUser(Mono<StringValue> request) { return request .map(StringValue::getValue) .doOnSuccess(login -> log.debug("gRPC request to get User : {}", login)) .map(login -> userService.getUserWithAuthoritiesByLogin(login).orElseThrow(Status.NOT_FOUND::asRuntimeException)) .map(userProtoMapper::userToUserProto); }
@Override public Mono<Empty> deleteUser(Mono<StringValue> request) { return request .map(StringValue::getValue) .doOnSuccess(login -> log.debug("gRPC request to delete User: {}", login)) .doOnSuccess(userService::deleteUser) .map(l -> Empty.newBuilder().build()); }
@Override public Flux<StringValue> getAllAuthorities(Mono<Empty> request) { return request .doOnSuccess(e -> log.debug("gRPC request to gat all authorities")) .filter(e -> SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) .switchIfEmpty(Mono.error(Status.PERMISSION_DENIED.asRuntimeException())) .flatMapIterable(e -> userService.getAuthorities()) .map(authority -> StringValue.newBuilder().setValue(authority).build()); }
@Override public Flux<UserProto> searchUsers(Mono<UserSearchPageRequest> request) { return request .map(UserSearchPageRequest::getQuery) .map(StringValue::getValue) .doOnSuccess(query -> log.debug("gRPC request to search Users for query {}", query)) .map(QueryBuilders::queryStringQuery) .flatMapMany(query -> request .map(UserSearchPageRequest::getPageRequest) .map(ProtobufMappers::pageRequestProtoToPageRequest) .flatMapIterable(pageRequest -> userSearchRepository.search(query, pageRequest)) ) .map(userProtoMapper::userToUserProto); }
@Override public Mono<StringValue> isAuthenticated(Mono<Empty> request) { return request.map(e -> { log.debug("gRPC request to check if the current user is authenticated"); Authentication principal = SecurityContextHolder.getContext().getAuthentication(); StringValue.Builder builder = StringValue.newBuilder(); if (principal != null) { builder.setValue(principal.getName()); } return builder.build(); }); }
@Override public Mono<UserProto> activateAccount(Mono<StringValue> request) { return request .map(StringValue::getValue) .map(key -> userService.activateRegistration(key).orElseThrow(Status.INTERNAL::asRuntimeException)) .map(userProtoMapper::userToUserProto); }
@Override public Mono<Empty> changePassword(Mono<StringValue> request) { return request .map(StringValue::getValue) .filter(AccountService::checkPasswordLength) .switchIfEmpty(Mono.error(Status.INVALID_ARGUMENT.withDescription("Incorrect password").asRuntimeException())) .doOnSuccess(userService::changePassword) .map(p -> Empty.newBuilder().build()); }
@Override public Mono<Empty> invalidateSession(Mono<StringValue> request) { return request .map(StringValue::getValue) .doOnSuccess(series -> SecurityUtils.getCurrentUserLogin() .flatMap(userRepository::findOneByLogin) .map(persistentTokenRepository::findByUser) .orElse(new ArrayList<>()) .stream() .filter(persistentToken -> StringUtils.equals(persistentToken.getSeries(), series)) .forEach(persistentTokenRepository::delete) ) .map(s -> Empty.newBuilder().build()); }
@Override public Mono<Empty> requestPasswordReset(Mono<StringValue> request) { return request .map(StringValue::getValue) .map(mail -> userService.requestPasswordReset(mail) .orElseThrow(Status.INVALID_ARGUMENT.withDescription("e-mail address not registered")::asRuntimeException) ) .doOnSuccess(mailService::sendPasswordResetMail) .map(u -> Empty.newBuilder().build()); }
public void getNonExistingUser() throws Exception { try { stub.getUser(StringValue.newBuilder().setValue("unknown").build()); failBecauseExceptionWasNotThrown(StatusRuntimeException.class); } catch (StatusRuntimeException e) { assertThat(e.getStatus().getCode()).isEqualTo(Status.Code.NOT_FOUND); } }
@Test public void testAuthenticatedUser() throws Exception { Authentication authentication = new TestingAuthenticationToken("grpc-authenticated-user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); StringValue login = stub.isAuthenticated(Empty.newBuilder().build()); assertThat(login.getValue()).isEqualTo("grpc-authenticated-user"); }
public void testActivateAccountWithWrongKey() throws Exception { try { stub.activateAccount(StringValue.newBuilder().setValue("some wrong key").build()); failBecauseExceptionWasNotThrown(StatusRuntimeException.class); } catch (StatusRuntimeException e) { assertThat(e.getStatus().getCode()).isEqualTo(Status.Code.INTERNAL); } }
@Test @DisplayName("produce CannotUpdateTaskDescription rejection") void produceRejection() { final CreateBasicTask createBasicTask = createTaskInstance(taskId, DESCRIPTION); dispatchCommand(aggregate, envelopeOf(createBasicTask)); final String expectedValue = "expected description"; final String newValue = "update description"; final String actualValue = createBasicTask.getDescription() .getValue(); final UpdateTaskDescription updateTaskDescription = updateTaskDescriptionInstance(taskId, expectedValue, newValue); final Throwable t = assertThrows(Throwable.class, () -> dispatchCommand(aggregate, envelopeOf(updateTaskDescription))); final Throwable cause = Throwables.getRootCause(t); assertThat(cause, instanceOf(CannotUpdateTaskDescription.class)); @SuppressWarnings("ConstantConditions") // Instance type checked before. final Rejections.CannotUpdateTaskDescription rejection = ((CannotUpdateTaskDescription) cause).getMessageThrown(); final DescriptionUpdateRejected rejectionDetails = rejection.getRejectionDetails(); final TaskId actualTaskId = rejectionDetails.getCommandDetails() .getTaskId(); assertEquals(taskId, actualTaskId); final StringValue expectedStringValue = toMessage(expectedValue); final StringValue actualStringValue = toMessage(actualValue); final StringValue newStringValue = toMessage(newValue); final ValueMismatch mismatch = rejectionDetails.getDescriptionMismatch(); assertEquals(expectedStringValue, unpack(mismatch.getExpected())); assertEquals(actualStringValue, unpack(mismatch.getActual())); assertEquals(newStringValue, unpack(mismatch.getNewValue())); }
@SuppressWarnings("UnnecessaryLocalVariable") /* We use more variables to make the code more readable in this example. This example has the same value for all UserIds, while the real import code would create IDs from imported data. */ private static List<Event> generateEvents(TaskId taskId) { final Task task = Task.newBuilder() .setId(taskId) .setName("Show how events can be imported into an aggregate") .build(); final String className = TaskImporter.class.getSimpleName(); final UserId taskOwner = Users.newUserId(className); final UserId assignee = taskOwner; // The ID of the entity, which produces events. final StringValue producerId = newStringValue(className); final ImmutableList.Builder<Event> builder = ImmutableList.builder(); final TaskCreated taskCreated = TaskCreated.newBuilder() .setTask(task) .build(); builder.add(createImportEvent(taskCreated, producerId)); final WorkStarted workStarted = WorkStarted.newBuilder() .setId(taskId) .setAssignee(assignee) .build(); builder.add(createImportEvent(workStarted, producerId)); final TaskDone taskDone = TaskDone.newBuilder().setId(taskId).build(); builder.add(createImportEvent(taskDone, producerId)); return builder.build(); }
public static void main(String[] args) { try (EnrichmentExample example = new EnrichmentExample(InMemoryStorageFactory.getInstance())) { // The ID of the entity, which produces events. final StringValue producerId = newStringValue(EnrichmentExample.class.getSimpleName()); final UserId userId = Users.newUserId("jdoe"); final PersonName name = PersonName .newBuilder() .setGivenName("John") .setFamilyName("Doe") .build(); // Post an event on user account creation. final UserAccountCreated accountCreated = UserAccountCreated .newBuilder() .setUserId(userId) .setName(name) .build(); final EventBus eventBus = example.boundedContext.getEventBus(); eventBus.post(createImportEvent(accountCreated, producerId)); final UserAccountSuspended accountSuspended = UserAccountSuspended .newBuilder() .setUserId(userId) .build(); eventBus.post(createImportEvent(accountSuspended, producerId)); //noinspection UseOfSystemOutOrSystemErr System.out.println("The End"); } catch (Exception e) { e.printStackTrace(); } }
/** * Creates additional types (Value, Struct and ListValue) to be added to the Service config. * TODO (guptasu): Fix this hack. Find a better way to add the predefined types. * TODO (guptasu): Add them only when required and not in all cases. */ static Iterable<Type> createAdditionalServiceTypes() { Map<String, DescriptorProto> additionalMessages = Maps.newHashMap(); additionalMessages.put(Struct.getDescriptor().getFullName(), Struct.getDescriptor().toProto()); additionalMessages.put(Value.getDescriptor().getFullName(), Value.getDescriptor().toProto()); additionalMessages.put(ListValue.getDescriptor().getFullName(), ListValue.getDescriptor().toProto()); additionalMessages.put(Empty.getDescriptor().getFullName(), Empty.getDescriptor().toProto()); additionalMessages.put(Int32Value.getDescriptor().getFullName(), Int32Value.getDescriptor().toProto()); additionalMessages.put(DoubleValue.getDescriptor().getFullName(), DoubleValue.getDescriptor().toProto()); additionalMessages.put(BoolValue.getDescriptor().getFullName(), BoolValue.getDescriptor().toProto()); additionalMessages.put(StringValue.getDescriptor().getFullName(), StringValue.getDescriptor().toProto()); for (Descriptor descriptor : Struct.getDescriptor().getNestedTypes()) { additionalMessages.put(descriptor.getFullName(), descriptor.toProto()); } // TODO (guptasu): Remove this hard coding. Without this, creation of Model from Service throws. // Needs investigation. String fileName = "struct.proto"; List<Type> additionalTypes = Lists.newArrayList(); for (String typeName : additionalMessages.keySet()) { additionalTypes.add(TypesBuilderFromDescriptor.createType(typeName, additionalMessages.get(typeName), fileName)); } return additionalTypes; }
@Test public void create_new_instances_with_current_time() { // We are creating a range of +/- second between the call to make sure the timestamp // would fit into this range. The purpose of this test is to make sure it works with // this precision and to add coverage. final Timestamp beforeCall = TimeTests.Past.secondsAgo(1); final Command command = factory().command() .create(StringValue.getDefaultInstance()); final Timestamp afterCall = TimeTests.Future.secondsFromNow(1); assertTrue(Timestamps2.isBetween( command.getContext() .getActorContext() .getTimestamp(), beforeCall, afterCall)); }
@Test public void create_new_instance_with_entity_version() { final Command command = factory().command() .create(StringValue.getDefaultInstance(), 2); assertEquals(2, command.getContext() .getTargetVersion()); }
@SuppressWarnings("OptionalGetWithoutIsPresent") // This test verifies that Optionals // are initialized. @Test public void stores_command_after_creation() { final StringValue commandMessage = newUuidValue(); final Command command = commandTest.createCommand(commandMessage); assertEquals(commandMessage, commandTest.commandMessage().get()); assertEquals(command.getContext(), commandTest.commandContext().get()); assertEquals(command, commandTest.command().get()); }
@Test public void pass_null_tolerance_test() { new NullPointerTester() .setDefault(FileDescriptor.class, DEFAULT_FILE_DESCRIPTOR) .setDefault(Timestamp.class, getCurrentTime()) .setDefault(Duration.class, Durations2.ZERO) .setDefault(Command.class, requestFactory.createCommand(StringValue.getDefaultInstance(), minutesAgo(1))) .setDefault(CommandContext.class, requestFactory.createCommandContext()) .setDefault(ZoneOffset.class, ZoneOffsets.UTC) .setDefault(UserId.class, GivenUserId.newUuid()) .testStaticMethods(Commands.class, NullPointerTester.Visibility.PACKAGE); }
@Test public void extract_message_from_command() { final StringValue message = toMessage("extract_message_from_command"); final Command command = requestFactory.createCommand(message); assertEquals(message, Commands.getMessage(command)); }
@Test public void when_command_delay_is_set_then_consider_it_scheduled() { final CommandContext context = GivenCommandContext.withScheduledDelayOf(seconds(10)); final Command cmd = requestFactory.command() .createBasedOnContext( StringValue.getDefaultInstance(), context); assertTrue(Commands.isScheduled(cmd)); }
@Test public void create_command_with_custom_Timestamp() { final StringValue commandMessage = newUuidValue(); final Timestamp timestamp = TimeTests.Past.minutesAgo(5); final Command command = commandTest.createCommand(commandMessage, timestamp); assertEquals(timestamp, command.getContext() .getActorContext() .getTimestamp()); }
/** * Creates a new command and checks its content. * * <p>If the method completes, we assume that the passed command test * has correctly working {@link ActorRequestFactory}. */ private static void createAndAssertCommand(CommandTest<StringValue> commandTest) { final StringValue commandMessage = newUuidValue(); final Command command = commandTest.createCommand(commandMessage); checkNotDefault(command); assertEquals(commandMessage, Commands.getMessage(command)); checkNotDefault(command.getContext()); }