Created RegionService and added unit tests.

Change-Id: If3735d160ead9269b8bb327a99d6dad85e5c57d0
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/RegionProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/RegionProtoTranslator.java
new file mode 100644
index 0000000..5baea7a
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/RegionProtoTranslator.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.incubator.protobuf.models.net;
+import com.google.common.base.Strings;
+import org.onosproject.incubator.protobuf.models.ProtobufUtils;
+import org.onosproject.incubator.protobuf.models.net.region.RegionEnumsProtoTranslator;
+
+
+
+import org.onosproject.cluster.NodeId;
+import org.onosproject.grpc.net.models.RegionProtoOuterClass;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.region.DefaultRegion;
+import org.onosproject.net.region.Region;
+import org.onosproject.net.region.RegionId;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * gRPC Region message to @link org.onosproject.net.region.Region conversion related utilities for region service.
+ */
+public final class RegionProtoTranslator {
+
+    /**
+     * Translates gRPC RegionProto message to {@link org.onosproject.net.region.Region}.
+     *
+     * @param region gRPC message
+     * @return {@link org.onosproject.net.region.Region}
+     */
+    public static Region translate(RegionProtoOuterClass.RegionProto region) {
+        RegionId id = RegionId.regionId(region.getRegionId());
+        Region.Type type = RegionEnumsProtoTranslator.translate(region.getType()).get();
+        String name = Strings.nullToEmpty(region.getName());
+
+        List<Set<NodeId>> masters = new ArrayList<>();
+
+        region.getMastersList().forEach(s -> {
+            Set<NodeId> nodeIdSet = new HashSet<NodeId>();
+            s.getNodeIdList().forEach(n -> {
+                nodeIdSet.add(new NodeId(n));
+            });
+            masters.add(nodeIdSet);
+        });
+
+        Annotations annots = ProtobufUtils.asAnnotations(region.getAnnotations());
+
+        return new DefaultRegion(id, name, type, annots, masters);
+    }
+
+    /**
+     * Translates {@link org.onosproject.net.region.Region} to gRPC RegionProto message.
+     *
+     * @param region {@link org.onosproject.net.region.Region}
+     * @return gRPC RegionProto message
+     */
+    public static RegionProtoOuterClass.RegionProto translate(Region region) {
+        return RegionProtoOuterClass.RegionProto.newBuilder()
+                .setRegionId(region.id().toString())
+                .setType(RegionEnumsProtoTranslator.translate(region.type()))
+                .setName(region.name().isEmpty() ? null : region.name())
+                .addAllMasters(region.masters()
+                                       .stream()
+                                       .map(s -> RegionProtoOuterClass.RegionProto.NodeIdSet
+                                               .newBuilder()
+                                               .addAllNodeId(s.stream().map(id -> {
+                                                   return id.toString();
+                                               }).collect(Collectors.toList()))
+                                               .build())
+                                       .collect(Collectors.toList()))
+                .build();
+    }
+
+    // Utility class not intended for instantiation.
+    private RegionProtoTranslator() {}
+
+}
+
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/RegionEnumsProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/RegionEnumsProtoTranslator.java
new file mode 100644
index 0000000..6f3130f
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/RegionEnumsProtoTranslator.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.incubator.protobuf.models.net.region;
+
+import org.onosproject.grpc.net.region.models.RegionEnumsProto;
+import org.onosproject.net.region.Region;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+/**
+ * gRPC RegionType message to equivalent ONOS enum conversion related utilities.
+ */
+public final class RegionEnumsProtoTranslator {
+
+    private static final Logger log = LoggerFactory.getLogger(RegionEnumsProtoTranslator.class);
+
+    /**
+     * Translates gRPC enum RegionType to Optional of ONOS enum.
+     *
+     * @param type regiontype type in gRPC enum
+     * @return Optional of equivalent ONOS enum or empty if not recognized
+     */
+    public static Optional<Region.Type> translate(RegionEnumsProto.RegionTypeProto type) {
+        switch (type) {
+            case CONTINENT:
+                return Optional.of(Region.Type.CONTINENT);
+            case COUNTRY:
+                return Optional.of(Region.Type.COUNTRY);
+            case METRO:
+                return Optional.of(Region.Type.METRO);
+            case CAMPUS:
+                return Optional.of(Region.Type.CAMPUS);
+            case BUILDING:
+                return Optional.of(Region.Type.BUILDING);
+            case DATA_CENTER:
+                return Optional.of(Region.Type.DATA_CENTER);
+            case FLOOR:
+                return Optional.of(Region.Type.FLOOR);
+            case ROOM:
+                return Optional.of(Region.Type.ROOM);
+            case RACK:
+                return Optional.of(Region.Type.RACK);
+            case LOGICAL_GROUP:
+                return Optional.of(Region.Type.LOGICAL_GROUP);
+            default:
+                log.warn("Unrecognized Type gRPC message: {}", type);
+                return Optional.empty();
+        }
+    }
+
+
+    /**
+     * Translates ONOS enum regionType to gRPC enum regionType.
+     *
+     * @param type ONOS' Type type
+     * @return equivalent gRPC message enum
+     */
+    public static RegionEnumsProto.RegionTypeProto translate(Region.Type type) {
+        switch (type) {
+            case CONTINENT:
+                return RegionEnumsProto.RegionTypeProto.CONTINENT;
+            case COUNTRY:
+                return RegionEnumsProto.RegionTypeProto.COUNTRY;
+            case METRO:
+                return RegionEnumsProto.RegionTypeProto.METRO;
+            case CAMPUS:
+                return RegionEnumsProto.RegionTypeProto.CAMPUS;
+            case BUILDING:
+                return RegionEnumsProto.RegionTypeProto.BUILDING;
+            case DATA_CENTER:
+                return RegionEnumsProto.RegionTypeProto.DATA_CENTER;
+            case FLOOR:
+                return RegionEnumsProto.RegionTypeProto.FLOOR;
+            case ROOM:
+                return RegionEnumsProto.RegionTypeProto.ROOM;
+            case RACK:
+                return RegionEnumsProto.RegionTypeProto.RACK;
+            case LOGICAL_GROUP:
+                return RegionEnumsProto.RegionTypeProto.LOGICAL_GROUP;
+            default:
+                log.warn("Unrecognized type", type);
+                throw new IllegalArgumentException("Unrecognized Type");
+        }
+    }
+
+    // Utility class not intended for instantiation.
+    private RegionEnumsProtoTranslator() {}
+}
+
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/package-info.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/package-info.java
new file mode 100644
index 0000000..459ad32
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * Utilities to handle ProtoBuf version of ONOS region models.
+ */
+package org.onosproject.incubator.protobuf.models.net.region;
diff --git a/incubator/protobuf/models/src/main/proto/net/RegionProto.proto b/incubator/protobuf/models/src/main/proto/net/RegionProto.proto
new file mode 100644
index 0000000..359008f
--- /dev/null
+++ b/incubator/protobuf/models/src/main/proto/net/RegionProto.proto
@@ -0,0 +1,24 @@
+syntax = "proto3";
+option java_package = "org.onosproject.grpc.net.models";
+
+package net;
+
+import "net/region/RegionEnumsProto.proto";
+
+// Corresponds to org.onosproject.net.Region.
+
+message RegionProto {
+    string region_id = 1;
+    net.region.RegionTypeProto type = 2;
+    string name = 3;
+
+    // List<Set<NodeId>> masters();
+    // Since masters is a list of set of NodeIds,
+    // the following message is required.
+    message NodeIdSet {
+        repeated string node_id = 1;
+    }
+
+    repeated NodeIdSet masters = 4;
+    map<string, string> annotations = 5;
+}
\ No newline at end of file
diff --git a/incubator/protobuf/models/src/main/proto/net/region/RegionEnumsProto.proto b/incubator/protobuf/models/src/main/proto/net/region/RegionEnumsProto.proto
new file mode 100644
index 0000000..c7b449d
--- /dev/null
+++ b/incubator/protobuf/models/src/main/proto/net/region/RegionEnumsProto.proto
@@ -0,0 +1,56 @@
+syntax = "proto3";
+option java_package = "org.onosproject.grpc.net.region.models";
+
+package net.region;
+
+enum RegionTypeProto {
+    /**
+     * Region represents an entire continent.
+     */
+    CONTINENT = 0;
+
+    /**
+     * Region represents an entire country.
+     */
+    COUNTRY = 1;
+
+    /**
+     * Region represents a metropolitan area.
+     */
+    METRO = 2;
+
+    /**
+     * Region represents a campus.
+     */
+    CAMPUS = 3;
+
+    /**
+     * Region represents a building.
+     */
+    BUILDING = 4;
+
+    /**
+     * Region represents a data center.
+     */
+    DATA_CENTER = 5;
+
+    /**
+     * Region represents a building floor.
+     */
+    FLOOR = 6;
+
+    /**
+     * Region represents a room.
+     */
+    ROOM = 7;
+
+    /**
+     * Region represents a rack.
+     */
+    RACK = 8;
+
+    /**
+     * Region represents a logical grouping.
+     */
+    LOGICAL_GROUP = 9;
+}
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
index 0ba9e48..4ca0e03 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.grpc.nb.net.device;
+package org.onosproject.incubator.protobuf.services.nb;
 
 
 import com.google.common.annotations.Beta;
@@ -84,7 +84,7 @@
         @Override
         public void getDeviceCount(
                 getDeviceCountRequest request,
-                StreamObserver<DeviceServiceNb.getDeviceCountReply> responseObserver) {
+                StreamObserver<getDeviceCountReply> responseObserver) {
             responseObserver
                     .onNext(getDeviceCountReply
                             .newBuilder()
@@ -97,7 +97,7 @@
         //FIXME NOTE: this will be switched to a streaming version.
         @Override
         public void getDevices(getDevicesRequest request,
-                               StreamObserver<DeviceServiceNb.getDevicesReply> responseObserver) {
+                               StreamObserver<getDevicesReply> responseObserver) {
             getDevicesReply.Builder replyBuilder = getDevicesReply.newBuilder();
             deviceService.getDevices().forEach(d -> {
                 replyBuilder.addDevice(
@@ -122,7 +122,7 @@
         @Override
         public void getAvailableDevices(getAvailableDevicesRequest request,
                                         StreamObserver
-                                                <DeviceServiceNb.getAvailableDevicesReply> responseObserver) {
+                                                <getAvailableDevicesReply> responseObserver) {
             getAvailableDevicesReply.Builder replyBuilder = getAvailableDevicesReply.newBuilder();
             deviceService.getAvailableDevices().forEach(d -> {
                 replyBuilder.addDevice(
@@ -144,7 +144,7 @@
 
         @Override
         public void getDevice(getDeviceRequest request,
-                              io.grpc.stub.StreamObserver<DeviceServiceNb.getDeviceReply> responseObserver) {
+                              io.grpc.stub.StreamObserver<getDeviceReply> responseObserver) {
             org.onosproject.net.Device device = deviceService.getDevice(
                     DeviceId.deviceId(request.getDeviceId()));
             responseObserver.onNext(
@@ -166,7 +166,7 @@
 
         @Override
         public void getRole(getRoleRequest request,
-                            StreamObserver<DeviceServiceNb.getRoleReply> responseObserver) {
+                            StreamObserver<getRoleReply> responseObserver) {
             DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
             MastershipRole role = deviceService.getRole(deviceId);
             DeviceEnumsProto.MastershipRoleProto mastershipRole =
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionService.java
new file mode 100644
index 0000000..744941f
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionService.java
@@ -0,0 +1,169 @@
+/*
+* Copyright 2017-present Open Networking Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.onosproject.incubator.protobuf.services.nb;
+import org.onosproject.incubator.protobuf.models.net.RegionProtoTranslator;
+
+import com.google.common.annotations.Beta;
+import io.grpc.Server;
+import io.grpc.ServerBuilder;
+import io.grpc.stub.StreamObserver;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.grpc.nb.net.region.RegionServiceGrpc.RegionServiceImplBase;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.region.RegionId;
+import org.onosproject.net.region.Region;
+import org.onosproject.net.region.RegionService;
+
+
+import java.io.IOException;
+
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionsRequest;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionsReply;
+
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionRequest;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionReply;
+
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionForDeviceRequest;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionForDeviceReply;
+
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionDevicesRequest;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionDevicesReply;
+
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionHostsRequest;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionHostsReply;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * A server that provides access to the methods exposed by {@link RegionService}.
+ */
+@Beta
+@Component(immediate = true)
+public class GrpcNbRegionService {
+
+    private Server server;
+    private final Logger log = getLogger(getClass());
+    private RegionServiceNBServerInternal innerClassInstance = null;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected RegionService regionService;
+
+    @Activate
+    public void activate() {
+        server = ServerBuilder.forPort(64000).addService(new RegionServiceNBServerInternal()).build();
+        try {
+            server.start();
+        } catch (IOException e) {
+            log.error("Failed to start server", e);
+            throw new RuntimeException("Failed to start server", e);
+        }
+    }
+
+    @Deactivate
+    public void deactivate() {
+        server.shutdown();
+    }
+
+    public class RegionServiceNBServerInternal extends RegionServiceImplBase {
+        /**
+         * Service for interacting with inventory of network control regions.
+         */
+        @Override
+        public void getRegions(getRegionsRequest request,
+                               StreamObserver<getRegionsReply> responseObserver) {
+            getRegionsReply.Builder builder = getRegionsReply.newBuilder();
+            regionService.getRegions().forEach(r -> {
+                builder.addRegion(RegionProtoTranslator.translate(r));
+            });
+            responseObserver.onNext(builder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getRegion(getRegionRequest request,
+                              StreamObserver<getRegionReply> responseObserver) {
+            RegionId regionId = RegionId.regionId(request.getRegionId());
+            Region region = regionService.getRegion(regionId);
+
+            getRegionReply reply = getRegionReply.newBuilder()
+                    .setRegion(RegionProtoTranslator.translate(region)).build();
+
+            responseObserver.onNext(reply);
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getRegionForDevice(getRegionForDeviceRequest request,
+                                       StreamObserver<getRegionForDeviceReply> responseObserver) {
+            DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
+            Region region = regionService.getRegionForDevice(deviceId);
+
+            getRegionForDeviceReply reply = getRegionForDeviceReply.newBuilder()
+                    .setRegion(RegionProtoTranslator.translate(region)).build();
+
+            responseObserver.onNext(reply);
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getRegionDevices(getRegionDevicesRequest request,
+                                     StreamObserver<getRegionDevicesReply> responseObserver) {
+            RegionId regionId = RegionId.regionId(request.getRegionId());
+            getRegionDevicesReply.Builder builder = getRegionDevicesReply.newBuilder();
+
+            regionService.getRegionDevices(regionId).forEach(d -> {
+                builder.addDeviceId(d.toString());
+            });
+
+            responseObserver.onNext(builder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getRegionHosts(getRegionHostsRequest request,
+                                   StreamObserver<getRegionHostsReply> responseObserver) {
+            RegionId regionId = RegionId.regionId(request.getRegionId());
+            getRegionHostsReply.Builder builder = getRegionHostsReply.newBuilder();
+
+            regionService.getRegionHosts(regionId).forEach(h -> {
+                builder.addHostId(h.toString());
+            });
+
+            responseObserver.onNext(builder.build());
+            responseObserver.onCompleted();
+        }
+    }
+
+    public RegionServiceNBServerInternal getInnerClassInstance() {
+        if (innerClassInstance == null) {
+            innerClassInstance = new RegionServiceNBServerInternal();
+        }
+        return innerClassInstance;
+    }
+}
+
+
+
+
+
+
+
diff --git a/incubator/protobuf/services/nb/src/main/proto/net/region/RegionServiceNb.proto b/incubator/protobuf/services/nb/src/main/proto/net/region/RegionServiceNb.proto
new file mode 100644
index 0000000..5498b33
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/proto/net/region/RegionServiceNb.proto
@@ -0,0 +1,53 @@
+syntax="proto3";
+option java_package = "org.onosproject.grpc.nb.net.region";
+
+package nb.net.region;
+
+import "net/RegionProto.proto";
+
+message getRegionsRequest {
+}
+
+message getRegionsReply {
+    repeated .net.RegionProto region = 1;
+}
+
+message getRegionRequest {
+    string regionId = 1;
+}
+
+message getRegionReply {
+    .net.RegionProto region = 1;
+}
+
+message getRegionForDeviceRequest {
+    string deviceId = 1;
+}
+
+message getRegionForDeviceReply {
+    .net.RegionProto region = 1;
+}
+
+message getRegionDevicesRequest {
+    string regionId = 1;
+}
+
+message getRegionDevicesReply {
+    repeated string deviceId = 1;
+}
+
+message getRegionHostsRequest {
+    string regionId = 1;
+}
+
+message getRegionHostsReply {
+    repeated string hostId = 1;
+}
+
+service RegionService {
+    rpc getRegions(getRegionsRequest) returns (getRegionsReply) {}
+    rpc getRegion(getRegionRequest) returns (getRegionReply) {}
+    rpc getRegionForDevice(getRegionForDeviceRequest) returns (getRegionForDeviceReply) {}
+    rpc getRegionDevices(getRegionDevicesRequest) returns (getRegionDevicesReply) {}
+    rpc getRegionHosts(getRegionHostsRequest) returns (getRegionHostsReply) {}
+}
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionServiceTest.java b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionServiceTest.java
new file mode 100644
index 0000000..7b93d8e
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionServiceTest.java
@@ -0,0 +1,382 @@
+/*
+* Copyright 2017-present Open Networking Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.onosproject.incubator.protobuf.services.nb;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableList;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.grpc.net.models.RegionProtoOuterClass;
+
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.cluster.NodeId.nodeId;
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.HostId.hostId;
+
+import io.grpc.ManagedChannel;
+import io.grpc.inprocess.InProcessChannelBuilder;
+import org.onosproject.net.DefaultAnnotations;
+
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+
+import org.onosproject.net.HostId;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.net.region.DefaultRegion;
+import org.onosproject.net.region.RegionListener;
+import org.onosproject.net.region.RegionService;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+
+import org.onosproject.incubator.protobuf.models.net.RegionProtoTranslator;
+import org.onosproject.grpc.nb.net.region.RegionServiceGrpc;
+import org.onosproject.grpc.nb.net.region.RegionServiceGrpc.RegionServiceBlockingStub;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb;
+import org.onosproject.incubator.protobuf.services.nb.GrpcNbRegionService.RegionServiceNBServerInternal;
+import org.onosproject.net.region.Region;
+import org.onosproject.net.region.RegionId;
+
+public class GrpcNbRegionServiceTest {
+    private static InProcessServer<GrpcNbRegionService.RegionServiceNBServerInternal> inprocessServer;
+    private static ManagedChannel channel;
+    private static RegionServiceBlockingStub blockingStub;
+
+    private static final String C1 = "C1";
+    private static final String C2 = "C2";
+    private static final String C3 = "C3";
+
+    private static final NodeId CNID_1 = nodeId(C1);
+    private static final NodeId CNID_2 = nodeId(C2);
+    private static final NodeId CNID_3 = nodeId(C3);
+
+    private static final String R1 = "R1";
+    private static final String R2 = "R2";
+    private static final String R3 = "R3";
+
+    private static final Set<NodeId> SET_C1 = ImmutableSet.of(CNID_1);
+    private static final Set<NodeId> SET_C2 = ImmutableSet.of(CNID_2);
+    private static final Set<NodeId> SET_C3 = ImmutableSet.of(CNID_3);
+
+    private static final Region REGION_1 =
+            region(R1, Region.Type.METRO, ImmutableList.of(SET_C1, SET_C2));
+    private static final Region REGION_2 =
+            region(R2, Region.Type.CAMPUS, ImmutableList.of(SET_C2, SET_C1));
+    private static final Region REGION_3 =
+            region(R3, Region.Type.CAMPUS, ImmutableList.of(SET_C3, SET_C1));
+
+    private static final Set<Region> REGION_SET =
+            ImmutableSet.of(REGION_1, REGION_2, REGION_3);
+
+    private static final String D1 = "d1";
+    private static final String D2 = "d2";
+    private static final String D3 = "d3";
+    private static final String D4 = "d4";
+    private static final String D5 = "d5";
+    private static final String D6 = "d6";
+    private static final String D7 = "d7";
+    private static final String D8 = "d8";
+    private static final String D9 = "d9";
+
+    private static final String MFR = "Mfr";
+    private static final String HW = "h/w";
+    private static final String SW = "s/w";
+    private static final String SERIAL = "ser123";
+
+    private static final DeviceId DEVID_1 = deviceId(D1);
+    private static final DeviceId DEVID_2 = deviceId(D2);
+    private static final DeviceId DEVID_3 = deviceId(D3);
+    private static final DeviceId DEVID_4 = deviceId(D4);
+    private static final DeviceId DEVID_5 = deviceId(D5);
+    private static final DeviceId DEVID_6 = deviceId(D6);
+    private static final DeviceId DEVID_7 = deviceId(D7);
+    private static final DeviceId DEVID_8 = deviceId(D8);
+    private static final DeviceId DEVID_9 = deviceId(D9);
+
+    private static final Set<DeviceId> DEVS_TRUNK =
+            ImmutableSet.of(DEVID_1, DEVID_2, DEVID_3);
+
+    private static final Set<DeviceId> DEVS_LEFT =
+            ImmutableSet.of(DEVID_4, DEVID_5, DEVID_6);
+
+    private static final Set<DeviceId> DEVS_RIGHT =
+            ImmutableSet.of(DEVID_7, DEVID_8, DEVID_9);
+
+    private static final String[][] HOST_DATA = {
+            {"AA:00:00:00:00:1A/None", R1},
+            {"AA:00:00:00:00:1B/None", R1},
+            {"AA:00:00:00:00:2A/None", R1},
+            {"AA:00:00:00:00:2B/None", R1},
+            {"AA:00:00:00:00:3A/None", R1},
+            {"AA:00:00:00:00:3B/None", R1},
+            {"AA:00:00:00:00:4A/None", R2},
+            {"AA:00:00:00:00:4B/None", R2},
+            {"AA:00:00:00:00:5A/None", R2},
+            {"AA:00:00:00:00:5B/None", R2},
+            {"AA:00:00:00:00:6A/None", R2},
+            {"AA:00:00:00:00:6B/None", R2},
+            {"AA:00:00:00:00:7A/None", R3},
+            {"AA:00:00:00:00:7B/None", R3},
+            {"AA:00:00:00:00:8A/None", R3},
+            {"AA:00:00:00:00:8B/None", R3},
+            {"AA:00:00:00:00:9A/None", R3},
+            {"AA:00:00:00:00:9B/None", R3},
+    };
+
+    private static final Map<HostId, RegionId> HOSTS = new HashMap<>();
+    private static final RegionService MOCK_REGION = new MockRegionService();
+
+    /**
+     * Returns device with given ID.
+     *
+     * @param id device ID
+     * @return device instance
+     */
+    protected static Device device(String id) {
+        return new DefaultDevice(ProviderId.NONE, deviceId(id),
+                                 Device.Type.SWITCH, MFR, HW, SW, SERIAL, null);
+    }
+
+    /**
+     * Returns a region instance with specified parameters.
+     *
+     * @param id      region id
+     * @param type    region type
+     * @param masters ordered list of master sets
+     * @return region instance
+     */
+    private static Region region(String id, Region.Type type,
+                                   List<Set<NodeId>> masters) {
+        return new DefaultRegion(RegionId.regionId(id), "Region-" + id,
+                                 type, DefaultAnnotations.EMPTY, masters);
+    }
+
+    /**
+     * Creates a map of hostIds corresponding to their regionIds.
+     *
+     */
+    private static void populateHosts() {
+        for (String[] row : HOST_DATA) {
+            HOSTS.put(hostId(row[0]), RegionId.regionId(row[1]));
+        }
+    }
+
+    public GrpcNbRegionServiceTest() {
+    }
+
+    @Test
+    public void testGetRegion() throws InterruptedException {
+
+        RegionServiceNb.getRegionRequest request = RegionServiceNb.getRegionRequest.newBuilder()
+                                                                                   .setRegionId(R1).build();
+        RegionServiceNb.getRegionReply response;
+
+        try {
+            response = blockingStub.getRegion(request);
+            Region actualRegion = RegionProtoTranslator.translate(response.getRegion());
+            assertTrue(REGION_1.equals(actualRegion));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetRegions() throws InterruptedException {
+
+        RegionServiceNb.getRegionsRequest request = RegionServiceNb.getRegionsRequest.newBuilder()
+                .build();
+        RegionServiceNb.getRegionsReply response;
+
+        try {
+            response = blockingStub.getRegions(request);
+            Set<Region> actualRegions = new HashSet<Region>();
+            for (RegionProtoOuterClass.RegionProto region : response.getRegionList()) {
+                actualRegions.add(RegionProtoTranslator.translate(region));
+            }
+            assertTrue(REGION_SET.equals(actualRegions));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetRegionForDevice() throws InterruptedException {
+
+        RegionServiceNb.getRegionForDeviceRequest request = RegionServiceNb.getRegionForDeviceRequest.newBuilder()
+                .setDeviceId(D1).build();
+        RegionServiceNb.getRegionForDeviceReply response;
+
+        try {
+            response = blockingStub.getRegionForDevice(request);
+            Region actualRegion = RegionProtoTranslator.translate(response.getRegion());
+            assertTrue(REGION_1.equals(actualRegion));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetRegionDevices() throws InterruptedException {
+
+        RegionServiceNb.getRegionDevicesRequest request = RegionServiceNb.getRegionDevicesRequest.newBuilder()
+                .setRegionId(R1).build();
+        RegionServiceNb.getRegionDevicesReply response;
+
+        try {
+            response = blockingStub.getRegionDevices(request);
+            Set<DeviceId> actualDevices = new HashSet<DeviceId>();
+            for (String deviceId : response.getDeviceIdList()) {
+                actualDevices.add(DeviceId.deviceId(deviceId));
+            }
+            assertTrue(DEVS_TRUNK.equals(actualDevices));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetRegionHosts() throws InterruptedException {
+        RegionServiceNb.getRegionHostsRequest request = RegionServiceNb.getRegionHostsRequest.newBuilder()
+                .setRegionId(R1).build();
+        RegionServiceNb.getRegionHostsReply response;
+
+        Set<HostId> expectedHosts = new HashSet<HostId>();
+
+        expectedHosts.add(HostId.hostId(HOST_DATA[0][0]));
+        expectedHosts.add(HostId.hostId(HOST_DATA[1][0]));
+        expectedHosts.add(HostId.hostId(HOST_DATA[2][0]));
+        expectedHosts.add(HostId.hostId(HOST_DATA[3][0]));
+        expectedHosts.add(HostId.hostId(HOST_DATA[4][0]));
+        expectedHosts.add(HostId.hostId(HOST_DATA[5][0]));
+
+        Set<HostId> actualHosts = new HashSet<HostId>();
+
+        try {
+            response = blockingStub.getRegionHosts(request);
+            for (String hostId : response.getHostIdList()) {
+                actualHosts.add(HostId.hostId(hostId));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        assertTrue(expectedHosts.equals(actualHosts));
+    }
+
+    @BeforeClass
+    public static void beforeClass() throws InstantiationException, IllegalAccessException, IOException {
+        inprocessServer = new InProcessServer<RegionServiceNBServerInternal>(RegionServiceNBServerInternal.class);
+
+        GrpcNbRegionService outer = new GrpcNbRegionService();
+        GrpcNbRegionService.RegionServiceNBServerInternal inner = outer.getInnerClassInstance();
+        outer.regionService = MOCK_REGION;
+        inprocessServer.addServiceToBind(inner);
+
+        inprocessServer.start();
+        channel = InProcessChannelBuilder.forName("test").directExecutor()
+                // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
+                // needing certificates.
+                .usePlaintext(true).build();
+        blockingStub = RegionServiceGrpc.newBlockingStub(channel);
+        populateHosts();
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        channel.shutdownNow();
+
+        inprocessServer.stop();
+    }
+
+    private static class MockRegionService implements RegionService {
+
+        private final Map<RegionId, Region> lookup = new HashMap<>();
+
+        MockRegionService() {
+            lookup.put(REGION_1.id(), REGION_1);
+            lookup.put(REGION_2.id(), REGION_2);
+            lookup.put(REGION_3.id(), REGION_3);
+        }
+
+        @Override
+        public Set<Region> getRegions() {
+            return REGION_SET;
+        }
+
+        @Override
+        public Region getRegion(RegionId regionId) {
+            return lookup.get(regionId);
+        }
+
+        @Override
+        public Region getRegionForDevice(DeviceId deviceId) {
+            if (DEVS_TRUNK.contains(deviceId)) {
+                return REGION_1;
+            }
+            if (DEVS_LEFT.contains(deviceId)) {
+                return REGION_2;
+            }
+            if (DEVS_RIGHT.contains(deviceId)) {
+                return REGION_3;
+            }
+            return null;
+        }
+
+        @Override
+        public Set<DeviceId> getRegionDevices(RegionId regionId) {
+            if (REGION_1.id().equals(regionId)) {
+                return DEVS_TRUNK;
+            }
+            if (REGION_2.id().equals(regionId)) {
+                return DEVS_LEFT;
+            }
+            if (REGION_3.id().equals(regionId)) {
+                return DEVS_RIGHT;
+            }
+            return Collections.emptySet();
+        }
+
+        @Override
+        public Set<HostId> getRegionHosts(RegionId regionId) {
+            Set<HostId> hosts = new HashSet<HostId>();
+            for (HostId hostId : HOSTS.keySet()) {
+                if (HOSTS.get(hostId).equals(regionId)) {
+                    hosts.add(hostId);
+                }
+            }
+            return hosts;
+        }
+
+        @Override
+        public void addListener(RegionListener listener) {
+
+        }
+
+        @Override
+        public void removeListener(RegionListener listener) {
+
+        }
+    }
+}
\ No newline at end of file