Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<version>3.14.0</version>
<configuration>
<target>1.8</target>
<source>1.8</source>
Expand All @@ -146,6 +146,8 @@
<!-- Silence warning "No processor claimed any of these annotations". One of the
annotations that would trigger it is org.junit.jupiter.api.Test -->
<arg>-Xlint:-processing</arg>
<!-- Silence warnning "source value 8 is obsolete and will be removed in a future release" -->
<arg>-Xlint:-options</arg>
</compilerArgs>
</configuration>
</plugin>
Expand Down
5 changes: 5 additions & 0 deletions scheme/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,10 @@
<artifactId>log4j-slf4j-impl</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>tech.ydb.test</groupId>
<artifactId>ydb-junit4-support</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,23 @@
*/
public class DescribePathResult {
private final SchemeOperationProtos.Entry self;
private final Entry entry;

protected DescribePathResult(SchemeOperationProtos.Entry self) {
this.self = self;
this.entry = new Entry(self);
}

public DescribePathResult(SchemeOperationProtos.DescribePathResult result) {
this(result.getSelf());
}

@Deprecated
public SchemeOperationProtos.Entry getSelf() {
return self;
}

public Entry getEntry() {
return entry;
}
}
85 changes: 85 additions & 0 deletions scheme/src/main/java/tech/ydb/scheme/description/Entry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package tech.ydb.scheme.description;

import java.util.Objects;

import tech.ydb.proto.scheme.SchemeOperationProtos;

/**
*
* @author Aleksandr Gorshenin
*/
public class Entry {
private final String name;
private final String owner;
private final EntryType type;
private final long sizeBytes;

public Entry(SchemeOperationProtos.Entry pb) {
this.name = pb.getName();
this.owner = pb.getOwner();
this.type = EntryType.fromCode(pb.getTypeValue());
this.sizeBytes = pb.getSizeBytes();
}

/**
* @return Name of scheme entry (dir2 of /dir1/dir2)
*/
public String getName() {
return this.name;
}

/**
* @return SID (Security ID) of user or group
*/
public String getOwner() {
return this.owner;
}

/**
* Approximate size of entry in bytes. Currently filled for:
* <ul>
* <li> TABLE </li>
* <li> DATABASE </li>
* </ul>
* Empty (zero) in other cases.
*
* @return Size of entry in bytes
*/
public long getSizeBytes() {
return this.sizeBytes;
}

public EntryType getType() {
return this.type;
}

@Override
public int hashCode() {
return Objects.hash(name, owner, type, sizeBytes);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || obj.getClass() != Entry.class) {
return false;
}
Entry o = (Entry) obj;
return Objects.equals(name, o.name)
&& Objects.equals(owner, o.owner)
&& type == o.type
&& sizeBytes == o.sizeBytes;
}

@Override
public String toString() {
return "Entry{name='" + name + "'"
+ (owner == null || owner.isEmpty() ? "" : ", owner='" + owner + "'")
+ ", type=" + type
+ (sizeBytes == 0 ? "" : ", size=" + Long.toUnsignedString(sizeBytes))
+ "}";
}
}

44 changes: 44 additions & 0 deletions scheme/src/main/java/tech/ydb/scheme/description/EntryType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package tech.ydb.scheme.description;

/**
*
* @author Aleksandr Gorshenin
*/
public enum EntryType {
UNSPECIFIED(0),

DIRECTORY(1),
TABLE(2),
PERS_QUEUE_GROUP(3),
DATABASE(4),
RTMR_VOLUME(5),
BLOCK_STORE_VOLUME(6),
COORDINATION_NODE(7),
COLUMN_STORE(12),
COLUMN_TABLE(13),
SEQUENCE(15),
REPLICATION(16),
TOPIC(17),
EXTERNAL_TABLE(18),
EXTERNAL_DATA_SOURCE(19),
VIEW(20);

private final int code;

EntryType(int code) {
this.code = code;
}

public int getCode() {
return code;
}

public static EntryType fromCode(int code) {
for (EntryType type: EntryType.values()) {
if (code == type.code) {
return type;
}
}
return UNSPECIFIED;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tech.ydb.scheme.description;

import java.util.List;
import java.util.stream.Collectors;

import tech.ydb.proto.scheme.SchemeOperationProtos;

Expand All @@ -10,13 +11,20 @@
public class ListDirectoryResult extends DescribePathResult {

private final List<SchemeOperationProtos.Entry> children;
private final List<Entry> entryChildren;

public ListDirectoryResult(SchemeOperationProtos.ListDirectoryResult result) {
super(result.getSelf());
this.children = result.getChildrenList();
this.entryChildren = result.getChildrenList().stream().map(Entry::new).collect(Collectors.toList());
}

@Deprecated
public List<SchemeOperationProtos.Entry> getChildren() {
return children;
}

public List<Entry> getEntryChildren() {
return entryChildren;
}
}
117 changes: 117 additions & 0 deletions scheme/src/test/java/tech/ydb/scheme/BaseIntegrationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package tech.ydb.scheme;

import java.util.Optional;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Test;

import tech.ydb.core.Result;
import tech.ydb.core.Status;
import tech.ydb.core.StatusCode;
import tech.ydb.scheme.description.DescribePathResult;
import tech.ydb.scheme.description.Entry;
import tech.ydb.scheme.description.EntryType;
import tech.ydb.scheme.description.ListDirectoryResult;
import tech.ydb.test.junit4.GrpcTransportRule;

/**
*
* @author Aleksandr Gorshenin
*/
public class BaseIntegrationTest {
@ClassRule
public final static GrpcTransportRule transport = new GrpcTransportRule();

private final static SchemeClient client = SchemeClient.newClient(transport).build();

@AfterClass
public static void close() {
client.close();
}

@Test
public void rootPathTest() {
Result<DescribePathResult> describeRoot = client.describePath("/").join();
Assert.assertTrue(describeRoot.isSuccess());
DescribePathResult root = describeRoot.getValue();
Assert.assertEquals("/", root.getEntry().getName());
Assert.assertEquals("", root.getEntry().getOwner());

Result<ListDirectoryResult> listRoot = client.listDirectory("/").join();
Assert.assertTrue(listRoot.isSuccess());
ListDirectoryResult listResult = listRoot.getValue();
Assert.assertEquals("/", listResult.getEntry().getName());
Assert.assertEquals("", listResult.getEntry().getOwner());
Assert.assertEquals("/", listResult.getEntry().getName());
Assert.assertEquals(0l, listResult.getEntry().getSizeBytes());
Assert.assertEquals(EntryType.DIRECTORY, listResult.getEntry().getType());
Assert.assertEquals("Entry{name='/', type=DIRECTORY}", listResult.getEntry().toString());


Assert.assertEquals(1, listResult.getEntryChildren().size());
listResult.getEntryChildren().get(0);
Entry firstChild = listResult.getEntryChildren().get(0);
Assert.assertTrue(transport.getDatabase().startsWith("/" + firstChild.getName()));
Assert.assertEquals(EntryType.DIRECTORY, firstChild.getType());
}

@Test
public void invalidPathTest() {
Result<DescribePathResult> describeInvalid = client.describePath("/invalid-path").join();
Assert.assertFalse(describeInvalid.isSuccess());
Assert.assertEquals(StatusCode.SCHEME_ERROR, describeInvalid.getStatus().getCode());
Assert.assertEquals(
"Status{code = SCHEME_ERROR(code=400070), issues = [Root not found (S_ERROR)]}",
describeInvalid.getStatus().toString()
);

Result<ListDirectoryResult> listInvalid = client.listDirectory("/invalid-path").join();
Assert.assertFalse(listInvalid.isSuccess());
Assert.assertEquals(StatusCode.SCHEME_ERROR, listInvalid.getStatus().getCode());
Assert.assertEquals(
"Status{code = SCHEME_ERROR(code=400070), issues = [Root not found (S_ERROR)]}",
listInvalid.getStatus().toString()
);

Status makeDirectory= client.makeDirectory("/invalid-path").join();
Assert.assertFalse(makeDirectory.isSuccess());
Assert.assertEquals(StatusCode.BAD_REQUEST, makeDirectory.getCode());

Status removeDirectory= client.removeDirectory("/invalid-path").join();
Assert.assertFalse(removeDirectory.isSuccess());
Assert.assertEquals(StatusCode.SCHEME_ERROR, removeDirectory.getCode());
Assert.assertEquals(
"Status{code = SCHEME_ERROR(code=400070), issues = [#200200 Path does not exist (S_ERROR)]}",
removeDirectory.toString()
);
}

@Test
public void createAndDeleteTest() {
String basePath = transport.getDatabase();
String dirName = "test_dir";

Status dirCreate1 = client.makeDirectory(basePath + "/" + dirName).join();
Assert.assertTrue(dirCreate1.isSuccess());

// Directory creating is idempotent
Status dirCreate2 = client.makeDirectory(basePath + "/" + dirName).join();
Assert.assertTrue(dirCreate2.isSuccess());

Result<DescribePathResult> dirEntry = client.describePath(basePath + "/" + dirName).join();
Assert.assertTrue(dirEntry.isSuccess());
Assert.assertEquals(dirName, dirEntry.getValue().getEntry().getName());

Result<ListDirectoryResult> rootList = client.listDirectory(basePath).join();
Assert.assertTrue(rootList.isSuccess());
Optional<Entry> child = rootList.getValue().getEntryChildren().stream()
.filter(e -> dirName.equals(e.getName())).findFirst();
Assert.assertTrue(child.isPresent());
Assert.assertEquals(child.get(), dirEntry.getValue().getEntry());

Status dirDelete = client.removeDirectory(basePath + "/" + dirName).join();
Assert.assertTrue(dirDelete.isSuccess());
}
}
26 changes: 26 additions & 0 deletions scheme/src/test/resources/log4j2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[%level] %d{HH:mm:ss.SSS} [%t] %logger{36} - %msg%n"/>
</Console>
</Appenders>

<Loggers>
<Logger name="io.grpc" level="warn" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="tech.ydb.core.grpc" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>

<!-- https://www.testcontainers.org/supported_docker_environment/logging_config/ -->
<Logger name="org.testcontainers" level="warn" />
<Logger name="com.github.dockerjava" level="warn"/>
<Logger name="com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.wire" level="off"/>

<Root level="debug" >
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>