/*
 * Copyright 2012 gitblit.com.
 *
 * 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 com.gitblit.tests;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.Test;

import com.gitblit.utils.ArrayUtils;

public class ArrayUtilsTest extends GitblitUnitTest {

	@Test
	public void testArrays() {
		Object [] nullArray = null;
		assertTrue(ArrayUtils.isEmpty(nullArray));

		Object [] emptyArray = new Object[0];
		assertTrue(ArrayUtils.isEmpty(emptyArray));

		assertFalse(ArrayUtils.isEmpty(new String [] { "" }));
	}

	@Test
	public void testLists() {
		List<?> nullList = null;
		assertTrue(ArrayUtils.isEmpty(nullList));

		List<?> emptyList = new ArrayList<Object>();
		assertTrue(ArrayUtils.isEmpty(emptyList));

		List<?> list = Arrays.asList("");
		assertFalse(ArrayUtils.isEmpty(list));
	}

	@Test
	public void testSets() {
		Set<?> nullSet = null;
		assertTrue(ArrayUtils.isEmpty(nullSet));

		Set<?> emptySet = new HashSet<Object>();
		assertTrue(ArrayUtils.isEmpty(emptySet));

		Set<?> set = new HashSet<Object>(Arrays.asList(""));
		assertFalse(ArrayUtils.isEmpty(set));
	}
}