Skip to content
This repository has been archived by the owner on Jun 7, 2024. It is now read-only.

Commit

Permalink
Merge pull request #721 from zalando/ARUHA-979-name-rules-changes
Browse files Browse the repository at this point in the history
ARUHA-979: Allow number after dot in event-type name;
  • Loading branch information
v-stepanov authored Aug 3, 2017
2 parents 83299b5 + a082eee commit 82a3e2b
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 68 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed
- Now it's possible to have a digit after the dot in event-type name.

## [1.1.2] - 2017-08-01

### Changed
Expand Down
2 changes: 1 addition & 1 deletion docs/_data/nakadi-event-bus-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2154,7 +2154,7 @@ definitions:
follow a common pattern that makes it easy to read and understand, but this level of
structure is not enforced. For example a team name and data type can be used such as
'acme-team.price-change'.
pattern: '[a-zA-Z][-0-9a-zA-Z_]*(\.[a-zA-Z][-0-9a-zA-Z_]*)*'
pattern: '[a-zA-Z][-0-9a-zA-Z_]*(\.[0-9a-zA-Z][-0-9a-zA-Z_]*)*'
example: order.order_cancelled, acme-platform.users
owning_application:
type: string
Expand Down
27 changes: 14 additions & 13 deletions src/main/java/org/zalando/nakadi/domain/EventTypeBase.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
package org.zalando.nakadi.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.ImmutableList;
import org.zalando.nakadi.partitioning.PartitionStrategy;

import javax.annotation.Nullable;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import static java.util.Collections.unmodifiableList;

public class EventTypeBase {
public static final List<String> EMPTY_STRING_LIST = new ArrayList<>(0);

private static final List<String> EMPTY_PARTITION_KEY_FIELDS = ImmutableList.of();

@NotNull
@Pattern(regexp = "[a-zA-Z][-0-9a-zA-Z_]*(\\.[a-zA-Z][-0-9a-zA-Z_]*)*", message = "format not allowed" )
@Pattern(regexp = "[a-zA-Z][-0-9a-zA-Z_]*(\\.[0-9a-zA-Z][-0-9a-zA-Z_]*)*", message = "format not allowed")
@Size(min = 1, max = 255, message = "the length of the name must be >= 1 and <= 255")
private String name;

Expand Down Expand Up @@ -74,15 +75,15 @@ public EventTypeBase() {
}

public EventTypeBase(final String name, final String topic, final String owningApplication,
final EventCategory category,
final List<ValidationStrategyConfiguration> validationStrategies,
final List<EnrichmentStrategyDescriptor> enrichmentStrategies,
final String partitionStrategy,
final List<String> partitionKeyFields, final EventTypeSchemaBase schema,
final EventTypeStatistics defaultStatistic,
final EventTypeOptions options, final Set<String> writeScopes,
final Set<String> readScopes,
final CompatibilityMode compatibilityMode) {
final EventCategory category,
final List<ValidationStrategyConfiguration> validationStrategies,
final List<EnrichmentStrategyDescriptor> enrichmentStrategies,
final String partitionStrategy,
final List<String> partitionKeyFields, final EventTypeSchemaBase schema,
final EventTypeStatistics defaultStatistic,
final EventTypeOptions options, final Set<String> writeScopes,
final Set<String> readScopes,
final CompatibilityMode compatibilityMode) {
this.name = name;
this.topic = topic;
this.owningApplication = owningApplication;
Expand Down Expand Up @@ -170,7 +171,7 @@ public void setDefaultStatistic(final EventTypeStatistics defaultStatistic) {
}

public List<String> getPartitionKeyFields() {
return unmodifiableList(partitionKeyFields != null ? partitionKeyFields : EMPTY_STRING_LIST);
return unmodifiableList(partitionKeyFields != null ? partitionKeyFields : EMPTY_PARTITION_KEY_FIELDS);
}

public void setPartitionKeyFields(final List<String> partitionKeyFields) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,14 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.io.Resources;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeoutException;
import javax.ws.rs.core.Response;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;
import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE;
import static org.hamcrest.Matchers.containsString;
import org.hamcrest.core.StringContains;
import org.json.JSONObject;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.zalando.nakadi.config.SecuritySettings;
import org.zalando.nakadi.domain.EnrichmentStrategyDescriptor;
import static org.zalando.nakadi.domain.EventCategory.BUSINESS;
import org.zalando.nakadi.domain.EventType;
import org.zalando.nakadi.domain.EventTypeAuthorization;
import org.zalando.nakadi.domain.EventTypeAuthorizationAttribute;
Expand All @@ -62,28 +35,92 @@
import org.zalando.nakadi.repository.TopicRepository;
import org.zalando.nakadi.utils.EventTypeTestBuilder;
import org.zalando.nakadi.utils.TestUtils;
import static org.zalando.nakadi.utils.TestUtils.buildDefaultEventType;
import static org.zalando.nakadi.utils.TestUtils.invalidProblem;
import static org.zalando.nakadi.utils.TestUtils.randomValidEventTypeName;
import org.zalando.problem.MoreStatus;
import org.zalando.problem.Problem;
import org.zalando.problem.ThrowableProblem;

import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeoutException;

import static javax.ws.rs.core.Response.Status.NOT_FOUND;
import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.zalando.nakadi.domain.EventCategory.BUSINESS;
import static org.zalando.nakadi.utils.TestUtils.buildDefaultEventType;
import static org.zalando.nakadi.utils.TestUtils.invalidProblem;
import static org.zalando.nakadi.utils.TestUtils.randomValidEventTypeName;

public class EventTypeControllerTest extends EventTypeControllerTestCase {

public EventTypeControllerTest() throws IOException {
}

@Test
public void eventTypeWithEmptyNameReturns422() throws Exception {
final EventType invalidEventType = buildDefaultEventType();
invalidEventType.setName("?");
public void whenPostEventTypeWithIncorrectNameThen422() throws Exception {
final List<String> incorrectNames = ImmutableList.of(
"?",
"56mycoolET",
"abc^%!",
"myET.-abc",
"abc._def",
"_underscore",
"-event",
"many..dots",
".firstDot"
);
for (final String etName : incorrectNames) {
final EventType invalidEventType = buildDefaultEventType();
invalidEventType.setName(etName);

final Problem expectedProblem = invalidProblem("name", "format not allowed");
final Problem expectedProblem = invalidProblem("name", "format not allowed");
postETAndExpect422WithProblem(invalidEventType, expectedProblem);
}
}

postEventType(invalidEventType).andExpect(status().isUnprocessableEntity())
.andExpect(content().contentType("application/problem+json")).andExpect(content()
.string(matchesProblem(expectedProblem)));
@Test
public void whenPostEventTypeWithCorrectNameThen201() throws Exception {
final List<String> correctNames = ImmutableList.of(
"myET",
"my-team.cool_event_type",
"event-type.391.16afg",
"eventType.59fc6871-b556-65a1-8b90-3dfff9d76f34"
);
for (final String etName : correctNames) {
final EventType eventType = buildDefaultEventType();
eventType.setName(etName);
postEventType(eventType).andExpect(status().isCreated()).andExpect(content().string(""));
}
}

@Test
public void whenPostEventTypeWithTooLongNameThen422() throws Exception {
final EventType invalidEventType = buildDefaultEventType();
invalidEventType.setName(TestUtils.randomValidStringOfLength(256));
final Problem expectedProblem = invalidProblem("name", "the length of the name must be >= 1 and <= 255");
postETAndExpect422WithProblem(invalidEventType, expectedProblem);
}

@Test
Expand All @@ -92,10 +129,7 @@ public void eventTypeWithoutSchemaReturns422() throws Exception {
invalidEventType.setSchema(null);

final Problem expectedProblem = invalidProblem("schema", "may not be null");

postEventType(invalidEventType).andExpect(status().isUnprocessableEntity())
.andExpect(content().contentType("application/problem+json")).andExpect(content()
.string(matchesProblem(expectedProblem)));
postETAndExpect422WithProblem(invalidEventType, expectedProblem);
}

@Test
Expand All @@ -104,10 +138,7 @@ public void whenPostWithEventTypeNameNotSetThenReturn422() throws Exception {
invalidEventType.setName(null);

final Problem expectedProblem = invalidProblem("name", "may not be null");

postEventType(invalidEventType).andExpect(status().isUnprocessableEntity())
.andExpect(content().contentType("application/problem+json")).andExpect(content()
.string(matchesProblem(expectedProblem)));
postETAndExpect422WithProblem(invalidEventType, expectedProblem);
}

@Test
Expand All @@ -118,10 +149,7 @@ public void whenPostWithNoCategoryThenReturn422() throws Exception {
jsonObject.remove("category");

final Problem expectedProblem = invalidProblem("category", "may not be null");

postEventType(jsonObject.toString()).andExpect(status().isUnprocessableEntity())
.andExpect(content().contentType("application/problem+json")).andExpect(
content().string(matchesProblem(expectedProblem)));
postETAndExpect422WithProblem(jsonObject.toString(), expectedProblem);
}

@Test
Expand All @@ -131,9 +159,7 @@ public void whenPostWithNoSchemaSchemaThenReturn422() throws Exception {
final String eventType = "{\"category\": \"data\", \"owning_application\": \"blah-app\", "
+ "\"name\": \"blah-event-type\", \"schema\": { \"type\": \"JSON_SCHEMA\" }}";

postEventType(eventType).andExpect(status().isUnprocessableEntity())
.andExpect(content().contentType("application/problem+json")).andExpect(content()
.string(matchesProblem(expectedProblem)));
postETAndExpect422WithProblem(eventType, expectedProblem);
}

@Test
Expand Down Expand Up @@ -263,7 +289,17 @@ public void whenPUTwithPartitionStrategyChangeFromUserDefinedToRandomThen422() t

private void postETAndExpect422WithProblem(final EventType eventType, final Problem expectedProblem)
throws Exception {
postEventType(eventType)
expect422WithProblem(postEventType(eventType), expectedProblem);
}

private void postETAndExpect422WithProblem(final String eventType, final Problem expectedProblem)
throws Exception {
expect422WithProblem(postEventType(eventType), expectedProblem);
}

private void expect422WithProblem(final ResultActions resultActions, final Problem expectedProblem)
throws Exception {
resultActions
.andExpect(status().isUnprocessableEntity())
.andExpect(content().contentType("application/problem+json"))
.andExpect(content().string(matchesProblem(expectedProblem)));
Expand Down

0 comments on commit 82a3e2b

Please sign in to comment.