content: package com.acgist.snail.format;
  
  import static org.junit.jupiter.api.Assertions.assertEquals;
  import static org.junit.jupiter.api.Assertions.assertFalse;
  import static org.junit.jupiter.api.Assertions.assertThrows;
  import static org.junit.jupiter.api.Assertions.assertTrue;
  
  import java.util.LinkedHashMap;
  import java.util.List;
  import java.util.Map;
  
  import org.junit.jupiter.api.Test;
  
  import com.acgist.snail.net.PacketSizeException;
  import com.acgist.snail.utils.Performance;
  
  class BEncodeEncoderTest extends Performance {
  
      @Test
      void testBEncode() throws PacketSizeException {
          final BEncodeEncoder encoder = BEncodeEncoder.newInstance();
          encoder
              .newList().put(List.of("a", "b")).flush()
              .newMap().put(Map.of("1", "2")).flush()
              .write("xxxx".getBytes());
          final String content = encoder.toString();
          this.log(content);
          assertEquals("l1:a1:bed1:11:2exxxx", content);
          final BEncodeDecoder decoder = BEncodeDecoder.newInstance(content.getBytes());
          final var list = decoder.nextList();
          list.forEach(value -> this.log(new String((byte[]) value)));
          final var map = decoder.nextMap();
          map.forEach((key, value) -> {
                  if(value instanceof Long) {
                      this.log(key + "=" + value);
                  } else {
                      this.log(key + "=" + new String((byte[]) value));
                  }
              });
          final String odd = decoder.toString();
          this.log(odd);
          assertEquals("xxxx", odd);
          assertEquals(1, map.size());
          assertEquals(2, list.size());
          final String mix = BEncodeEncoder.newInstance()
              .newList().put(List.of("a", List.of("b", "c"), Map.of("d", "e"))).flush().toString();
          this.log(mix);
          assertEquals("l1:al1:b1:ced1:d1:eee", mix);
          final var mixList = BEncodeDecoder.newInstance(mix).nextList();
          assertEquals("a", new String((byte[]) mixList.get(0)));
          final List<?> mixListList = (List<?>) mixList.get(1);
          assertEquals("b", new String((byte[]) mixListList.get(0)));
          assertEquals("c", new String((byte[]) mixListList.get(1)));
          final Map<?, ?> mixListMap = (Map<?, ?>) mixList.get(2);
          assertEquals("e", new String((byte[]) mixListMap.get("d")));
      }
      
      @Test
      void testNull() throws PacketSizeException {
          final Map<String, Object> map = new LinkedHashMap<>();
          map.put("a", 1);
          map.put("b", null);
          map.put("c", "c");
          map.put("d", "");
          map.put(null, "c");
          final String content = new String(BEncodeEncoder.encodeMap(map));
          this.log(content);
          assertEquals("d1:ai1e1:b0:1:c1:c1:d0:0:1:ce", content);
          final var decoder = BEncodeDecoder.newInstance(content);
          final var decodeMap = decoder.nextMap();
          decodeMap.forEach((key, value) -> {
              if(value instanceof Number) {
                  this.log(key + "-" + value);
              } else {
                  this.log(key + "-" + new String((byte[]) value));
              }
          });
          assertEquals(map.size(), decodeMap.size());
      }
      
      @Test
      void testEncode() {
          final String map = BEncodeEncoder.encodeMapString(Map.of("1", "2"));
          final String list = BEncodeEncoder.encodeListString(List.of("1", "2"));
          assertEquals("d1:11:2e", map);
          assertEquals("l1:11:2e", list);
      }
  
      @Test
      void testException() throws PacketSizeException {
          assertThrows(IllegalArgumentException.class, () -> BEncodeDecoder.newInstance("l"));
      }
      
      @Test
      void testEmpty() throws PacketSizeException {
          var decoder = BEncodeDecoder.newInstance("d1:11:2e");
          assertTrue(decoder.isEmpty());
          decoder.nextType();
          assertTrue(decoder.isNotEmpty());
          decoder = BEncodeDecoder.newInstance("de");
          assertEquals(BEncodeDecoder.Type.MAP, decoder.nextType());
          assertTrue(decoder.isEmpty());
          decoder = BEncodeDecoder.newInstance("le");
          assertEquals(BEncodeDecoder.Type.LIST, decoder.nextType());
          assertTrue(decoder.isEmpty());
          decoder = BEncodeDecoder.newInstance("xx");
          decoder.nextType();
          assertTrue(decoder.isEmpty());
      }
      
      @Test
      void testNext() throws PacketSizeException {
          var decoder = BEncodeDecoder.newInstance("d1:11:2e").next();
          assertFalse(decoder.isEmpty());
          decoder = BEncodeDecoder.newInstance("de").next();
          assertTrue(decoder.isEmpty());
          decoder = BEncodeDecoder.newInstance("le").next();
          assertTrue(decoder.isEmpty());
      }
      
      @Test
      void testCosted() {
          final long costed = this.costed(100000, () -> {
              BEncodeEncoder.encodeMapString(Map.of("1", "2"));
              BEncodeEncoder.encodeListString(List.of("1", "2"));
          });
          assertTrue(costed < 1000);
      }
      
  }
  