Skip to content

Commit 9ab3410

Browse files
authored
Merge pull request #378 from alex268/scheme_client_updates
Scheme client updates
2 parents 133b2c0 + 7302ca9 commit 9ab3410

File tree

8 files changed

+295
-1
lines changed

8 files changed

+295
-1
lines changed

pom.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@
137137
<plugin>
138138
<groupId>org.apache.maven.plugins</groupId>
139139
<artifactId>maven-compiler-plugin</artifactId>
140-
<version>3.13.0</version>
140+
<version>3.14.0</version>
141141
<configuration>
142142
<target>1.8</target>
143143
<source>1.8</source>
@@ -146,6 +146,8 @@
146146
<!-- Silence warning "No processor claimed any of these annotations". One of the
147147
annotations that would trigger it is org.junit.jupiter.api.Test -->
148148
<arg>-Xlint:-processing</arg>
149+
<!-- Silence warnning "source value 8 is obsolete and will be removed in a future release" -->
150+
<arg>-Xlint:-options</arg>
149151
</compilerArgs>
150152
</configuration>
151153
</plugin>

scheme/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,10 @@
3535
<artifactId>log4j-slf4j-impl</artifactId>
3636
<scope>test</scope>
3737
</dependency>
38+
<dependency>
39+
<groupId>tech.ydb.test</groupId>
40+
<artifactId>ydb-junit4-support</artifactId>
41+
<scope>test</scope>
42+
</dependency>
3843
</dependencies>
3944
</project>

scheme/src/main/java/tech/ydb/scheme/description/DescribePathResult.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,23 @@
88
*/
99
public class DescribePathResult {
1010
private final SchemeOperationProtos.Entry self;
11+
private final Entry entry;
1112

1213
protected DescribePathResult(SchemeOperationProtos.Entry self) {
1314
this.self = self;
15+
this.entry = new Entry(self);
1416
}
1517

1618
public DescribePathResult(SchemeOperationProtos.DescribePathResult result) {
1719
this(result.getSelf());
1820
}
1921

22+
@Deprecated
2023
public SchemeOperationProtos.Entry getSelf() {
2124
return self;
2225
}
26+
27+
public Entry getEntry() {
28+
return entry;
29+
}
2330
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package tech.ydb.scheme.description;
2+
3+
import java.util.Objects;
4+
5+
import tech.ydb.proto.scheme.SchemeOperationProtos;
6+
7+
/**
8+
*
9+
* @author Aleksandr Gorshenin
10+
*/
11+
public class Entry {
12+
private final String name;
13+
private final String owner;
14+
private final EntryType type;
15+
private final long sizeBytes;
16+
17+
public Entry(SchemeOperationProtos.Entry pb) {
18+
this.name = pb.getName();
19+
this.owner = pb.getOwner();
20+
this.type = EntryType.fromCode(pb.getTypeValue());
21+
this.sizeBytes = pb.getSizeBytes();
22+
}
23+
24+
/**
25+
* @return Name of scheme entry (dir2 of /dir1/dir2)
26+
*/
27+
public String getName() {
28+
return this.name;
29+
}
30+
31+
/**
32+
* @return SID (Security ID) of user or group
33+
*/
34+
public String getOwner() {
35+
return this.owner;
36+
}
37+
38+
/**
39+
* Approximate size of entry in bytes. Currently filled for:
40+
* <ul>
41+
* <li> TABLE </li>
42+
* <li> DATABASE </li>
43+
* </ul>
44+
* Empty (zero) in other cases.
45+
*
46+
* @return Size of entry in bytes
47+
*/
48+
public long getSizeBytes() {
49+
return this.sizeBytes;
50+
}
51+
52+
public EntryType getType() {
53+
return this.type;
54+
}
55+
56+
@Override
57+
public int hashCode() {
58+
return Objects.hash(name, owner, type, sizeBytes);
59+
}
60+
61+
@Override
62+
public boolean equals(Object obj) {
63+
if (this == obj) {
64+
return true;
65+
}
66+
if (obj == null || obj.getClass() != Entry.class) {
67+
return false;
68+
}
69+
Entry o = (Entry) obj;
70+
return Objects.equals(name, o.name)
71+
&& Objects.equals(owner, o.owner)
72+
&& type == o.type
73+
&& sizeBytes == o.sizeBytes;
74+
}
75+
76+
@Override
77+
public String toString() {
78+
return "Entry{name='" + name + "'"
79+
+ (owner == null || owner.isEmpty() ? "" : ", owner='" + owner + "'")
80+
+ ", type=" + type
81+
+ (sizeBytes == 0 ? "" : ", size=" + Long.toUnsignedString(sizeBytes))
82+
+ "}";
83+
}
84+
}
85+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package tech.ydb.scheme.description;
2+
3+
/**
4+
*
5+
* @author Aleksandr Gorshenin
6+
*/
7+
public enum EntryType {
8+
UNSPECIFIED(0),
9+
10+
DIRECTORY(1),
11+
TABLE(2),
12+
PERS_QUEUE_GROUP(3),
13+
DATABASE(4),
14+
RTMR_VOLUME(5),
15+
BLOCK_STORE_VOLUME(6),
16+
COORDINATION_NODE(7),
17+
COLUMN_STORE(12),
18+
COLUMN_TABLE(13),
19+
SEQUENCE(15),
20+
REPLICATION(16),
21+
TOPIC(17),
22+
EXTERNAL_TABLE(18),
23+
EXTERNAL_DATA_SOURCE(19),
24+
VIEW(20);
25+
26+
private final int code;
27+
28+
EntryType(int code) {
29+
this.code = code;
30+
}
31+
32+
public int getCode() {
33+
return code;
34+
}
35+
36+
public static EntryType fromCode(int code) {
37+
for (EntryType type: EntryType.values()) {
38+
if (code == type.code) {
39+
return type;
40+
}
41+
}
42+
return UNSPECIFIED;
43+
}
44+
}

scheme/src/main/java/tech/ydb/scheme/description/ListDirectoryResult.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package tech.ydb.scheme.description;
22

33
import java.util.List;
4+
import java.util.stream.Collectors;
45

56
import tech.ydb.proto.scheme.SchemeOperationProtos;
67

@@ -10,13 +11,20 @@
1011
public class ListDirectoryResult extends DescribePathResult {
1112

1213
private final List<SchemeOperationProtos.Entry> children;
14+
private final List<Entry> entryChildren;
1315

1416
public ListDirectoryResult(SchemeOperationProtos.ListDirectoryResult result) {
1517
super(result.getSelf());
1618
this.children = result.getChildrenList();
19+
this.entryChildren = result.getChildrenList().stream().map(Entry::new).collect(Collectors.toList());
1720
}
1821

22+
@Deprecated
1923
public List<SchemeOperationProtos.Entry> getChildren() {
2024
return children;
2125
}
26+
27+
public List<Entry> getEntryChildren() {
28+
return entryChildren;
29+
}
2230
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package tech.ydb.scheme;
2+
3+
import java.util.Optional;
4+
5+
import org.junit.AfterClass;
6+
import org.junit.Assert;
7+
import org.junit.ClassRule;
8+
import org.junit.Test;
9+
10+
import tech.ydb.core.Result;
11+
import tech.ydb.core.Status;
12+
import tech.ydb.core.StatusCode;
13+
import tech.ydb.scheme.description.DescribePathResult;
14+
import tech.ydb.scheme.description.Entry;
15+
import tech.ydb.scheme.description.EntryType;
16+
import tech.ydb.scheme.description.ListDirectoryResult;
17+
import tech.ydb.test.junit4.GrpcTransportRule;
18+
19+
/**
20+
*
21+
* @author Aleksandr Gorshenin
22+
*/
23+
public class BaseIntegrationTest {
24+
@ClassRule
25+
public final static GrpcTransportRule transport = new GrpcTransportRule();
26+
27+
private final static SchemeClient client = SchemeClient.newClient(transport).build();
28+
29+
@AfterClass
30+
public static void close() {
31+
client.close();
32+
}
33+
34+
@Test
35+
public void rootPathTest() {
36+
Result<DescribePathResult> describeRoot = client.describePath("/").join();
37+
Assert.assertTrue(describeRoot.isSuccess());
38+
DescribePathResult root = describeRoot.getValue();
39+
Assert.assertEquals("/", root.getEntry().getName());
40+
Assert.assertEquals("", root.getEntry().getOwner());
41+
42+
Result<ListDirectoryResult> listRoot = client.listDirectory("/").join();
43+
Assert.assertTrue(listRoot.isSuccess());
44+
ListDirectoryResult listResult = listRoot.getValue();
45+
Assert.assertEquals("/", listResult.getEntry().getName());
46+
Assert.assertEquals("", listResult.getEntry().getOwner());
47+
Assert.assertEquals("/", listResult.getEntry().getName());
48+
Assert.assertEquals(0l, listResult.getEntry().getSizeBytes());
49+
Assert.assertEquals(EntryType.DIRECTORY, listResult.getEntry().getType());
50+
Assert.assertEquals("Entry{name='/', type=DIRECTORY}", listResult.getEntry().toString());
51+
52+
53+
Assert.assertEquals(1, listResult.getEntryChildren().size());
54+
listResult.getEntryChildren().get(0);
55+
Entry firstChild = listResult.getEntryChildren().get(0);
56+
Assert.assertTrue(transport.getDatabase().startsWith("/" + firstChild.getName()));
57+
Assert.assertEquals(EntryType.DIRECTORY, firstChild.getType());
58+
}
59+
60+
@Test
61+
public void invalidPathTest() {
62+
Result<DescribePathResult> describeInvalid = client.describePath("/invalid-path").join();
63+
Assert.assertFalse(describeInvalid.isSuccess());
64+
Assert.assertEquals(StatusCode.SCHEME_ERROR, describeInvalid.getStatus().getCode());
65+
Assert.assertEquals(
66+
"Status{code = SCHEME_ERROR(code=400070), issues = [Root not found (S_ERROR)]}",
67+
describeInvalid.getStatus().toString()
68+
);
69+
70+
Result<ListDirectoryResult> listInvalid = client.listDirectory("/invalid-path").join();
71+
Assert.assertFalse(listInvalid.isSuccess());
72+
Assert.assertEquals(StatusCode.SCHEME_ERROR, listInvalid.getStatus().getCode());
73+
Assert.assertEquals(
74+
"Status{code = SCHEME_ERROR(code=400070), issues = [Root not found (S_ERROR)]}",
75+
listInvalid.getStatus().toString()
76+
);
77+
78+
Status makeDirectory= client.makeDirectory("/invalid-path").join();
79+
Assert.assertFalse(makeDirectory.isSuccess());
80+
Assert.assertEquals(StatusCode.BAD_REQUEST, makeDirectory.getCode());
81+
82+
Status removeDirectory= client.removeDirectory("/invalid-path").join();
83+
Assert.assertFalse(removeDirectory.isSuccess());
84+
Assert.assertEquals(StatusCode.SCHEME_ERROR, removeDirectory.getCode());
85+
Assert.assertEquals(
86+
"Status{code = SCHEME_ERROR(code=400070), issues = [#200200 Path does not exist (S_ERROR)]}",
87+
removeDirectory.toString()
88+
);
89+
}
90+
91+
@Test
92+
public void createAndDeleteTest() {
93+
String basePath = transport.getDatabase();
94+
String dirName = "test_dir";
95+
96+
Status dirCreate1 = client.makeDirectory(basePath + "/" + dirName).join();
97+
Assert.assertTrue(dirCreate1.isSuccess());
98+
99+
// Directory creating is idempotent
100+
Status dirCreate2 = client.makeDirectory(basePath + "/" + dirName).join();
101+
Assert.assertTrue(dirCreate2.isSuccess());
102+
103+
Result<DescribePathResult> dirEntry = client.describePath(basePath + "/" + dirName).join();
104+
Assert.assertTrue(dirEntry.isSuccess());
105+
Assert.assertEquals(dirName, dirEntry.getValue().getEntry().getName());
106+
107+
Result<ListDirectoryResult> rootList = client.listDirectory(basePath).join();
108+
Assert.assertTrue(rootList.isSuccess());
109+
Optional<Entry> child = rootList.getValue().getEntryChildren().stream()
110+
.filter(e -> dirName.equals(e.getName())).findFirst();
111+
Assert.assertTrue(child.isPresent());
112+
Assert.assertEquals(child.get(), dirEntry.getValue().getEntry());
113+
114+
Status dirDelete = client.removeDirectory(basePath + "/" + dirName).join();
115+
Assert.assertTrue(dirDelete.isSuccess());
116+
}
117+
}

scheme/src/test/resources/log4j2.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Configuration status="WARN">
3+
<Appenders>
4+
<Console name="Console" target="SYSTEM_OUT">
5+
<PatternLayout pattern="[%level] %d{HH:mm:ss.SSS} [%t] %logger{36} - %msg%n"/>
6+
</Console>
7+
</Appenders>
8+
9+
<Loggers>
10+
<Logger name="io.grpc" level="warn" additivity="false">
11+
<AppenderRef ref="Console"/>
12+
</Logger>
13+
<Logger name="tech.ydb.core.grpc" level="trace" additivity="false">
14+
<AppenderRef ref="Console"/>
15+
</Logger>
16+
17+
<!-- https://www.testcontainers.org/supported_docker_environment/logging_config/ -->
18+
<Logger name="org.testcontainers" level="warn" />
19+
<Logger name="com.github.dockerjava" level="warn"/>
20+
<Logger name="com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.wire" level="off"/>
21+
22+
<Root level="debug" >
23+
<AppenderRef ref="Console"/>
24+
</Root>
25+
</Loggers>
26+
</Configuration>

0 commit comments

Comments
 (0)