mirror of https://github.com/apache/jclouds.git
Issue 158: ProductItemToImage implementation and tests
This commit is contained in:
parent
7894d830bf
commit
7bcdde91a3
|
@ -18,8 +18,9 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.softlayer.compute.config;
|
package org.jclouds.softlayer.compute.config;
|
||||||
|
|
||||||
import java.util.Set;
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
import org.jclouds.compute.ComputeServiceAdapter;
|
import org.jclouds.compute.ComputeServiceAdapter;
|
||||||
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
|
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
@ -28,17 +29,16 @@ import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
|
||||||
import org.jclouds.softlayer.SoftLayerAsyncClient;
|
import org.jclouds.softlayer.SoftLayerAsyncClient;
|
||||||
import org.jclouds.softlayer.SoftLayerClient;
|
import org.jclouds.softlayer.SoftLayerClient;
|
||||||
import org.jclouds.softlayer.compute.functions.DatacenterToLocation;
|
import org.jclouds.softlayer.compute.functions.DatacenterToLocation;
|
||||||
import org.jclouds.softlayer.compute.functions.ProductItemPriceToImage;
|
|
||||||
import org.jclouds.softlayer.compute.functions.ProductItemPricesToHardware;
|
import org.jclouds.softlayer.compute.functions.ProductItemPricesToHardware;
|
||||||
|
import org.jclouds.softlayer.compute.functions.ProductItemToImage;
|
||||||
import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata;
|
import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata;
|
||||||
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
|
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
|
||||||
import org.jclouds.softlayer.domain.Datacenter;
|
import org.jclouds.softlayer.domain.Datacenter;
|
||||||
|
import org.jclouds.softlayer.domain.ProductItem;
|
||||||
import org.jclouds.softlayer.domain.ProductItemPrice;
|
import org.jclouds.softlayer.domain.ProductItemPrice;
|
||||||
import org.jclouds.softlayer.domain.VirtualGuest;
|
import org.jclouds.softlayer.domain.VirtualGuest;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import java.util.Set;
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.inject.TypeLiteral;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -54,17 +54,17 @@ public class SoftLayerComputeServiceContextModule extends
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
super.configure();
|
super.configure();
|
||||||
bind(new TypeLiteral<ComputeServiceAdapter<VirtualGuest, Set<ProductItemPrice>, ProductItemPrice, Datacenter>>() {
|
bind(new TypeLiteral<ComputeServiceAdapter<VirtualGuest, Set<ProductItemPrice>, ProductItemPrice, Datacenter>>() {})
|
||||||
}).to(SoftLayerComputeServiceAdapter.class);
|
.to(SoftLayerComputeServiceAdapter.class);
|
||||||
bind(new TypeLiteral<Function<VirtualGuest, NodeMetadata>>() {
|
bind(new TypeLiteral<Function<VirtualGuest, NodeMetadata>>() {})
|
||||||
}).to(VirtualGuestToNodeMetadata.class);
|
.to(VirtualGuestToNodeMetadata.class);
|
||||||
bind(new TypeLiteral<Function<ProductItemPrice, org.jclouds.compute.domain.Image>>() {
|
bind(new TypeLiteral<Function<ProductItem, org.jclouds.compute.domain.Image>>() {})
|
||||||
}).to(ProductItemPriceToImage.class);
|
.to(ProductItemToImage.class);
|
||||||
bind(new TypeLiteral<Function<Set<ProductItemPrice>, org.jclouds.compute.domain.Hardware>>() {
|
bind(new TypeLiteral<Function<Set<ProductItemPrice>, org.jclouds.compute.domain.Hardware>>() {})
|
||||||
}).to(ProductItemPricesToHardware.class);
|
.to(ProductItemPricesToHardware.class);
|
||||||
bind(new TypeLiteral<Function<Datacenter, Location>>() {
|
bind(new TypeLiteral<Function<Datacenter, Location>>() {})
|
||||||
}).to(DatacenterToLocation.class);
|
.to(DatacenterToLocation.class);
|
||||||
bind(new TypeLiteral<Supplier<Location>>() {
|
bind(new TypeLiteral<Supplier<Location>>() {})
|
||||||
}).to(OnlyLocationOrFirstZone.class);
|
.to(OnlyLocationOrFirstZone.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,61 +0,0 @@
|
||||||
/**
|
|
||||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. jclouds licenses this file
|
|
||||||
* to you 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 org.jclouds.softlayer.compute.functions;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.inject.Named;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Image;
|
|
||||||
import org.jclouds.compute.domain.ImageBuilder;
|
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
|
||||||
import org.jclouds.logging.Logger;
|
|
||||||
import org.jclouds.softlayer.domain.ProductItemPrice;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Singleton
|
|
||||||
public class ProductItemPriceToImage implements Function<ProductItemPrice, Image> {
|
|
||||||
@Resource
|
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
|
||||||
protected Logger logger = Logger.NULL;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Image apply(ProductItemPrice from) {
|
|
||||||
|
|
||||||
ImageBuilder builder = new ImageBuilder();
|
|
||||||
//TODO
|
|
||||||
// builder.ids(from.id + "");
|
|
||||||
// builder.name(from.name);
|
|
||||||
// builder.description(from.name);
|
|
||||||
//
|
|
||||||
// OsFamily family = null;
|
|
||||||
// try {
|
|
||||||
// family = OsFamily.fromValue(from.name);
|
|
||||||
// builder.operatingSystem(new OperatingSystem.Builder().name(from.name).family(family).build());
|
|
||||||
// } catch (IllegalArgumentException e) {
|
|
||||||
// logger.debug("<< didn't match os(%s)", from);
|
|
||||||
// }
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you 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 org.jclouds.softlayer.compute.functions;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.Image;
|
||||||
|
import org.jclouds.compute.domain.ImageBuilder;
|
||||||
|
import org.jclouds.compute.domain.OperatingSystem;
|
||||||
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.softlayer.domain.ProductItem;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jason King
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ProductItemToImage implements Function<ProductItem, Image> {
|
||||||
|
|
||||||
|
/** Pattern to capture the number of bits e.g. "a (32 bit) os" */
|
||||||
|
private static final Pattern OS_BITS_PATTERN = Pattern.compile(".*\\((\\d+) ?bit\\).*");
|
||||||
|
|
||||||
|
private static final String CENTOS = "CentOS";
|
||||||
|
private static final String DEBIAN = "Debian GNU/Linux";
|
||||||
|
private static final String FEDORA = "Fedora Release";
|
||||||
|
private static final String RHEL = "Red Hat Enterprise Linux";
|
||||||
|
private static final String UBUNTU = "Ubuntu Linux";
|
||||||
|
private static final String WINDOWS = "Windows Server";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Image apply(ProductItem from) {
|
||||||
|
|
||||||
|
//Somehow this method gets called with the correct product item.
|
||||||
|
OsFamily family = osFamily().apply(from);
|
||||||
|
Integer bits = osBits().apply(from);
|
||||||
|
OperatingSystem os = OperatingSystem.builder()
|
||||||
|
.description(from.getDescription())
|
||||||
|
.family(family)
|
||||||
|
.version(osVersion().apply(from))
|
||||||
|
.is64Bit(bits.equals(64))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return new ImageBuilder()
|
||||||
|
.id("" + from.getId())
|
||||||
|
.description(from.getDescription())
|
||||||
|
.operatingSystem(os)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the item description to determine the OSFamily
|
||||||
|
* @return the @see OsFamily or OsFamily.UNRECOGNIZED
|
||||||
|
*/
|
||||||
|
public static Function<ProductItem,OsFamily> osFamily() {
|
||||||
|
return new Function<ProductItem,OsFamily>() {
|
||||||
|
@Override
|
||||||
|
public OsFamily apply(ProductItem productItem) {
|
||||||
|
final String description = productItem.getDescription();
|
||||||
|
if ( description.startsWith(CENTOS)) return OsFamily.CENTOS;
|
||||||
|
else if( description.startsWith(DEBIAN) ) return OsFamily.DEBIAN;
|
||||||
|
else if( description.startsWith(FEDORA) ) return OsFamily.FEDORA;
|
||||||
|
else if( description.startsWith(RHEL) ) return OsFamily.RHEL;
|
||||||
|
else if( description.startsWith(UBUNTU) ) return OsFamily.UBUNTU;
|
||||||
|
else if( description.startsWith(WINDOWS) ) return OsFamily.WINDOWS;
|
||||||
|
return OsFamily.UNRECOGNIZED;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the item description to determine the os version
|
||||||
|
* @return the version
|
||||||
|
* @throws java.util.NoSuchElementException if the version cannot be determined
|
||||||
|
*/
|
||||||
|
public static Function<ProductItem,String> osVersion() {
|
||||||
|
return new Function<ProductItem,String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(ProductItem productItem) {
|
||||||
|
final String description = productItem.getDescription();
|
||||||
|
OsFamily family = osFamily().apply(productItem);
|
||||||
|
if (family.equals(OsFamily.CENTOS)) return parseVersion(description, CENTOS);
|
||||||
|
else if(family.equals(OsFamily.DEBIAN)) return parseVersion(description, DEBIAN);
|
||||||
|
else if(family.equals(OsFamily.FEDORA)) return parseVersion(description, FEDORA);
|
||||||
|
else if(family.equals(OsFamily.RHEL)) return parseVersion(description, RHEL);
|
||||||
|
else if(family.equals(OsFamily.UBUNTU)) return parseVersion(description, UBUNTU);
|
||||||
|
else if(family.equals(OsFamily.WINDOWS)) return parseVersion(description, WINDOWS);
|
||||||
|
else throw new NoSuchElementException("No os parseVersion for item:"+productItem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String parseVersion(String description, String os) {
|
||||||
|
String noOsName = description.replaceFirst(os,"").trim();
|
||||||
|
return noOsName.split(" ")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the item description to determine the number of OS bits
|
||||||
|
* Expects the number to be in parenthesis and to contain the word "bit".
|
||||||
|
* The following return 64: "A (64 bit) OS", "A (64bit) OS"
|
||||||
|
* @return the number of bits
|
||||||
|
* @throws java.util.NoSuchElementException if the number of bits cannot be determined
|
||||||
|
*/
|
||||||
|
public static Function<ProductItem,Integer> osBits() {
|
||||||
|
return new Function<ProductItem,Integer>() {
|
||||||
|
@Override
|
||||||
|
public Integer apply(ProductItem productItem) {
|
||||||
|
Matcher m = OS_BITS_PATTERN.matcher(productItem.getDescription());
|
||||||
|
if (m.matches()) {
|
||||||
|
return Integer.parseInt(m.group(1));
|
||||||
|
} else {
|
||||||
|
throw new NoSuchElementException("Cannot determine os-bits for item:"+productItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
package org.jclouds.softlayer.compute.functions;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.Image;
|
||||||
|
import org.jclouds.compute.domain.OperatingSystem;
|
||||||
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
|
import org.jclouds.softlayer.domain.ProductItem;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import static org.jclouds.softlayer.compute.functions.ProductItemToImage.*;
|
||||||
|
import static org.testng.AssertJUnit.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@code ProductItemToImage}
|
||||||
|
*
|
||||||
|
* @author Jason King
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class ProductItemToImageTest {
|
||||||
|
// Operating Systems available SEPT 2011
|
||||||
|
private static final List<String> operatingSystems = Arrays.asList(
|
||||||
|
"CentOS 5 - LAMP Install (32 bit)",
|
||||||
|
"CentOS 5 - LAMP Install (64 bit)",
|
||||||
|
"CentOS 5 - Minimal Install (32 bit)",
|
||||||
|
"CentOS 5 - Minimal Install (64 bit)",
|
||||||
|
"CentOS 6.0 - LAMP Install (32 bit)",
|
||||||
|
"CentOS 6.0 - LAMP Install (64 bit)",
|
||||||
|
"CentOS 6.0 - Minimal Install (32 bit)",
|
||||||
|
"CentOS 6.0 - Minimal Install (64 bit)",
|
||||||
|
"Debian GNU/Linux 5.0 Lenny/Stable - LAMP Install (32 bit)",
|
||||||
|
"Debian GNU/Linux 5.0 Lenny/Stable - LAMP Install (64 bit)",
|
||||||
|
"Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (32 bit)",
|
||||||
|
"Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (64 bit)",
|
||||||
|
"Fedora Release 13 (32bit) - LAMP Install",
|
||||||
|
"Fedora Release 13 (32bit) - Minimal Install",
|
||||||
|
"Fedora Release 13 (64bit) - LAMP Install",
|
||||||
|
"Fedora Release 13 (64bit) - Minimal Install",
|
||||||
|
"Fedora Release 15 (32bit) - LAMP Install",
|
||||||
|
"Fedora Release 15 (32bit) - Minimal Install",
|
||||||
|
"Fedora Release 15 (64bit) - LAMP Install",
|
||||||
|
"Fedora Release 15 (64bit) - Minimal Install",
|
||||||
|
"Red Hat Enterprise Linux 5 - LAMP Install (32 bit)",
|
||||||
|
"Red Hat Enterprise Linux 5 - LAMP Install (64 bit)",
|
||||||
|
"Red Hat Enterprise Linux 5 - Minimal Install (64 bit)",
|
||||||
|
"Red Hat Enterprise Linux 6 - LAMP Install (32 bit)",
|
||||||
|
"Red Hat Enterprise Linux 6 - LAMP Install (64 bit)",
|
||||||
|
"Red Hat Enterprise Linux 6 - Minimal Install (32 bit)",
|
||||||
|
"Red Hat Enterprise Linux 6 - Minimal Install (64 bit)",
|
||||||
|
"Ubuntu Linux 10.04 LTS Lucid Lynx - LAMP Install (32 bit)",
|
||||||
|
"Ubuntu Linux 10.04 LTS Lucid Lynx - LAMP Install (64 bit)",
|
||||||
|
"Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (32 bit)",
|
||||||
|
"Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (64 bit)",
|
||||||
|
"Ubuntu Linux 8 LTS Hardy Heron - LAMP Install (32 bit)",
|
||||||
|
"Ubuntu Linux 8 LTS Hardy Heron - LAMP Install (64 bit)",
|
||||||
|
"Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (32 bit)",
|
||||||
|
"Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)",
|
||||||
|
"Windows Server 2003 Datacenter SP2 with R2 (32 bit)",
|
||||||
|
"Windows Server 2003 Datacenter SP2 with R2 (64 bit)",
|
||||||
|
"Windows Server 2003 Enterprise SP2 with R2 (64 bit)",
|
||||||
|
"Windows Server 2003 Standard SP2 with R2 (64 bit)",
|
||||||
|
"Windows Server 2008 Datacenter Edition SP2 (32bit)",
|
||||||
|
"Windows Server 2008 Datacenter Edition SP2 (64bit)",
|
||||||
|
"Windows Server 2008 Enterprise Edition SP2 (32bit)",
|
||||||
|
"Windows Server 2008 Enterprise Edition SP2 (64bit)",
|
||||||
|
"Windows Server 2008 R2 Datacenter Edition (64bit)",
|
||||||
|
"Windows Server 2008 R2 Enterprise Edition (64bit)",
|
||||||
|
"Windows Server 2008 R2 Standard Edition (64bit)",
|
||||||
|
"Windows Server 2008 Standard Edition SP2 (32bit)",
|
||||||
|
"Windows Server 2008 Standard Edition SP2 (64bit)");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConversion() {
|
||||||
|
for( String description : operatingSystems )
|
||||||
|
{
|
||||||
|
ProductItem item = ProductItem.builder().description(description).build();
|
||||||
|
Image i = new ProductItemToImage().apply(item);
|
||||||
|
OperatingSystem os = i.getOperatingSystem();
|
||||||
|
assertNotNull(os);
|
||||||
|
assertNotNull(os.getFamily());
|
||||||
|
assertFalse(os.getFamily().equals(OsFamily.UNRECOGNIZED));
|
||||||
|
assertNotNull(os.getVersion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOsFamily() {
|
||||||
|
ProductItem item = ProductItem.builder().description("Ubuntu Linux os").build();
|
||||||
|
assertEquals(OsFamily.UBUNTU,osFamily().apply(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOsFamilyUnrecognized() {
|
||||||
|
ProductItem item = ProductItem.builder().description("not a known operating system").build();
|
||||||
|
assertEquals(OsFamily.UNRECOGNIZED,osFamily().apply(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBitsWithSpace() {
|
||||||
|
ProductItem item = ProductItem.builder().description("a (32 bit) os").build();
|
||||||
|
assertEquals(osBits().apply(item),new Integer(32));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBitsNoSpace() {
|
||||||
|
ProductItem item = ProductItem.builder().description("a (64bit) os").build();
|
||||||
|
assertEquals(osBits().apply(item),new Integer(64));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NoSuchElementException.class)
|
||||||
|
public void testBitsMissing() {
|
||||||
|
ProductItem item = ProductItem.builder().description("an os").build();
|
||||||
|
osBits().apply(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOsVersion() {
|
||||||
|
ProductItem item = ProductItem.builder().description("Windows Server 2099 (256 bit)").build();
|
||||||
|
assertEquals("2099",osVersion().apply(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NoSuchElementException.class)
|
||||||
|
public void testOsVersionMissing() {
|
||||||
|
ProductItem item = ProductItem.builder().description("asd Server ").build();
|
||||||
|
osVersion().apply(item);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue