diff --git a/pom.xml b/pom.xml
index 38c2decde..b3b60323f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -137,7 +137,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.13.0
+ 3.14.0
1.8
1.8
@@ -146,6 +146,8 @@
-Xlint:-processing
+
+ -Xlint:-options
diff --git a/scheme/pom.xml b/scheme/pom.xml
index 08fa74580..1dac3046b 100644
--- a/scheme/pom.xml
+++ b/scheme/pom.xml
@@ -35,5 +35,10 @@
log4j-slf4j-impl
test
+
+ tech.ydb.test
+ ydb-junit4-support
+ test
+
diff --git a/scheme/src/main/java/tech/ydb/scheme/description/DescribePathResult.java b/scheme/src/main/java/tech/ydb/scheme/description/DescribePathResult.java
index 38439d5cb..e9da37c5b 100644
--- a/scheme/src/main/java/tech/ydb/scheme/description/DescribePathResult.java
+++ b/scheme/src/main/java/tech/ydb/scheme/description/DescribePathResult.java
@@ -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;
+ }
}
diff --git a/scheme/src/main/java/tech/ydb/scheme/description/Entry.java b/scheme/src/main/java/tech/ydb/scheme/description/Entry.java
new file mode 100644
index 000000000..4b3129d7c
--- /dev/null
+++ b/scheme/src/main/java/tech/ydb/scheme/description/Entry.java
@@ -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:
+ *
+ * - TABLE
+ * - DATABASE
+ *
+ * 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))
+ + "}";
+ }
+}
+
diff --git a/scheme/src/main/java/tech/ydb/scheme/description/EntryType.java b/scheme/src/main/java/tech/ydb/scheme/description/EntryType.java
new file mode 100644
index 000000000..86279b485
--- /dev/null
+++ b/scheme/src/main/java/tech/ydb/scheme/description/EntryType.java
@@ -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;
+ }
+}
diff --git a/scheme/src/main/java/tech/ydb/scheme/description/ListDirectoryResult.java b/scheme/src/main/java/tech/ydb/scheme/description/ListDirectoryResult.java
index d0891491f..37d7eaccb 100644
--- a/scheme/src/main/java/tech/ydb/scheme/description/ListDirectoryResult.java
+++ b/scheme/src/main/java/tech/ydb/scheme/description/ListDirectoryResult.java
@@ -1,6 +1,7 @@
package tech.ydb.scheme.description;
import java.util.List;
+import java.util.stream.Collectors;
import tech.ydb.proto.scheme.SchemeOperationProtos;
@@ -10,13 +11,20 @@
public class ListDirectoryResult extends DescribePathResult {
private final List children;
+ private final List 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 getChildren() {
return children;
}
+
+ public List getEntryChildren() {
+ return entryChildren;
+ }
}
diff --git a/scheme/src/test/java/tech/ydb/scheme/BaseIntegrationTest.java b/scheme/src/test/java/tech/ydb/scheme/BaseIntegrationTest.java
new file mode 100644
index 000000000..428aa0bb8
--- /dev/null
+++ b/scheme/src/test/java/tech/ydb/scheme/BaseIntegrationTest.java
@@ -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 describeRoot = client.describePath("/").join();
+ Assert.assertTrue(describeRoot.isSuccess());
+ DescribePathResult root = describeRoot.getValue();
+ Assert.assertEquals("/", root.getEntry().getName());
+ Assert.assertEquals("", root.getEntry().getOwner());
+
+ Result 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 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 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 dirEntry = client.describePath(basePath + "/" + dirName).join();
+ Assert.assertTrue(dirEntry.isSuccess());
+ Assert.assertEquals(dirName, dirEntry.getValue().getEntry().getName());
+
+ Result rootList = client.listDirectory(basePath).join();
+ Assert.assertTrue(rootList.isSuccess());
+ Optional 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());
+ }
+}
diff --git a/scheme/src/test/resources/log4j2.xml b/scheme/src/test/resources/log4j2.xml
new file mode 100644
index 000000000..0515e3a0a
--- /dev/null
+++ b/scheme/src/test/resources/log4j2.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file