1   /**
2    * Copyright 2007 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.io;
21  
22  import java.io.*;
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import junit.framework.TestCase;
27  
28  import org.apache.hadoop.conf.Configuration;
29  import org.apache.hadoop.hbase.HBaseConfiguration;
30  import org.apache.hadoop.hbase.HConstants;
31  import org.apache.hadoop.hbase.filter.Filter;
32  import org.apache.hadoop.hbase.filter.FilterBase;
33  import org.apache.hadoop.hbase.filter.FilterList;
34  import org.apache.hadoop.hbase.filter.PrefixFilter;
35  import org.apache.hadoop.io.Text;
36  import org.apache.hadoop.io.Writable;
37  import org.apache.hadoop.io.WritableComparator;
38  import org.junit.Assert;
39  
40  public class TestHbaseObjectWritable extends TestCase {
41  
42    @Override
43    protected void setUp() throws Exception {
44      super.setUp();
45    }
46  
47    @Override
48    protected void tearDown() throws Exception {
49      super.tearDown();
50    }
51  
52    @SuppressWarnings("boxing")
53    public void testReadObjectDataInputConfiguration() throws IOException {
54      Configuration conf = HBaseConfiguration.create();
55      // Do primitive type
56      final int COUNT = 101;
57      assertTrue(doType(conf, COUNT, int.class).equals(COUNT));
58      // Do array
59      final byte [] testing = "testing".getBytes();
60      byte [] result = (byte [])doType(conf, testing, testing.getClass());
61      assertTrue(WritableComparator.compareBytes(testing, 0, testing.length,
62         result, 0, result.length) == 0);
63      // Do unsupported type.
64      boolean exception = false;
65      try {
66        doType(conf, new File("a"), File.class);
67      } catch (UnsupportedOperationException uoe) {
68        exception = true;
69      }
70      assertTrue(exception);
71      // Try odd types
72      final byte A = 'A';
73      byte [] bytes = new byte[1];
74      bytes[0] = A;
75      Object obj = doType(conf, bytes, byte [].class);
76      assertTrue(((byte [])obj)[0] == A);
77      // Do 'known' Writable type.
78      obj = doType(conf, new Text(""), Text.class);
79      assertTrue(obj instanceof Text);
80      //List.class
81      List<String> list = new ArrayList<String>();
82      list.add("hello");
83      list.add("world");
84      list.add("universe");
85      obj = doType(conf, list, List.class);
86      assertTrue(obj instanceof List);
87      Assert.assertArrayEquals(list.toArray(), ((List)obj).toArray() );
88      //ArrayList.class
89      ArrayList<String> arr = new ArrayList<String>();
90      arr.add("hello");
91      arr.add("world");
92      arr.add("universe");
93      obj = doType(conf,  arr, ArrayList.class);
94      assertTrue(obj instanceof ArrayList);
95      Assert.assertArrayEquals(list.toArray(), ((ArrayList)obj).toArray() );
96      // Check that filters can be serialized
97      obj = doType(conf, new PrefixFilter(HConstants.EMPTY_BYTE_ARRAY),
98        PrefixFilter.class);
99      assertTrue(obj instanceof PrefixFilter);
100   }
101 
102   public void testCustomWritable() throws Exception {
103     Configuration conf = HBaseConfiguration.create();
104 
105     // test proper serialization of un-encoded custom writables
106     CustomWritable custom = new CustomWritable("test phrase");
107     Object obj = doType(conf, custom, CustomWritable.class);
108     assertTrue(obj instanceof Writable);
109     assertTrue(obj instanceof CustomWritable);
110     assertEquals("test phrase", ((CustomWritable)obj).getValue());
111 
112     // test proper serialization of a custom filter
113     CustomFilter filt = new CustomFilter("mykey");
114     FilterList filtlist = new FilterList(FilterList.Operator.MUST_PASS_ALL);
115     filtlist.addFilter(filt);
116     obj = doType(conf, filtlist, FilterList.class);
117     assertTrue(obj instanceof FilterList);
118     assertNotNull(((FilterList)obj).getFilters());
119     assertEquals(1, ((FilterList)obj).getFilters().size());
120     Filter child = ((FilterList)obj).getFilters().get(0);
121     assertTrue(child instanceof CustomFilter);
122     assertEquals("mykey", ((CustomFilter)child).getKey());
123   }
124 
125   private Object doType(final Configuration conf, final Object value,
126       final Class<?> clazz)
127   throws IOException {
128     ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
129     DataOutputStream out = new DataOutputStream(byteStream);
130     HbaseObjectWritable.writeObject(out, value, clazz, conf);
131     out.close();
132     ByteArrayInputStream bais =
133       new ByteArrayInputStream(byteStream.toByteArray());
134     DataInputStream dis = new DataInputStream(bais);
135     Object product = HbaseObjectWritable.readObject(dis, conf);
136     dis.close();
137     return product;
138   }
139 
140   public static class CustomWritable implements Writable {
141     private String value = null;
142 
143     public CustomWritable() {
144     }
145 
146     public CustomWritable(String val) {
147       this.value = val;
148     }
149 
150     public String getValue() { return value; }
151 
152     @Override
153     public void write(DataOutput out) throws IOException {
154       Text.writeString(out, this.value);
155     }
156 
157     @Override
158     public void readFields(DataInput in) throws IOException {
159       this.value = Text.readString(in);
160     }
161   }
162 
163   public static class CustomFilter extends FilterBase {
164     private String key = null;
165 
166     public CustomFilter() {
167     }
168 
169     public CustomFilter(String key) {
170       this.key = key;
171     }
172 
173     public String getKey() { return key; }
174 
175     public void write(DataOutput out) throws IOException {
176       Text.writeString(out, this.key);
177     }
178 
179     public void readFields(DataInput in) throws IOException {
180       this.key = Text.readString(in);
181     }
182   }
183 }