code: def test_enumerable_sharding_spec(self):
      # test valid specs
  
      # test row-wise sharding
      spec = EnumerableShardingSpec(
          [
              ShardMetadata(
                  shard_offsets=[0, 0],
                  shard_sizes=[5, 5],
                  placement="cuda:0",
              ),
              ShardMetadata(
                  shard_offsets=[5, 0],
                  shard_sizes=[5, 5],
                  placement="cuda:1",
              ),
          ]
      )
      check_tensor(spec.shards, torch.rand(10, 5).size())
  
      # test row and column sharding
      spec = EnumerableShardingSpec(
          [
              ShardMetadata(
                  shard_offsets=[0, 0],
                  shard_sizes=[3, 3],
                  placement="cuda:0",
              ),
              ShardMetadata(
                  shard_offsets=[0, 3],
                  shard_sizes=[3, 3],
                  placement="cuda:1",
              ),
              ShardMetadata(
                  shard_offsets=[3, 0],
                  shard_sizes=[3, 3],
                  placement="cuda:2",
              ),
              ShardMetadata(
                  shard_offsets=[3, 3],
                  shard_sizes=[3, 3],
                  placement="cuda:3",
              ),
          ]
      )
      check_tensor(spec.shards, torch.rand(6, 6).size())
  
      # test uneven shard sizes.
      spec = EnumerableShardingSpec(
          [
              ShardMetadata(
                  shard_offsets=[0, 0],
                  shard_sizes=[2, 4],
                  placement="cuda:0",
              ),
              ShardMetadata(
                  shard_offsets=[0, 4],
                  shard_sizes=[4, 2],
                  placement="cuda:1",
              ),
              ShardMetadata(
                  shard_offsets=[2, 0],
                  shard_sizes=[4, 4],
                  placement="cuda:2",
              ),
              ShardMetadata(
                  shard_offsets=[4, 4],
                  shard_sizes=[2, 2],
                  placement="cuda:3",
              ),
          ]
      )
      check_tensor(spec.shards, torch.rand(6, 6).size())
  
      # test invalid sharding
      with self.assertRaisesRegex(
          ValueError, "Could not parse remote_device"
      ):
          ShardMetadata(
              shard_offsets=[0], shard_sizes=[1], placement="cuda:foo"
          )
  
      with self.assertRaisesRegex(
          ValueError, "same number of elements"
      ):
          ShardMetadata(
              shard_offsets=[0, 0], shard_sizes=[1], placement="cuda:0"
          )
  
      with self.assertRaisesRegex(
          ValueError, "shard_offsets should be >=0"
      ):
          ShardMetadata(
              shard_offsets=[-1, 0],
              shard_sizes=[1, 1],
              placement="cuda:0",
          )
  
      with self.assertRaisesRegex(
          ValueError, "shard_sizes should be >= 0"
      ):
          ShardMetadata(
              shard_offsets=[0, 0],
              shard_sizes=[-1, 1],
              placement="cuda:0",
          )
  
      with self.assertRaisesRegex(
          ValueError, "Empty shard list provided"
      ):
          EnumerableShardingSpec([])
  
      with self.assertRaisesRegex(
          ValueError, "Found inconsistent ranks for shards"
      ):
          EnumerableShardingSpec(
              [
                  ShardMetadata(
                      shard_offsets=[0, 0],
                      shard_sizes=[1, 1],
                      placement="cpu",
                  ),
                  ShardMetadata(
                      shard_offsets=[0, 0, 0],
                      shard_sizes=[1, 1, 1],
                      placement="cpu",
                  ),
              ]
          )
  
      with self.assertRaisesRegex(ValueError, "Shards.*overlap"):
          EnumerableShardingSpec(
              [
                  ShardMetadata(
                      shard_offsets=[0, 0],
                      shard_sizes=[3, 3],
                      placement="cpu",
                  ),
                  ShardMetadata(
                      shard_offsets=[2, 0],
                      shard_sizes=[3, 3],
                      placement="cpu",
                  ),
              ]
          )
  
      spec = EnumerableShardingSpec(
          [
              ShardMetadata(
                  shard_offsets=[0, 0],
                  shard_sizes=[5, 5],
                  placement="cuda:0",
              ),
              ShardMetadata(
                  shard_offsets=[5, 0],
                  shard_sizes=[5, 5],
                  placement="cuda:1",
              ),
          ]
      )
  
      with self.assertRaisesRegex(
          ValueError, "Rank of tensor is.*but shards rank"
      ):
          check_tensor(spec.shards, torch.rand(10, 10, 10).size())
  
      spec = EnumerableShardingSpec(
          [
              ShardMetadata(
                  shard_offsets=[0, 0],
                  shard_sizes=[5, 5],
                  placement="cuda:0",
              ),
              ShardMetadata(
                  shard_offsets=[5, 0],
                  shard_sizes=[5, 5],
                  placement="cuda:1",
              ),
          ]
      )
  
      with self.assertRaisesRegex(ValueError, "exceeds tensor dim"):
          check_tensor(spec.shards, torch.rand(10, 3).size())
  
      spec = EnumerableShardingSpec(
          [
              ShardMetadata(
                  shard_offsets=[0, 0],
                  shard_sizes=[5, 5],
                  placement="cuda:0",
              ),
              ShardMetadata(
                  shard_offsets=[5, 5],
                  shard_sizes=[5, 5],
                  placement="cuda:1",
              ),
          ]
      )
  
      with self.assertRaisesRegex(
          ValueError, "does not match tensor volume"
      ):
          check_tensor(spec.shards, torch.rand(10, 10).size())
  
imports: from typing import List, Union
  from dataclasses import dataclass
  import copy
  import torch
  from torch.testing._internal.common_utils import TestCase
  from torch.testing._internal.common_distributed import requires_nccl, skip_if_lt_x_gpu
  from torch.distributed._shard import sharded_tensor, _shard_tensor
  from torch.distributed._shard.sharding_spec import ShardingSpec, ChunkShardingSpec, DevicePlacementSpec, EnumerableShardingSpec, ShardMetadata, _infer_sharding_spec_from_shards_metadata
  from torch.distributed._shard.sharded_tensor import TensorProperties, ShardedTensor, ShardedTensorMetadata
  from torch.distributed._shard.sharding_spec._internals import check_tensor, get_split_size, get_chunked_dim_size, get_chunk_sharding_params, validate_non_overlapping_shards_metadata
  from torch.testing._internal.common_cuda import TEST_MULTIGPU
  from torch.testing._internal.common_utils import run_tests, skip_but_pass_in_sandcastle_if
  from torch.testing._internal.distributed._shard.sharded_tensor._test_st_common import _chunk_sharding_specs_list_for_test
  from torch.testing._internal.distributed._shard.sharded_tensor import ShardedTensorTestBase, with_comms
label_desc: Use image node_id 3 for calling the TestShardingSpec obj's underlying member method code with example usage: obj.test_enumerable_sharding_spec() without return types