def test_object_query(self): """ JIRA ID: DAOS-4694 Test Description: Test daos object query. :avocado: tags=all,container,hw,small,full_regression,daos_object_query """ daos_cmd = DaosCommand(self.bin) errors = [] # Create a pool and a container. self.add_pool() self.add_container(self.pool) self.pool.connect() self.container.open(pool_handle=self.pool.pool.handle.value) # Prepare to write object. self.container.data_size.update(100) # Write 1 object. self.container.object_qty.update(1) # Record quantity is the number of times we write the object. self.container.record_qty.update(1) # These determine the size of the keys. Use the frequently used values. self.container.akey_size.update(4) self.container.dkey_size.update(4) # Object class defines the number of replicas, groups, etc. # 202: OC_S4, 214: OC_SX, 220: OC_RP_2G1, 221: OC_PR_2G2 # Other classes and more details are in src/include/daos_obj_class.h obj_classes = [202, 214, 220, 221] expected_replica_ones = { 200: (0, 1), 202: (0, 2), 214: (0, 8), 220: (1, 1), 221: (2, 2) } for obj_class in obj_classes: # Write object. self.container.write_objects(obj_class=obj_class) # Verify oid values. # written_data is a list of TestContainerData, which has DaosObj as # member. This is what we need to obtain oid values. obj = self.container.written_data[-1].obj obj.close() expected_oid_hi = obj.c_oid.hi expected_oid_lo = obj.c_oid.lo self.log.info("oid.hi = %s", expected_oid_hi) self.log.info("oid.lo = %s", expected_oid_lo) oid_concat = "{}.{}".format(expected_oid_hi, expected_oid_lo) kwargs = { "pool": self.pool.uuid, "svc": convert_list(self.pool.svc_ranks), "cont": self.container.uuid, "oid": oid_concat } # Call dmg object query. query_output = daos_cmd.object_query(**kwargs) actual_oid_hi = query_output["oid"][0] actual_oid_lo = query_output["oid"][1] if str(expected_oid_hi) != actual_oid_hi: errors.append( "Unexpected oid.hi! OC = {}; Expected = {}; "\ "Actual = {}".format( obj_class, expected_oid_hi, actual_oid_hi)) if str(expected_oid_lo) != actual_oid_lo: errors.append( "Unexpected oid.lo! OC = {}; Expected = {}; "\ "Actual = {}".format( obj_class, expected_oid_lo, actual_oid_lo)) # Verify replica nums and grp_nr. # For grp_nr, check to see if grp 0 -> grp_nr - 1 exists. e.g., if # grp_nr is 4, we expect to see grp: 0, grp: 1, grp: 2, grp: 3. expected_grps = set( [nr for nr in range(int(query_output["grp_nr"]))]) # For replica nums, check the total number of 1s on the left and # right because the sequence seems to be arbitrary. left = 0 right = 0 obj_groups = query_output["layout"] for obj_group in obj_groups: # Test grp_nr. if int(obj_group["grp"]) not in expected_grps: errors.append( "Unexpected grp sequence! OC = {}; {} is not in "\ "{}".format(obj_class, obj_group["grp"], expected_grps)) else: expected_grps.remove(int(obj_group["grp"])) # Accumulate replica 1s. replica_tuples = obj_group["replica"] for replica_tuple in replica_tuples: left += int(replica_tuple[0]) right += int(replica_tuple[1]) # Test replica's left and right 1 counts are expected. actual_replica_ones = (left, right) if expected_replica_ones[obj_class] != actual_replica_ones: errors.append( "Unexpected replica values! OC = {}; Expected = {}; "\ "Actual = {}".format( obj_class, expected_replica_ones[obj_class], actual_replica_ones)) # Check that we have seen all values in 0 -> grp_nr - 1. if expected_grps: errors.append( "There is grp_nr we haven't seen! OC = {}; {}".format( obj_class, expected_grps)) if errors: self.log.info("--- Error List ---") for error in errors: self.log.info(error) self.fail("Error found!")
def test_object_query(self): """JIRA ID: DAOS-4694 Test Description: Test daos object query. :avocado: tags=all,full_regression :avocado: tags=control :avocado: tags=daos_object_query """ daos_cmd = DaosCommand(self.bin) errors = [] # Create a pool and a container. Specify --oclass, which will be used # when writing object. self.add_pool() self.add_container(self.pool) self.pool.connect() self.container.open(pool_handle=self.pool.pool.handle.value) # Prepare to write object. self.container.data_size.update(100) # Write 1 object. self.container.object_qty.update(1) # Record quantity is the number of times we write the object. self.container.record_qty.update(1) # These determine the size of the keys. Use the frequently used values. self.container.akey_size.update(4) self.container.dkey_size.update(4) # Object class defines the number of replicas, groups, etc. # Other classes and more details are in src/include/daos_obj_class.h # This mapping could change, so check daos_obj_class.h when this test # fails. class_name_to_code = { "S1": 16777217, "RP_2G1": 134217729, "RP_2G2": 134217730, "RP_3G1": 150994945 } class_name_to_group_num = { "S1": 1, "RP_2G1": 1, "RP_2G2": 2, "RP_3G1": 1 } class_name_to_replica_rows = { "S1": 1, "RP_2G1": 2, "RP_2G2": 4, "RP_3G1": 3 } # Write object. Use the same object class as the one used during the # container create. We need the corresponding integer value for # write_objects. class_name = self.container.oclass.value obj_class = class_name_to_code[class_name] self.container.write_objects(obj_class=obj_class) # Verify oid values. First, get the expected oid hi and lo. # written_data is a list of TestContainerData, which has DaosObj as # member. This is what we need to obtain oid values. obj = self.container.written_data[-1].obj obj.close() expected_oid_hi = obj.c_oid.hi expected_oid_lo = obj.c_oid.lo self.log.info("oid.hi = %s", expected_oid_hi) self.log.info("oid.lo = %s", expected_oid_lo) oid_concat = "{}.{}".format(expected_oid_hi, expected_oid_lo) kwargs = { "pool": self.pool.uuid, "cont": self.container.uuid, "oid": oid_concat } # Call daos object query and verify oid values. query_output = daos_cmd.object_query(**kwargs) actual_oid_hi = query_output["oid"][0] actual_oid_lo = query_output["oid"][1] if str(expected_oid_hi) != actual_oid_hi: errors.append( "Unexpected oid.hi! OC = {}; Expected = {}; "\ "Actual = {}".format( obj_class, expected_oid_hi, actual_oid_hi)) if str(expected_oid_lo) != actual_oid_lo: errors.append( "Unexpected oid.lo! OC = {}; Expected = {}; "\ "Actual = {}".format( obj_class, expected_oid_lo, actual_oid_lo)) # Verify grp_nr. Expected group number is the number that comes after G. expected_group_num = class_name_to_group_num[class_name] actual_group_num = query_output["grp_nr"] if str(expected_group_num) != actual_group_num: errors.append( "Unexpected grp_nr! Class = {}; Expected = {}; "\ "Actual = {}".format( class_name, expected_group_num, actual_group_num)) # Verify number of replica rows, which should be the multiplication of # replication (num before G) and group number (num after G). For S1, # there's 1 group and no replication, so the row count should be 1. expected_replica_rows = class_name_to_replica_rows[class_name] obj_layout = query_output["layout"] actual_replica_rows = 0 actual_group_rows = 0 for layout in obj_layout: actual_replica_rows += len(layout["replica"]) actual_group_rows += 1 if expected_replica_rows != actual_replica_rows: errors.append( "Unexpected replica row count! Class = {}; Expected = {}; "\ "Actual = {}".format( class_name, expected_replica_rows, actual_replica_rows)) # Also verify the number of group rows; rows that start with "grp". if expected_group_num != actual_group_rows: errors.append( "Unexpected group row count! Class = {}; Expected = {}; "\ "Actual = {}".format( class_name, expected_group_num, actual_group_rows)) # Print accumulated errors. if errors: self.log.info("--- Error List ---") for error in errors: self.log.info(error) self.fail("Error found!")